From 680e862e76fcf0bcf847c5c5d527be2e70dbfe10 Mon Sep 17 00:00:00 2001 From: Dilawar Singh Date: Tue, 10 Mar 2020 17:16:26 +0530 Subject: [PATCH 1/7] Squashed 'moose-core/' changes from 2062ab231..280dfa54d 280dfa54d Adds Test Coverage (#394) 4de9cc74e Combined 391+386+337+281 (#392) 9489bbdda Named variables in Function expression (#390) ec9e209b5 Fixes regression caused by #387 (#389) d3fe5e9fc Thread-safe and more performant parser based on ExprTK (#387) dd2a902c9 Update to install instructions... (#386) ea443fea9 Add pip support to build system | `pip install pymoose` will work on all platforms (#385) e7cd7c0ec Hotfix | Packaging issues on OSX (#383) 16cd0d6bb Merge pull request #381 from hrani/master e08492bca kkit: channel's permeability converted from uM to mM, writeSBML: channel is written as MMenz and Km in kinetics law updated based on no. substrate 60fd143c7 while writting genesis file compartment is added as a group 770ab5322 readsbml: compartment name & Id is mapped to the values in comptSbmlidMooseIdMap,writesbml: added annotation for cplxpool, autolayout for cspaccemodels (#374) 8d68b6dc9 upi commit dec 2019 (#380) 3d2d55487 writekkit: cleanup eb88a23a0 readSBML:compartment name and id is mapped, in Assignment rule a check made for integer in the expression,writeSBML:added autlayout which was required for writting cspace model while writting from command line, for cplxpool's x-y coordinates and motor/diff constant are added,fixXreac: check to see if object exist before _moose.connect, case where object is deleted but _xref_ annotation info field still hold the reference 660c91d07 Merge pull request #375 from keszybz/string-comparison 137e34831 neuroml: do not use "is" with strings git-subtree-dir: moose-core git-subtree-split: 280dfa54daf002ec2c53921b5549117fc59c2027 --- .ci/Dockerfile | 8 + .ci/build_wheels_osx.sh | 94 + .ci/coverage.sh | 8 + {.travis => .ci}/deploy_pypi.sh | 0 {.travis => .ci}/download_and_run_doqcs.sh | 0 {.travis => .ci}/run_pylint.sh | 0 .ci/travis_build_linux.sh | 80 + {.travis => .ci}/travis_build_osx.sh | 22 +- .ci/travis_prepare_linux.sh | 31 + {.travis => .ci}/travis_prepare_osx.sh | 0 .github/main.workflow | 15 + .github/workflows/pymoose.yml | 27 + .gitlab-ci.yml | 22 + .travis.yml | 46 +- .travis/travis_build_linux.sh | 75 - .travis/travis_prepare_linux.sh | 48 - CMakeLists.txt | 326 +- CheckCXXCompiler.cmake | 26 +- INSTALL.md | 67 +- MANIFEST.in | 36 + basecode/EpFunc.cpp | 5 +- basecode/EpFunc.h | 286 +- basecode/FieldElement.h | 3 +- basecode/FieldElementFinfo.cpp | 33 +- basecode/OpFunc.h | 272 +- basecode/OpFuncBase.h | 630 +- basecode/SetGet.cpp | 129 +- basecode/SetGet.h | 18 +- basecode/global.cpp | 17 + basecode/global.h | 7 +- basecode/main.cpp | 98 +- benchmarks/CMakeLists.txt | 29 - benchmarks/benchmarks.cpp | 40 - benchmarks/kineticMarks.cpp | 22 - biophysics/CMakeLists.txt | 12 +- biophysics/CaConcBase.cpp | 456 +- biophysics/MarkovChannel.cpp | 288 +- biophysics/MarkovGslSolver.cpp | 350 - biophysics/MarkovGslSolver.h | 78 - biophysics/MarkovOdeSolver.cpp | 439 + biophysics/MarkovOdeSolver.h | 88 + biophysics/MarkovSolver.cpp | 929 +- biophysics/Neuron.cpp | 610 +- biophysics/ReadCell.cpp | 2 +- biophysics/testBiophysics.cpp | 95 +- builtins/CMakeLists.txt | 15 +- builtins/Func.cpp | 696 - builtins/Func.h | 121 - builtins/Function.cpp | 890 +- builtins/Function.h | 123 +- builtins/InputVariable.cpp | 3 +- builtins/MooseParser.cpp | 413 +- builtins/MooseParser.h | 148 +- builtins/Table.h | 4 + builtins/Variable.cpp | 29 +- builtins/Variable.h | 95 +- {cmake_modules => cmake}/FindGSL.cmake | 6 +- {cmake_modules => cmake}/FindLIBSBML.cmake | 0 {cmake_modules => cmake}/FindLibXML2.cmake | 0 {cmake_modules => cmake}/FindPyQt.py | 0 {cmake_modules => cmake}/FindPyQt4.cmake | 0 {cmake_modules => cmake}/FindReadline.cmake | 0 {cmake_modules => cmake}/FindSIP.cmake | 0 {cmake_modules => cmake}/FindSIP.py | 0 {cmake_modules => cmake}/FindSphinx.cmake | 0 {cmake_modules => cmake}/FindTermcap.cmake | 0 .../GetGitRevisionDescription.cmake | 0 .../GetGitRevisionDescription.cmake.in | 0 {cmake_modules => cmake}/GetRevision.cmake | 0 {cmake_modules => cmake}/Pinfo.plist | 0 {cmake_modules => cmake}/SIPMacros.cmake | 0 cmake_modules/FindNumPy.cmake | 94 - devel/CMakeLists.txt | 14 + devel/_conftest.py | 25 + devel/docker/centos/Dockerfile | 26 + devel/docker/centos/Makefile | 18 + devel/docker/opensuse/Dockerfile | 18 + devel/docker/opensuse/Makefile | 18 + devel/docker/travis/Dockerfile | 22 + devel/docker/travis/Makefile | 20 + devel/docker/wheel/Dockerfile | 23 + devel/docker/wheel/Makefile | 16 + devel/docker/wheel/README.md | 3 + devel/docker/wheel/build_wheels.sh | 67 + devel/docker/wheel/test_and_upload.sh | 67 + .../testDisabled_socket_streamer_tcp.py | 0 devel/fixme/test_81_synTrigCICR.py | 97 + .../test_82_multiscale_gluR_phosph_3compt.py | 111 + ...test_long_sbml+exp+parser+multithreaded.py | 580 + .../fixme}/test_socket_streamer_multitab.py | 0 .../fixme}/test_socket_streamer_uds.py | 0 {tests => devel}/issues/hsolve/README | 0 .../issues/hsolve/compare_moose_nrn.py | 0 {tests => devel}/issues/hsolve/h10.CNG.hoc | 0 .../issues/hsolve/h10.CNG.moose.py | 0 {tests => devel}/issues/hsolve/h10.CNG.swc | 0 .../issues/hsolve/run_h10.CNG.hoc | 0 {tests => devel}/issues/issue_124.py | 0 {tests => devel}/issues/issue_239.py | 0 {tests => devel}/issues/issue_34.py | 0 {tests => devel}/issues/issue_45.py | 0 {tests => devel}/issues/issue_47.py | 0 {tests => devel}/issues/issue_93.py | 0 diffusion/ConcChanInfo.h | 34 +- diffusion/Dsolve.cpp | 366 +- diffusion/Dsolve.h | 3 + diffusion/FastMatrixElim.h | 182 +- diffusion/testDiffusion.cpp | 1651 +- .../boost/numeric/bindings/lapack/gees.hpp | 9 - .../boost/numeric/bindings/lapack/gesdd.hpp | 18 +- .../boost/numeric/bindings/lapack/gesvd.hpp | 12 +- .../boost/numeric/bindings/lapack/ormqr.hpp | 2 +- .../boost/numeric/bindings/lapack/syev.hpp | 4 - external/exprtk/exprtk.hpp | 38962 ++++++++++++++++ external/libsoda/.travis.yml | 25 + external/libsoda/CMakeLists.txt | 15 + external/libsoda/LICENSE | 21 + external/libsoda/LSODA.cpp | 2268 + external/libsoda/LSODA.h | 158 + external/libsoda/README.md | 13 + external/libsoda/benchmark_LSODA.cpp | 248 + external/libsoda/helper.h | 24 + external/libsoda/run_benchmark.sh | 6 + external/libsoda/test_LSODA.cpp | 199 + external/muparser/CMakeLists.txt | 11 - external/muparser/License.txt | 35 - external/muparser/Makefile.in | 368 - external/muparser/include/muParser.h | 129 - external/muparser/include/muParserBase.h | 317 - external/muparser/include/muParserBytecode.h | 141 - external/muparser/include/muParserCallback.h | 118 - external/muparser/include/muParserDLL.h | 241 - external/muparser/include/muParserDef.h | 368 - external/muparser/include/muParserError.h | 176 - external/muparser/include/muParserFixes.h | 62 - external/muparser/include/muParserInt.h | 140 - external/muparser/include/muParserStack.h | 125 - .../muparser/include/muParserTemplateMagic.h | 113 - external/muparser/include/muParserTest.h | 214 - external/muparser/include/muParserToken.h | 401 - .../muparser/include/muParserTokenReader.h | 161 - external/muparser/src/muParser.cpp | 444 - external/muparser/src/muParserBase.cpp | 1779 - external/muparser/src/muParserBytecode.cpp | 588 - external/muparser/src/muParserCallback.cpp | 463 - external/muparser/src/muParserDLL.cpp | 1096 - external/muparser/src/muParserError.cpp | 337 - external/muparser/src/muParserInt.cpp | 280 - external/muparser/src/muParserTest.cpp | 1552 - external/muparser/src/muParserTokenReader.cpp | 968 - external/tinyexpr/.travis.yml | 7 + external/tinyexpr/CMakeLists.txt | 64 + external/tinyexpr/CONTRIBUTING | 10 + external/tinyexpr/LICENSE | 20 + external/tinyexpr/README.md | 319 + external/tinyexpr/benchmark.c | 125 + external/tinyexpr/doc/e1.dot | 8 + external/tinyexpr/doc/e1.png | Bin 0 -> 11883 bytes external/tinyexpr/doc/e2.dot | 5 + external/tinyexpr/doc/e2.png | Bin 0 -> 10032 bytes external/tinyexpr/example.c | 10 + external/tinyexpr/example2.c | 42 + external/tinyexpr/example3.c | 35 + external/tinyexpr/minctest.h | 128 + external/tinyexpr/test.c | 825 + external/tinyexpr/tinyexpr.c | 1108 + external/tinyexpr/tinyexpr.h | 86 + hsolve/HSolveInterface.cpp | 12 +- kinetics/Pool.cpp | 8 +- kinetics/PoolBase.cpp | 9 +- kinetics/PoolBase.h | 1 + kinetics/ReadKkit.cpp | 2633 +- kinetics/ReadKkit.h | 453 +- kinetics/lookupVolumeFromMesh.cpp | 216 +- ksolve/BoostSys.cpp | 2 +- ksolve/CMakeLists.txt | 10 +- ksolve/FuncRateTerm.h | 50 +- ksolve/FuncTerm.cpp | 117 +- ksolve/FuncTerm.h | 81 +- ksolve/Gsolve.cpp | 68 +- ksolve/Gsolve.h | 6 +- ksolve/GssaVoxelPools.cpp | 16 +- ksolve/GssaVoxelPools.h | 10 +- ksolve/KinSparseMatrix.cpp | 442 +- ksolve/KinSparseMatrix.h | 94 +- ksolve/Ksolve.cpp | 145 +- ksolve/Ksolve.h | 14 +- ksolve/RateTerm.cpp | 42 +- ksolve/RateTerm.h | 1087 +- ksolve/Stoich.cpp | 55 +- ksolve/Stoich.h | 4 + ksolve/VoxelPools.cpp | 357 +- ksolve/VoxelPools.h | 17 +- ksolve/VoxelPoolsBase.cpp | 5 +- ksolve/ZombieBufPool.cpp | 40 +- ksolve/ZombieBufPool.h | 22 +- ksolve/ZombieFunction.cpp | 277 +- ksolve/ZombieFunction.h | 48 +- ksolve/ZombiePool.cpp | 200 +- ksolve/ZombiePool.h | 92 +- ksolve/ZombiePoolInterface.h | 3 + ksolve/helper.h | 18 + ksolve/testKsolve.cpp | 70 +- mesh/CylMesh.cpp | 45 +- pymoose/CMakeLists.txt | 129 +- pymoose/PyRun.cpp | 22 +- pymoose/melement.cpp | 50 +- pymoose/moosemodule.cpp | 323 +- pymoose/moosemodule.h | 27 +- pymoose/pymooseinit.cpp | 92 +- pymoose/test_moosemodule.cpp | 47 +- pymoose/vec.cpp | 56 +- python/InstallPyMoose.cmake | 25 - python/moose/OrderedDict.py | 260 - python/moose/SBML/readSBML.py | 117 +- python/moose/SBML/writeSBML.py | 214 +- python/moose/__init__.py | 19 +- python/moose/alternate.py | 1037 - .../chemUtil/add_Delete_ChemicalSolver.py | 4 +- python/moose/chemUtil/chemConnectUtil.py | 6 +- python/moose/fixXreacs.py | 184 +- python/moose/genesis/writeKkit.py | 38 +- python/moose/graph_utils.py | 85 - python/moose/graphutil.py | 193 - python/moose/methods_utils.py | 7 - python/moose/model_utils.py | 248 + python/moose/moose.py | 473 +- python/moose/moose_config.py | 61 - python/moose/moose_constants.py | 5 - python/moose/moose_test.py | 212 +- python/moose/network_utils.py | 129 + python/moose/neuroml/MorphML.py | 4 +- python/moose/neuroml2/hhfit.py | 122 +- python/moose/neuroml2/reader.py | 36 +- python/moose/neuroml2/test_converter.py | 104 - python/moose/neuroml2/test_hhfit.py | 157 - python/moose/plot_utils.py | 27 +- python/moose/server.py | 2 +- python/moose/utils.py | 36 +- python/moose/wrapper.py | 212 + python/rdesigneur/rdesigneur.py | 66 +- python/rdesigneur/rdesigneurProtos.py | 1 - python/rdesigneur/rmoogli.py | 2 +- python/setup.cmake.py | 63 - randnum/CMakeLists.txt | 8 +- randnum/RNG.h | 2 +- scheduling/Clock.cpp | 14 +- scripts/submit.py | 147 - setup.py | 179 + shell/Neutral.cpp | 1164 +- shell/Neutral.h | 424 +- shell/Shell.cpp | 11 +- synapse/RollingMatrix.cpp | 142 +- synapse/RollingMatrix.h | 87 +- synapse/SeqSynHandler.cpp | 830 +- tests/alpha/function.py | 160 - .../chem_models => data}/00001-sbml-l3v1.xml | 0 .../{python/chem_models => data}/19085.cspace | 0 .../{python/chem_models => data}/Anno_acc2.g | 0 tests/{python/genesis => data}/acc11.g | 0 tests/data/acc27.g | 325 - tests/data/c_m.xml | 6225 +++ .../genesis => data}/kkit_objects_example.g | 0 .../mkp1_feedback_effects_acc4.g | 0 .../mkp1_feedback_effects_acc4.xml | 0 tests/data/prot_wt.xml | 1 + tests/issues/issue_69.py | 15 - tests/{python => py_moose}/OSC_diff_vols.g | 0 tests/{python => py_moose}/benchmark.py | 0 tests/{python => py_moose}/chan_proto.py | 0 tests/{python => py_moose}/models.py | 0 tests/{python => py_moose}/param_chan.py | 0 tests/{python => py_moose}/params.py | 0 tests/{python => py_moose}/run_mumble.sh | 0 tests/{python => py_moose}/soma.p | 0 tests/{python => py_moose}/streamer.py | 0 ...GraupnerBrunel2012_STDPfromCaPlasticity.py | 5 +- tests/{python => py_moose}/test_Xchan1.py | 7 +- tests/{python => py_moose}/test_Xdiff1.py | 5 +- tests/{python => py_moose}/test_Xenz1.py | 6 +- tests/{python => py_moose}/test_Xreacs2.py | 7 +- tests/{python => py_moose}/test_Xreacs3.py | 7 +- tests/{python => py_moose}/test_Xreacs4.py | 8 +- tests/{python => py_moose}/test_Xreacs4a.py | 8 +- tests/{python => py_moose}/test_Xreacs5.py | 4 +- tests/{python => py_moose}/test_Xreacs5a.py | 19 +- tests/{python => py_moose}/test_Xreacs6.py | 8 +- tests/{python => py_moose}/test_Xreacs7.py | 17 +- tests/{python => py_moose}/test_Xreacs8.py | 22 +- .../py_moose/test_accessing_existing_paths.py | 47 + .../test_connectionLists.py | 11 +- .../test_cylinder_diffusion_gsolve+dsolve.py | 5 +- tests/{python => py_moose}/test_difshells.py | 7 +- tests/{python => py_moose}/test_docs.py | 5 +- .../test_dose_response.py | 11 +- .../{python => py_moose}/test_expr_parser.py | 5 +- tests/{python => py_moose}/test_function.py | 29 +- .../test_function_chemsys.py | 8 +- .../test_function_controls_reac_rate.py | 1 - tests/py_moose/test_function_namedvars.py | 121 + .../test_gsolve_parallel.py | 12 +- .../test_hsolve_externalCalcium.py | 8 +- tests/py_moose/test_kkit.py | 39 + tests/py_moose/test_ksolve.py | 58 + .../test_ksolve_parallel.py | 8 +- .../test_moose_attribs.py | 24 +- tests/py_moose/test_moose_paths.py | 43 + .../test_negative_value_flag.py | 54 +- .../test_pymoose_1.py} | 90 +- tests/py_moose/test_pymoose_2.py | 60 + tests/{python => py_moose}/test_random_gen.sh | 0 tests/{python => py_moose}/test_random_num.py | 10 +- tests/{python => py_moose}/test_rdesigneur.py | 8 +- .../test_rdesigneur_random_syn_input.py | 53 + .../test_steady_state_solver.py | 6 +- tests/{python => py_moose}/test_streamer.py | 9 +- tests/py_moose/test_switch_solvers.py | 146 + tests/{python => py_moose}/test_synchan.py | 5 +- .../test_table_streaming_support.py | 0 tests/py_moose/test_vec.py | 10 + tests/py_moose/test_wrapper.py | 91 + tests/py_rdesigneur/Na_Chan_Migliore2018_.py | 80 + tests/py_rdesigneur/chem/CICRspineDend.g | 332 + tests/py_rdesigneur/chem/CICRwithConcChan.g | 284 + tests/py_rdesigneur/chem/chanPhosph3compt.g | 189 + tests/py_rdesigneur/chem/chanPhosphByCaMKII.g | 162 + tests/py_rdesigneur/chem/psd52.g | 488 + tests/py_rdesigneur/chem/psd53_old.g | 474 + tests/py_rdesigneur/test_1_minimalModel.py | 50 + tests/py_rdesigneur/test_20_currentPulse.py | 48 + tests/py_rdesigneur/test_21_vclamp.py | 29 + .../test_30_squid_currentPulse.py | 32 + .../test_32_squid_axon_propgn.py | 74 + tests/py_rdesigneur/test_41_ballAndStick.py | 52 + .../test_51_periodic_syn_input.py | 32 + tests/py_rdesigneur/test_6_chem_osc.py | 28 + tests/py_rdesigneur/test_72_CICR.py | 94 + tests/py_rdesigneur/test_74_travelling_osc.py | 75 + .../test_76_func_func_control_reac_rates.py} | 64 +- .../test_rdes_with_func_proto.py | 58 + tests/pytest.ini | 10 + tests/python/Rallpacks/README.Rallpack3 | 163 - tests/python/Rallpacks/compartment.py | 126 - tests/python/Rallpacks/data/run_data.dat | 14 - .../rallpack3/active_cable_template.nrn | 68 - .../moose_vs_neuron/rallpack3/cable.out | 5001 -- .../rallpack3/cable_in_neuron.hoc | 68 - .../moose_vs_neuron/rallpack3/compare.hs | 15 - .../moose_vs_neuron/rallpack3/compare.py | 130 - .../moose_vs_neuron/rallpack3/data/cable.out | 5001 -- .../rallpack3/data/compare_neuron0.png | Bin 76567 -> 0 bytes .../rallpack3/data/compare_neuron1.png | Bin 78880 -> 0 bytes .../moose_vs_neuron/rallpack3/data/moose.dat | 5001 -- .../rallpack3/data/moose_sim_dt_1us.dat | 5001 -- .../rallpack3/data/reference_neuron.dat | 5000 -- .../moose_vs_neuron/rallpack3/moose_sim.py | 329 - .../rallpack3/moose_vs_neuron0.png | Bin 69909 -> 0 bytes .../rallpack3/moose_vs_neuron1.png | Bin 66248 -> 0 bytes .../moose_vs_neuron/rallpack3/neuron.log | 24 - .../moose_vs_neuron/rallpack3/neuron_sim.py | 147 - .../rallpack3/profile_neuron.sh | 8 - .../rallpack3/profile_rallapck.py | 120 - tests/python/Rallpacks/profile_rallapck.py | 116 - .../Rallpacks/rallpacks_cable_hhchannel.py | 274 - .../Rallpacks/rallpacks_passive_cable.py | 206 - .../python/Rallpacks/rallpacks_tree_cable.py | 250 - tests/python/abstrModelEqns9.py | 239 - tests/python/chem_models/acc27.g | 347 - tests/python/deprecated_test_gc.py | 138 - tests/python/mpi/.gdbinit | 5 - tests/python/mpi/benchmark.py | 152 - tests/python/mpi/launch.sh | 2 - tests/python/mpi/recurrentIntFire.py | 85 - tests/python/mumbl/mumbl.xml | 74 - tests/python/mus/README | 7 - tests/python/mus/cachannel.py | 157 - tests/python/mus/ee | 0 tests/python/mus/hchannel.py | 90 - tests/python/mus/kchannel.py | 195 - tests/python/mus/nachannel.py | 116 - tests/python/mus/nmda.py | 13 - tests/python/mus/out | 249 - tests/python/mus/passive | 0 tests/python/mus/rc19.p | 499 - tests/python/mus/rc19.py | 264 - tests/python/mus/settings.py | 58 - tests/python/mus/synapse.py | 109 - tests/python/testXchan1.py | 181 - tests/python/testXdiff1.py | 172 - tests/python/testXenz1.py | 135 - tests/python/testXreacs2.py | 59 - tests/python/testXreacs3.py | 130 - tests/python/testXreacs4.py | 112 - tests/python/testXreacs4a.py | 112 - tests/python/testXreacs5.py | 118 - tests/python/testXreacs5a.py | 118 - tests/python/testXreacs6.py | 118 - tests/python/testXreacs7.py | 135 - tests/python/testXreacs8.py | 132 - tests/python/test_accessing_existing_paths.py | 41 - tests/python/test_all.sh | 15 - tests/python/test_function_derivative.py | 160 - tests/python/test_import.py | 8 - tests/python/test_kkit.py | 57 - tests/python/test_ksolve.py | 54 - tests/python/test_moose_paths.py | 36 - tests/python/test_muparser.py | 162 - tests/python/test_paths.py | 51 - tests/python/test_pyrun.py | 3 - .../test_rdesigneur_random_syn_input.py | 46 - tests/python/test_snippets.py | 58 - tests/python/test_vec.py | 5 - tests/python/testdisabled_dose_response.py | 106 - .../ChannelML_v1.8.1_GENESIStab.xsl | 1503 - .../DoubExpSyn/ChannelML_v1.8.1_NEURONmod.xsl | 1974 - .../cellMechanisms/DoubExpSyn/DoubExpSyn.xml | 28 - .../cellMechanisms/DoubExpSyn/properties.xml | 25 - .../ChannelML_v1.8.1_GENESIStab.xsl | 1503 - .../ChannelML_v1.8.1_NEURONmod.xsl | 1974 - .../KConductance/ChannelML_v1.8.1_PSICS.xsl | 471 - .../KConductance/KChannel_HH.xml | 49 - .../KConductance/properties.xml | 26 - .../ChannelML_v1.8.1_GENESIStab.xsl | 1503 - .../ChannelML_v1.8.1_NEURONmod.xsl | 1974 - .../ChannelML_v1.8.1_PSICS.xsl | 471 - .../LeakConductance/LeakConductance.xml | 17 - .../LeakConductance/properties.xml | 27 - .../ChannelML_v1.8.1_GENESIStab.xsl | 1503 - .../ChannelML_v1.8.1_NEURONmod.xsl | 1974 - .../NaConductance/ChannelML_v1.8.1_PSICS.xsl | 471 - .../NaConductance/NaChannel_HH.xml | 58 - .../NaConductance/properties.xml | 26 - .../two_cells_nml_1.8/cellMechanisms/README | 2 - .../two_cells_nml_1.8/chem_model_sbml.xml | 31 - tests/python/two_cells_nml_1.8/config.xml | 58 - .../two_cells_nml_1.8/morphologies/README | 14 - .../morphologies/SampleCell.java.ser | Bin 3292 -> 0 bytes .../morphologies/cellA.java.ser | Bin 8561 -> 0 bytes .../morphologies/cellB.java.ser | Bin 2965 -> 0 bytes tests/python/two_cells_nml_1.8/mumbl.xml | 74 - .../two_cells_nml_1.8/simulations/README | 1 - tests/python/two_cells_nml_1.8/two_cells.ncx | 516 - tests/python/two_cells_nml_1.8/two_cells.nml | 715 - tests/requirements.txt | 7 + .../{python => support}/_neuroml/CA1.net.xml | 0 tests/{python => support}/_neuroml/CA1.py | 0 .../_neuroml/CA1_hsolve.py | 0 .../_neuroml/CA1inhomog.net.xml | 0 .../_neuroml/CA1soma.net.xml | 0 .../{python => support}/_neuroml/FvsI_CA1.py | 0 tests/{python => support}/_neuroml/README | 0 .../{python => support}/_neuroml/__init__.py | 0 .../_neuroml/cells_channels/CA1soma.morph.xml | 0 .../_neuroml/cells_channels/Gran_KDr_98.xml | 0 .../_neuroml/cells_channels/Gran_NaF_98.xml | 0 .../_neuroml/cells_channels/Purkinje_KA.xml | 0 .../_neuroml/cells_channels/README | 0 .../_neuroml/cells_channels/hd.xml | 0 .../_neuroml/cells_channels/hd_minus73.xml | 0 .../_neuroml/cells_channels/kad.xml | 0 .../_neuroml/cells_channels/kap.xml | 0 .../_neuroml/cells_channels/kdr.xml | 0 .../_neuroml/cells_channels/na3.xml | 0 .../_neuroml/cells_channels/nax.xml | 0 .../_neuroml/cells_channels/pas.xml | 0 tests/{python => support}/_neuroml/count.py | 0 tests/{python => support}/test_files | 0 tests/support/test_hhfit.py | 131 + tests/{python => support}/test_neuroml.py | 13 +- tests/{python => support}/test_neuroml2.py | 14 +- tests/{python => support}/test_nsdf.py | 10 +- tests/{python => support}/test_sbml.py | 23 +- utility/CMakeLists.txt | 2 +- utility/boost_ode.h | 39 + utility/matrix_util.cpp | 122 - utility/numutil.cpp | 11 +- utility/numutil.h | 13 +- utility/print_function.hpp | 19 +- utility/setupenv.cpp | 144 +- utility/strutil.cpp | 27 + utility/strutil.h | 6 + utility/testing_macros.hpp | 9 +- utility/utility.cpp | 31 + utility/utility.h | 26 +- 484 files changed, 68043 insertions(+), 74205 deletions(-) create mode 100644 .ci/Dockerfile create mode 100755 .ci/build_wheels_osx.sh create mode 100755 .ci/coverage.sh rename {.travis => .ci}/deploy_pypi.sh (100%) rename {.travis => .ci}/download_and_run_doqcs.sh (100%) rename {.travis => .ci}/run_pylint.sh (100%) create mode 100755 .ci/travis_build_linux.sh rename {.travis => .ci}/travis_build_osx.sh (70%) create mode 100755 .ci/travis_prepare_linux.sh rename {.travis => .ci}/travis_prepare_osx.sh (100%) create mode 100644 .github/main.workflow create mode 100644 .github/workflows/pymoose.yml create mode 100644 .gitlab-ci.yml delete mode 100755 .travis/travis_build_linux.sh delete mode 100755 .travis/travis_prepare_linux.sh create mode 100644 MANIFEST.in delete mode 100644 benchmarks/CMakeLists.txt delete mode 100644 benchmarks/benchmarks.cpp delete mode 100644 benchmarks/kineticMarks.cpp delete mode 100644 biophysics/MarkovGslSolver.cpp delete mode 100644 biophysics/MarkovGslSolver.h create mode 100644 biophysics/MarkovOdeSolver.cpp create mode 100644 biophysics/MarkovOdeSolver.h delete mode 100644 builtins/Func.cpp delete mode 100644 builtins/Func.h rename {cmake_modules => cmake}/FindGSL.cmake (97%) rename {cmake_modules => cmake}/FindLIBSBML.cmake (100%) rename {cmake_modules => cmake}/FindLibXML2.cmake (100%) rename {cmake_modules => cmake}/FindPyQt.py (100%) rename {cmake_modules => cmake}/FindPyQt4.cmake (100%) rename {cmake_modules => cmake}/FindReadline.cmake (100%) rename {cmake_modules => cmake}/FindSIP.cmake (100%) rename {cmake_modules => cmake}/FindSIP.py (100%) rename {cmake_modules => cmake}/FindSphinx.cmake (100%) rename {cmake_modules => cmake}/FindTermcap.cmake (100%) rename {cmake_modules => cmake}/GetGitRevisionDescription.cmake (100%) rename {cmake_modules => cmake}/GetGitRevisionDescription.cmake.in (100%) rename {cmake_modules => cmake}/GetRevision.cmake (100%) rename {cmake_modules => cmake}/Pinfo.plist (100%) rename {cmake_modules => cmake}/SIPMacros.cmake (100%) delete mode 100644 cmake_modules/FindNumPy.cmake create mode 100644 devel/CMakeLists.txt create mode 100644 devel/_conftest.py create mode 100644 devel/docker/centos/Dockerfile create mode 100644 devel/docker/centos/Makefile create mode 100644 devel/docker/opensuse/Dockerfile create mode 100644 devel/docker/opensuse/Makefile create mode 100644 devel/docker/travis/Dockerfile create mode 100644 devel/docker/travis/Makefile create mode 100644 devel/docker/wheel/Dockerfile create mode 100644 devel/docker/wheel/Makefile create mode 100644 devel/docker/wheel/README.md create mode 100755 devel/docker/wheel/build_wheels.sh create mode 100755 devel/docker/wheel/test_and_upload.sh rename {tests/python => devel/fixme}/testDisabled_socket_streamer_tcp.py (100%) create mode 100644 devel/fixme/test_81_synTrigCICR.py create mode 100644 devel/fixme/test_82_multiscale_gluR_phosph_3compt.py create mode 100644 devel/fixme/test_long_sbml+exp+parser+multithreaded.py rename {tests/alpha => devel/fixme}/test_socket_streamer_multitab.py (100%) rename {tests/alpha => devel/fixme}/test_socket_streamer_uds.py (100%) rename {tests => devel}/issues/hsolve/README (100%) rename {tests => devel}/issues/hsolve/compare_moose_nrn.py (100%) rename {tests => devel}/issues/hsolve/h10.CNG.hoc (100%) rename {tests => devel}/issues/hsolve/h10.CNG.moose.py (100%) rename {tests => devel}/issues/hsolve/h10.CNG.swc (100%) rename {tests => devel}/issues/hsolve/run_h10.CNG.hoc (100%) rename {tests => devel}/issues/issue_124.py (100%) rename {tests => devel}/issues/issue_239.py (100%) rename {tests => devel}/issues/issue_34.py (100%) rename {tests => devel}/issues/issue_45.py (100%) rename {tests => devel}/issues/issue_47.py (100%) rename {tests => devel}/issues/issue_93.py (100%) create mode 100644 external/exprtk/exprtk.hpp create mode 100644 external/libsoda/.travis.yml create mode 100644 external/libsoda/CMakeLists.txt create mode 100644 external/libsoda/LICENSE create mode 100644 external/libsoda/LSODA.cpp create mode 100644 external/libsoda/LSODA.h create mode 100644 external/libsoda/README.md create mode 100644 external/libsoda/benchmark_LSODA.cpp create mode 100644 external/libsoda/helper.h create mode 100755 external/libsoda/run_benchmark.sh create mode 100644 external/libsoda/test_LSODA.cpp delete mode 100644 external/muparser/CMakeLists.txt delete mode 100644 external/muparser/License.txt delete mode 100644 external/muparser/Makefile.in delete mode 100644 external/muparser/include/muParser.h delete mode 100644 external/muparser/include/muParserBase.h delete mode 100644 external/muparser/include/muParserBytecode.h delete mode 100644 external/muparser/include/muParserCallback.h delete mode 100644 external/muparser/include/muParserDLL.h delete mode 100644 external/muparser/include/muParserDef.h delete mode 100644 external/muparser/include/muParserError.h delete mode 100644 external/muparser/include/muParserFixes.h delete mode 100644 external/muparser/include/muParserInt.h delete mode 100644 external/muparser/include/muParserStack.h delete mode 100644 external/muparser/include/muParserTemplateMagic.h delete mode 100644 external/muparser/include/muParserTest.h delete mode 100644 external/muparser/include/muParserToken.h delete mode 100644 external/muparser/include/muParserTokenReader.h delete mode 100644 external/muparser/src/muParser.cpp delete mode 100644 external/muparser/src/muParserBase.cpp delete mode 100644 external/muparser/src/muParserBytecode.cpp delete mode 100644 external/muparser/src/muParserCallback.cpp delete mode 100644 external/muparser/src/muParserDLL.cpp delete mode 100644 external/muparser/src/muParserError.cpp delete mode 100644 external/muparser/src/muParserInt.cpp delete mode 100644 external/muparser/src/muParserTest.cpp delete mode 100644 external/muparser/src/muParserTokenReader.cpp create mode 100644 external/tinyexpr/.travis.yml create mode 100644 external/tinyexpr/CMakeLists.txt create mode 100644 external/tinyexpr/CONTRIBUTING create mode 100644 external/tinyexpr/LICENSE create mode 100644 external/tinyexpr/README.md create mode 100644 external/tinyexpr/benchmark.c create mode 100644 external/tinyexpr/doc/e1.dot create mode 100644 external/tinyexpr/doc/e1.png create mode 100644 external/tinyexpr/doc/e2.dot create mode 100644 external/tinyexpr/doc/e2.png create mode 100644 external/tinyexpr/example.c create mode 100644 external/tinyexpr/example2.c create mode 100644 external/tinyexpr/example3.c create mode 100644 external/tinyexpr/minctest.h create mode 100644 external/tinyexpr/test.c create mode 100644 external/tinyexpr/tinyexpr.c create mode 100644 external/tinyexpr/tinyexpr.h create mode 100644 ksolve/helper.h delete mode 100644 python/InstallPyMoose.cmake delete mode 100644 python/moose/OrderedDict.py delete mode 100644 python/moose/alternate.py delete mode 100644 python/moose/graph_utils.py delete mode 100644 python/moose/graphutil.py create mode 100644 python/moose/model_utils.py delete mode 100644 python/moose/moose_config.py create mode 100644 python/moose/network_utils.py delete mode 100644 python/moose/neuroml2/test_converter.py delete mode 100644 python/moose/neuroml2/test_hhfit.py create mode 100644 python/moose/wrapper.py delete mode 100644 python/setup.cmake.py delete mode 100755 scripts/submit.py create mode 100644 setup.py delete mode 100644 tests/alpha/function.py rename tests/{python/chem_models => data}/00001-sbml-l3v1.xml (100%) rename tests/{python/chem_models => data}/19085.cspace (100%) rename tests/{python/chem_models => data}/Anno_acc2.g (100%) rename tests/{python/genesis => data}/acc11.g (100%) delete mode 100644 tests/data/acc27.g create mode 100644 tests/data/c_m.xml rename tests/{python/genesis => data}/kkit_objects_example.g (100%) rename tests/{python/chem_models => data}/mkp1_feedback_effects_acc4.g (100%) rename tests/{python/chem_models => data}/mkp1_feedback_effects_acc4.xml (100%) create mode 100644 tests/data/prot_wt.xml delete mode 100644 tests/issues/issue_69.py rename tests/{python => py_moose}/OSC_diff_vols.g (100%) rename tests/{python => py_moose}/benchmark.py (100%) rename tests/{python => py_moose}/chan_proto.py (100%) rename tests/{python => py_moose}/models.py (100%) rename tests/{python => py_moose}/param_chan.py (100%) rename tests/{python => py_moose}/params.py (100%) rename tests/{python => py_moose}/run_mumble.sh (100%) rename tests/{python => py_moose}/soma.p (100%) rename tests/{python => py_moose}/streamer.py (100%) rename tests/{python => py_moose}/test_GraupnerBrunel2012_STDPfromCaPlasticity.py (99%) rename tests/{python => py_moose}/test_Xchan1.py (97%) rename tests/{python => py_moose}/test_Xdiff1.py (99%) rename tests/{python => py_moose}/test_Xenz1.py (96%) rename tests/{python => py_moose}/test_Xreacs2.py (96%) rename tests/{python => py_moose}/test_Xreacs3.py (98%) rename tests/{python => py_moose}/test_Xreacs4.py (97%) rename tests/{python => py_moose}/test_Xreacs4a.py (95%) rename tests/{python => py_moose}/test_Xreacs5.py (98%) rename tests/{python => py_moose}/test_Xreacs5a.py (85%) rename tests/{python => py_moose}/test_Xreacs6.py (97%) rename tests/{python => py_moose}/test_Xreacs7.py (89%) rename tests/{python => py_moose}/test_Xreacs8.py (80%) create mode 100644 tests/py_moose/test_accessing_existing_paths.py rename tests/{python => py_moose}/test_connectionLists.py (97%) rename tests/{python => py_moose}/test_cylinder_diffusion_gsolve+dsolve.py (98%) rename tests/{python => py_moose}/test_difshells.py (98%) rename tests/{python => py_moose}/test_docs.py (92%) rename tests/{python => py_moose}/test_dose_response.py (94%) rename tests/{python => py_moose}/test_expr_parser.py (99%) rename tests/{python => py_moose}/test_function.py (78%) rename tests/{python => py_moose}/test_function_chemsys.py (99%) rename tests/{python => py_moose}/test_function_controls_reac_rate.py (99%) create mode 100644 tests/py_moose/test_function_namedvars.py rename tests/{python => py_moose}/test_gsolve_parallel.py (94%) rename tests/{python => py_moose}/test_hsolve_externalCalcium.py (96%) create mode 100644 tests/py_moose/test_kkit.py create mode 100644 tests/py_moose/test_ksolve.py rename tests/{python => py_moose}/test_ksolve_parallel.py (94%) rename tests/{python => py_moose}/test_moose_attribs.py (80%) create mode 100644 tests/py_moose/test_moose_paths.py rename tests/{python => py_moose}/test_negative_value_flag.py (53%) rename tests/{python/test_pymoose.py => py_moose/test_pymoose_1.py} (71%) create mode 100644 tests/py_moose/test_pymoose_2.py rename tests/{python => py_moose}/test_random_gen.sh (100%) rename tests/{python => py_moose}/test_random_num.py (90%) rename tests/{python => py_moose}/test_rdesigneur.py (92%) create mode 100644 tests/py_moose/test_rdesigneur_random_syn_input.py rename tests/{python => py_moose}/test_steady_state_solver.py (99%) rename tests/{python => py_moose}/test_streamer.py (97%) create mode 100644 tests/py_moose/test_switch_solvers.py rename tests/{python => py_moose}/test_synchan.py (98%) rename tests/{python => py_moose}/test_table_streaming_support.py (100%) create mode 100644 tests/py_moose/test_vec.py create mode 100644 tests/py_moose/test_wrapper.py create mode 100644 tests/py_rdesigneur/Na_Chan_Migliore2018_.py create mode 100644 tests/py_rdesigneur/chem/CICRspineDend.g create mode 100644 tests/py_rdesigneur/chem/CICRwithConcChan.g create mode 100644 tests/py_rdesigneur/chem/chanPhosph3compt.g create mode 100644 tests/py_rdesigneur/chem/chanPhosphByCaMKII.g create mode 100644 tests/py_rdesigneur/chem/psd52.g create mode 100644 tests/py_rdesigneur/chem/psd53_old.g create mode 100644 tests/py_rdesigneur/test_1_minimalModel.py create mode 100644 tests/py_rdesigneur/test_20_currentPulse.py create mode 100644 tests/py_rdesigneur/test_21_vclamp.py create mode 100644 tests/py_rdesigneur/test_30_squid_currentPulse.py create mode 100644 tests/py_rdesigneur/test_32_squid_axon_propgn.py create mode 100644 tests/py_rdesigneur/test_41_ballAndStick.py create mode 100644 tests/py_rdesigneur/test_51_periodic_syn_input.py create mode 100644 tests/py_rdesigneur/test_6_chem_osc.py create mode 100644 tests/py_rdesigneur/test_72_CICR.py create mode 100644 tests/py_rdesigneur/test_74_travelling_osc.py rename tests/{alpha/ex7.6_func_controls_reac_rate.py => py_rdesigneur/test_76_func_func_control_reac_rates.py} (50%) create mode 100644 tests/py_rdesigneur/test_rdes_with_func_proto.py create mode 100644 tests/pytest.ini delete mode 100644 tests/python/Rallpacks/README.Rallpack3 delete mode 100644 tests/python/Rallpacks/compartment.py delete mode 100644 tests/python/Rallpacks/data/run_data.dat delete mode 100644 tests/python/Rallpacks/moose_vs_neuron/rallpack3/active_cable_template.nrn delete mode 100644 tests/python/Rallpacks/moose_vs_neuron/rallpack3/cable.out delete mode 100644 tests/python/Rallpacks/moose_vs_neuron/rallpack3/cable_in_neuron.hoc delete mode 100644 tests/python/Rallpacks/moose_vs_neuron/rallpack3/compare.hs delete mode 100755 tests/python/Rallpacks/moose_vs_neuron/rallpack3/compare.py delete mode 100644 tests/python/Rallpacks/moose_vs_neuron/rallpack3/data/cable.out delete mode 100644 tests/python/Rallpacks/moose_vs_neuron/rallpack3/data/compare_neuron0.png delete mode 100644 tests/python/Rallpacks/moose_vs_neuron/rallpack3/data/compare_neuron1.png delete mode 100644 tests/python/Rallpacks/moose_vs_neuron/rallpack3/data/moose.dat delete mode 100644 tests/python/Rallpacks/moose_vs_neuron/rallpack3/data/moose_sim_dt_1us.dat delete mode 100644 tests/python/Rallpacks/moose_vs_neuron/rallpack3/data/reference_neuron.dat delete mode 100644 tests/python/Rallpacks/moose_vs_neuron/rallpack3/moose_sim.py delete mode 100644 tests/python/Rallpacks/moose_vs_neuron/rallpack3/moose_vs_neuron0.png delete mode 100644 tests/python/Rallpacks/moose_vs_neuron/rallpack3/moose_vs_neuron1.png delete mode 100644 tests/python/Rallpacks/moose_vs_neuron/rallpack3/neuron.log delete mode 100644 tests/python/Rallpacks/moose_vs_neuron/rallpack3/neuron_sim.py delete mode 100755 tests/python/Rallpacks/moose_vs_neuron/rallpack3/profile_neuron.sh delete mode 100755 tests/python/Rallpacks/moose_vs_neuron/rallpack3/profile_rallapck.py delete mode 100755 tests/python/Rallpacks/profile_rallapck.py delete mode 100644 tests/python/Rallpacks/rallpacks_cable_hhchannel.py delete mode 100644 tests/python/Rallpacks/rallpacks_passive_cable.py delete mode 100644 tests/python/Rallpacks/rallpacks_tree_cable.py delete mode 100644 tests/python/abstrModelEqns9.py delete mode 100644 tests/python/chem_models/acc27.g delete mode 100644 tests/python/deprecated_test_gc.py delete mode 100644 tests/python/mpi/.gdbinit delete mode 100644 tests/python/mpi/benchmark.py delete mode 100644 tests/python/mpi/launch.sh delete mode 100644 tests/python/mpi/recurrentIntFire.py delete mode 100644 tests/python/mumbl/mumbl.xml delete mode 100644 tests/python/mus/README delete mode 100644 tests/python/mus/cachannel.py delete mode 100644 tests/python/mus/ee delete mode 100644 tests/python/mus/hchannel.py delete mode 100644 tests/python/mus/kchannel.py delete mode 100644 tests/python/mus/nachannel.py delete mode 100644 tests/python/mus/nmda.py delete mode 100644 tests/python/mus/out delete mode 100644 tests/python/mus/passive delete mode 100644 tests/python/mus/rc19.p delete mode 100644 tests/python/mus/rc19.py delete mode 100644 tests/python/mus/settings.py delete mode 100644 tests/python/mus/synapse.py delete mode 100644 tests/python/testXchan1.py delete mode 100644 tests/python/testXdiff1.py delete mode 100644 tests/python/testXenz1.py delete mode 100644 tests/python/testXreacs2.py delete mode 100644 tests/python/testXreacs3.py delete mode 100644 tests/python/testXreacs4.py delete mode 100644 tests/python/testXreacs4a.py delete mode 100644 tests/python/testXreacs5.py delete mode 100644 tests/python/testXreacs5a.py delete mode 100644 tests/python/testXreacs6.py delete mode 100644 tests/python/testXreacs7.py delete mode 100644 tests/python/testXreacs8.py delete mode 100644 tests/python/test_accessing_existing_paths.py delete mode 100755 tests/python/test_all.sh delete mode 100644 tests/python/test_function_derivative.py delete mode 100644 tests/python/test_import.py delete mode 100644 tests/python/test_kkit.py delete mode 100644 tests/python/test_ksolve.py delete mode 100644 tests/python/test_moose_paths.py delete mode 100644 tests/python/test_muparser.py delete mode 100644 tests/python/test_paths.py delete mode 100644 tests/python/test_pyrun.py delete mode 100644 tests/python/test_rdesigneur_random_syn_input.py delete mode 100644 tests/python/test_snippets.py delete mode 100644 tests/python/test_vec.py delete mode 100644 tests/python/testdisabled_dose_response.py delete mode 100644 tests/python/two_cells_nml_1.8/cellMechanisms/DoubExpSyn/ChannelML_v1.8.1_GENESIStab.xsl delete mode 100644 tests/python/two_cells_nml_1.8/cellMechanisms/DoubExpSyn/ChannelML_v1.8.1_NEURONmod.xsl delete mode 100644 tests/python/two_cells_nml_1.8/cellMechanisms/DoubExpSyn/DoubExpSyn.xml delete mode 100644 tests/python/two_cells_nml_1.8/cellMechanisms/DoubExpSyn/properties.xml delete mode 100644 tests/python/two_cells_nml_1.8/cellMechanisms/KConductance/ChannelML_v1.8.1_GENESIStab.xsl delete mode 100644 tests/python/two_cells_nml_1.8/cellMechanisms/KConductance/ChannelML_v1.8.1_NEURONmod.xsl delete mode 100644 tests/python/two_cells_nml_1.8/cellMechanisms/KConductance/ChannelML_v1.8.1_PSICS.xsl delete mode 100644 tests/python/two_cells_nml_1.8/cellMechanisms/KConductance/KChannel_HH.xml delete mode 100644 tests/python/two_cells_nml_1.8/cellMechanisms/KConductance/properties.xml delete mode 100644 tests/python/two_cells_nml_1.8/cellMechanisms/LeakConductance/ChannelML_v1.8.1_GENESIStab.xsl delete mode 100644 tests/python/two_cells_nml_1.8/cellMechanisms/LeakConductance/ChannelML_v1.8.1_NEURONmod.xsl delete mode 100644 tests/python/two_cells_nml_1.8/cellMechanisms/LeakConductance/ChannelML_v1.8.1_PSICS.xsl delete mode 100644 tests/python/two_cells_nml_1.8/cellMechanisms/LeakConductance/LeakConductance.xml delete mode 100644 tests/python/two_cells_nml_1.8/cellMechanisms/LeakConductance/properties.xml delete mode 100644 tests/python/two_cells_nml_1.8/cellMechanisms/NaConductance/ChannelML_v1.8.1_GENESIStab.xsl delete mode 100644 tests/python/two_cells_nml_1.8/cellMechanisms/NaConductance/ChannelML_v1.8.1_NEURONmod.xsl delete mode 100644 tests/python/two_cells_nml_1.8/cellMechanisms/NaConductance/ChannelML_v1.8.1_PSICS.xsl delete mode 100644 tests/python/two_cells_nml_1.8/cellMechanisms/NaConductance/NaChannel_HH.xml delete mode 100644 tests/python/two_cells_nml_1.8/cellMechanisms/NaConductance/properties.xml delete mode 100644 tests/python/two_cells_nml_1.8/cellMechanisms/README delete mode 100644 tests/python/two_cells_nml_1.8/chem_model_sbml.xml delete mode 100644 tests/python/two_cells_nml_1.8/config.xml delete mode 100644 tests/python/two_cells_nml_1.8/morphologies/README delete mode 100644 tests/python/two_cells_nml_1.8/morphologies/SampleCell.java.ser delete mode 100644 tests/python/two_cells_nml_1.8/morphologies/cellA.java.ser delete mode 100644 tests/python/two_cells_nml_1.8/morphologies/cellB.java.ser delete mode 100644 tests/python/two_cells_nml_1.8/mumbl.xml delete mode 100644 tests/python/two_cells_nml_1.8/simulations/README delete mode 100644 tests/python/two_cells_nml_1.8/two_cells.ncx delete mode 100644 tests/python/two_cells_nml_1.8/two_cells.nml create mode 100644 tests/requirements.txt rename tests/{python => support}/_neuroml/CA1.net.xml (100%) rename tests/{python => support}/_neuroml/CA1.py (100%) rename tests/{python => support}/_neuroml/CA1_hsolve.py (100%) rename tests/{python => support}/_neuroml/CA1inhomog.net.xml (100%) rename tests/{python => support}/_neuroml/CA1soma.net.xml (100%) rename tests/{python => support}/_neuroml/FvsI_CA1.py (100%) rename tests/{python => support}/_neuroml/README (100%) rename tests/{python => support}/_neuroml/__init__.py (100%) rename tests/{python => support}/_neuroml/cells_channels/CA1soma.morph.xml (100%) rename tests/{python => support}/_neuroml/cells_channels/Gran_KDr_98.xml (100%) rename tests/{python => support}/_neuroml/cells_channels/Gran_NaF_98.xml (100%) rename tests/{python => support}/_neuroml/cells_channels/Purkinje_KA.xml (100%) rename tests/{python => support}/_neuroml/cells_channels/README (100%) rename tests/{python => support}/_neuroml/cells_channels/hd.xml (100%) rename tests/{python => support}/_neuroml/cells_channels/hd_minus73.xml (100%) rename tests/{python => support}/_neuroml/cells_channels/kad.xml (100%) rename tests/{python => support}/_neuroml/cells_channels/kap.xml (100%) rename tests/{python => support}/_neuroml/cells_channels/kdr.xml (100%) rename tests/{python => support}/_neuroml/cells_channels/na3.xml (100%) rename tests/{python => support}/_neuroml/cells_channels/nax.xml (100%) rename tests/{python => support}/_neuroml/cells_channels/pas.xml (100%) rename tests/{python => support}/_neuroml/count.py (100%) rename tests/{python => support}/test_files (100%) create mode 100644 tests/support/test_hhfit.py rename tests/{python => support}/test_neuroml.py (95%) rename tests/{python => support}/test_neuroml2.py (84%) rename tests/{python => support}/test_nsdf.py (97%) rename tests/{python => support}/test_sbml.py (68%) create mode 100644 utility/boost_ode.h delete mode 100644 utility/matrix_util.cpp create mode 100644 utility/utility.cpp diff --git a/.ci/Dockerfile b/.ci/Dockerfile new file mode 100644 index 00000000..6ff57e4b --- /dev/null +++ b/.ci/Dockerfile @@ -0,0 +1,8 @@ +# Run this script from top directory +# docker build . --file .ci/Dockerfile --tag bhallalab/build-wheels:$(date +%s) +FROM bhallalab/python-wheels:latest +MAINTAINER Dilawar Singh +WORKDIR /root +COPY . /root/moose-core/ +# RUN ./build_wheels.sh +CMD [ "./build_wheels.sh" ] diff --git a/.ci/build_wheels_osx.sh b/.ci/build_wheels_osx.sh new file mode 100755 index 00000000..26a95bb6 --- /dev/null +++ b/.ci/build_wheels_osx.sh @@ -0,0 +1,94 @@ +#!/bin/bash +set -e +set -x + +BRANCH=$(cat ./BRANCH) +VERSION=3.2.dev$(date +%Y%m%d) + +# Just to be sure on homebrew. +export PATH=/usr/local/bin:$PATH + +brew update || echo "Failed to update brew" +brew install gsl || brew upgrade gsl +brew upgrade python3 || echo "Failed to upgrade python3" +brew upgrade python2 || echo "Failed to upgrade python2" +brew upgrade python || echo "Failed to upgrade python" + +# Following are to remove numpy; It is breaking the build on Xcode9.4. +brew uninstall gdal postgis || echo "Failed to uninstall gdal/postgis" +brew uninstall numpy || echo "Failed to uninstall numpy" + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +MOOSE_SOURCE_DIR=`pwd`/moose-core + +if [ ! -d $MOOSE_SOURCE_DIR ]; then + git clone https://github.com/BhallaLab/moose-core -b $BRANCH --depth 10 +fi +cd moose-core && git pull +WHEELHOUSE=$HOME/wheelhouse +mkdir -p $WHEELHOUSE +# Current version 0.7.4 seems to be broken with python3.7 . +# See https://travis-ci.org/BhallaLab/deploy/jobs/435219820 +sudo /usr/local/bin/python -m pip install delocate virtualenv +sudo /usr/local/bin/python3 -m pip install delocate virtualenv +DELOCATE_WHEEL=/usr/local/bin/delocate-wheel + +# Always prefer brew version. +for _py in 3 2; do + PYTHON=/usr/local/bin/python$_py + + if [ ! -f $PYTHON ]; then + echo "Not found $PYTHON" + continue + fi + + $PYTHON -m pip install setuptools --upgrade --user + $PYTHON -m pip install wheel --upgrade --user + $PYTHON -m pip install numpy --upgrade --user + $PYTHON -m pip install twine --upgrade --user + + PLATFORM=$($PYTHON -c "import distutils.util; print(distutils.util.get_platform())") + + ( + cd $MOOSE_SOURCE_DIR + BUILDDIR=_build_$_py + mkdir -p $BUILDDIR && cd $BUILDDIR + echo " -- Building wheel for $PLATFORM" + cmake -DVERSION_MOOSE=$VERSION -DPYTHON_EXECUTABLE=$PYTHON .. + + make -j4 + ( + cd python + ls *.py + sed "s/from distutils.*setup/from setuptools import setup/g" \ + setup.cmake.py > setup.wheel.py + $PYTHON setup.wheel.py bdist_wheel -p $PLATFORM + # Now fix the wheel using delocate. + $DELOCATE_WHEEL -w $WHEELHOUSE -v dist/*.whl + ) + + ls $WHEELHOUSE/pymoose*-py${_py}-*.whl + + # create a virtualenv and test this. + rm -rf $HOME/Py${_py} + ( + python3 -m virtualenv -p $PYTHON $HOME/Py${_py} + source $HOME/Py${_py}/bin/activate + set +x + python -m pip install $WHEELHOUSE/pymoose*-py${_py}-*.whl + echo "Testing wheel in virtualenv" + which python + python --version + python -c 'import moose; print( moose.__version__ )' + deactivate + set -x + ) + ) + + if [ ! -z "$PYPI_PASSWORD" ]; then + echo "Did you test the wheels? I am uploading anyway ..." + $PYTHON -m twine upload -u bhallalab -p $PYPI_PASSWORD \ + $HOME/wheelhouse/pymoose*.whl || echo "Failed to upload to PyPi" + fi +done diff --git a/.ci/coverage.sh b/.ci/coverage.sh new file mode 100755 index 00000000..f7193561 --- /dev/null +++ b/.ci/coverage.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +python3 -m trace --count \ + --ignore-dir=/usr/lib64 \ + --ignore-module=libsbml \ + --ignore-module=numpy \ + --ignore-module=neuroml \ + "$@" + diff --git a/.travis/deploy_pypi.sh b/.ci/deploy_pypi.sh similarity index 100% rename from .travis/deploy_pypi.sh rename to .ci/deploy_pypi.sh diff --git a/.travis/download_and_run_doqcs.sh b/.ci/download_and_run_doqcs.sh similarity index 100% rename from .travis/download_and_run_doqcs.sh rename to .ci/download_and_run_doqcs.sh diff --git a/.travis/run_pylint.sh b/.ci/run_pylint.sh similarity index 100% rename from .travis/run_pylint.sh rename to .ci/run_pylint.sh diff --git a/.ci/travis_build_linux.sh b/.ci/travis_build_linux.sh new file mode 100755 index 00000000..b11cf031 --- /dev/null +++ b/.ci/travis_build_linux.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env bash +# +# DESCRIPTION: Build on linux environment. +# +# AUTHOR: Dilawar Singh (), dilawars@ncbs.res.in +# ORGANIZATION: NCBS Bangalore +# CREATED: 01/02/2017 10:11:46 AM + +set -e +set -x + +BUILDDIR=_build_travis +mkdir -p $BUILDDIR + +PYTHON2="/usr/bin/python2" +PYTHON3="/usr/bin/python3" + +$PYTHON2 -m pip install pip --upgrade --user +$PYTHON2 -m pip install libNeuroML numpy==1.14 scipy==1.2 \ + pyNeuroML python-libsbml --upgrade --user + +$PYTHON3 -m pip install pip --upgrade --user +$PYTHON3 -m pip install libNeuroML pyNeuroML python-libsbml --upgrade --user + +# sympy is only needed for pretty-priting for one test. +$PYTHON3 -m pip install numpy sympy scipy --upgrade --user + +# pytest requirements. +$PYTHON3 -m pip install -r ./tests/requirements.txt --user + +NPROC=$(nproc) +MAKE="make -j$NPROC" + +unset PYTHONPATH + +# Bug: `which python` returns /opt/bin/python* etc on travis. For which numpy +# many not be available. Therefore, it is neccessary to use fixed path for +# python executable. + +$PYTHON2 -m compileall -q . +$PYTHON3 -m compileall -q . + +# Python3 with GSL in debug more. +( + mkdir -p $BUILDDIR && cd $BUILDDIR && \ + cmake -DPYTHON_EXECUTABLE=$PYTHON3 \ + -DCMAKE_INSTALL_PREFIX=/usr -DDEBUG=ON .. + $MAKE + # Run with valgrind to log any memory leak. + valgrind --leak-check=full ./moose.bin -q -u + + # Run all tests in debug mode. + MOOSE_NUM_THREADS=$NPROC ctest -j$NPROC --output-on-failure + + + make install || sudo make install + cd /tmp + $PYTHON3 -c 'import moose;print(moose.__file__);print(moose.version())' +) + +# BOOST and python3 +( + mkdir -p $BUILDDIR && cd $BUILDDIR && \ + cmake -DWITH_BOOST_ODE=ON -DPYTHON_EXECUTABLE="$PYTHON3" \ + -DCMAKE_INSTALL_PREFIX=/usr .. + # Run coverage + export MOOSE_NUM_THREADS=3 + make coverage +) + +# GSL and python2, failure is allowed +set +e +( + mkdir -p $BUILDDIR && cd $BUILDDIR && \ + cmake -DPYTHON_EXECUTABLE=$PYTHON2 -DCMAKE_INSTALL_PREFIX=/usr .. + $MAKE && MOOSE_NUM_THREADS=$NPROC ctest -j$NPROC --output-on-failure +) +set -e + +echo "All done" diff --git a/.travis/travis_build_osx.sh b/.ci/travis_build_osx.sh similarity index 70% rename from .travis/travis_build_osx.sh rename to .ci/travis_build_osx.sh index 20d0638e..be6d57d4 100755 --- a/.travis/travis_build_osx.sh +++ b/.ci/travis_build_osx.sh @@ -20,8 +20,9 @@ set -o nounset # Treat unset variables as an error set -e -# NOTE: On travis, don't enable -j`nproc` option. It may not compile properly. +BUILDDIR=_build_travis +NPROC=$(nproc) ( # Make sure not to pick up python from /opt. PATH=/usr/local/bin:/usr/bin:$PATH @@ -33,22 +34,17 @@ set -e $PYTHON3 -m pip install python-libsbml --user $PYTHON3 -m pip install pyneuroml --user - mkdir -p _GSL_BUILD && cd _GSL_BUILD \ - && cmake -DDEBUG=ON \ - -DPYTHON_EXECUTABLE=$PYTHON3 \ + mkdir -p $BUILDDIR && cd $BUILDDIR \ + && cmake -DPYTHON_EXECUTABLE=$PYTHON3 \ .. - make pylint -j3 - make && ctest --output-on-failure + make pylint -j$NPROC + make -j$NPROC && MOOSE_NUM_THREAD=$NPROC ctest --output-on-failure -j$NPROC cd .. # Now with boost. - mkdir -p _BOOST_BUILD && cd _BOOST_BUILD \ - && cmake -DWITH_BOOST_ODE=ON -DDEBUG=ON \ + mkdir -p $BUILDDIR && cd $BUILDDIR \ + && cmake -DWITH_BOOST_ODE=ON \ -DPYTHON_EXECUTABLE=`which python3` .. - make -j4 && ctest --output-on-failure - cd .. - set +e - + make -j$NPROC && MOOSE_NUM_THREAD=$NPROC ctest -j$NPROC --output-on-failure ) set +e - diff --git a/.ci/travis_prepare_linux.sh b/.ci/travis_prepare_linux.sh new file mode 100755 index 00000000..772eef5b --- /dev/null +++ b/.ci/travis_prepare_linux.sh @@ -0,0 +1,31 @@ +#!/bin/bash - +# +# DESCRIPTION: Prepare linux build environment on travis. +# NOTES: Always run with sudo permission. +# AUTHOR: Dilawar Singh (), dilawars@ncbs.res.in +# ORGANIZATION: NCBS Bangalore +# CREATED: 01/02/2017 10:10:02 AM + +set -e -x +apt update +apt-get install -qq libxml2-dev libbz2-dev +apt-get install -qq make cmake +apt-get install -qq python-numpy python-matplotlib python-networkx python-pip +apt-get install -qq python3-numpy python3-matplotlib python3-networkx python3-pip +apt-get install -qq python-tk python3-tk +apt-get install -qq valgrind + +# Gsl +apt-get install -qq libgsl0-dev || apt-get install -qq libgsl-dev + +# Boost related. +apt-get install -qq liblapack-dev +apt-get install -qq libboost-all-dev + +# Dependencies for NML2 +apt-get install -qq python-scipy python3-scipy +apt-get install -qq python-lxml python3-lxml +apt-get install -qq python-setuptools python3-setuptools + +# Install twine +python3 -m pip install twine diff --git a/.travis/travis_prepare_osx.sh b/.ci/travis_prepare_osx.sh similarity index 100% rename from .travis/travis_prepare_osx.sh rename to .ci/travis_prepare_osx.sh diff --git a/.github/main.workflow b/.github/main.workflow new file mode 100644 index 00000000..acf33180 --- /dev/null +++ b/.github/main.workflow @@ -0,0 +1,15 @@ +workflow "build pymoose" { + resolves = "build" + on = "push" +} + +action "build" { + uses = "./" + args = "install" + env = { + CMAKE_GIT_REPO = "https://github.com/dilawar/moose-core", + CMAKE_INSTALL_DEPS_SCRIPT = ".travis/travis_prepare_linux.sh", + CMAKE_FLAGS = "-DCMAKE_INSTALL_PREFIX:PATH=/tmp/foo", + CMAKE_BUILD_THREADS = "4" + } +} diff --git a/.github/workflows/pymoose.yml b/.github/workflows/pymoose.yml new file mode 100644 index 00000000..686d19af --- /dev/null +++ b/.github/workflows/pymoose.yml @@ -0,0 +1,27 @@ +name: Python package + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [2.7, 3.7, 3.8] + + steps: + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + export DEBIAN_FRONTEND=noninteractive + sudo -E apt install -y cmake libgsl-dev g++ gcc git + sudo -E apt install python3-tk python-tk + python -m pip install numpy matplotlib --user + - name: Build + run: | + python setup.py install diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 00000000..26e6d1cf --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,22 @@ +# This file is a template, and might need editing before it works on your project. +# use the official gcc image, based on debian +# can use verions as well, like gcc:5.2 +# see https://hub.docker.com/_/gcc/ +image: gcc + +build: + stage: build + # instead of calling g++ directly you can also use some build toolkit like make + # install the necessary build tools when needed + before_script: + - apt update && apt -y install cmake git libgsl-dev + - apt -y install python3-numpy python3-matplotlib python3-pip python3-dev + - apt -y install python-numpy python-matplotlib python-pip python-dev + script: + - python3 -m pip install setuptools pip --user --upgrade + - python3 -m pip install python-libsbml --user --upgrade + - python3 -m pip install pyneuroml --user --upgrade + - python3 -m pip install sympy scipy --user --upgrade + - python3 setup.py build test + - python3 setup.py install --user + - python3 -c "import moose; moose.test()" diff --git a/.travis.yml b/.travis.yml index 0bf992ae..e7591dfb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,34 +2,34 @@ language: cpp sudo: required matrix: - include: - - os: linux - dist: xenial - - os: osx - osx_image: xcode10.2 + include: + - os: linux + dist: bionic + services: + - xvfb + - os: osx + osx_image: + - xcode11.3 notifications: - email: - recipients: - - bhalla@ncbs.res.in - - dilawar.s.rajput@gmail.com - - hrani@ncbs.res.in - on_success: change - on_failure: always + email: + recipients: + - bhalla@ncbs.res.in + - dilawar.s.rajput@gmail.com + - hrani@ncbs.res.in + on_success: change + on_failure: always addons: - apt: - update: true + apt: + update: true + before_script: -- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then nvm get head || true; fi -- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ./.travis/travis_prepare_osx.sh; fi -- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo ./.travis/travis_prepare_linux.sh; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then nvm get head || true; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ./.ci/travis_prepare_osx.sh; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo ./.ci/travis_prepare_linux.sh; fi script: -- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ./.travis/travis_build_osx.sh; fi -- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./.travis/travis_build_linux.sh; fi - -addons: - apt: - update: true + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ./.ci/travis_build_osx.sh; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./.ci/travis_build_linux.sh; fi diff --git a/.travis/travis_build_linux.sh b/.travis/travis_build_linux.sh deleted file mode 100755 index eb36a324..00000000 --- a/.travis/travis_build_linux.sh +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env bash - -#=============================================================================== -# -# FILE: travis_build_linux.sh -# -# USAGE: ./travis_build_linux.sh -# -# DESCRIPTION: Build on linux environment. -# -# OPTIONS: --- -# REQUIREMENTS: --- -# BUGS: --- -# NOTES: --- -# AUTHOR: Dilawar Singh (), dilawars@ncbs.res.in -# ORGANIZATION: NCBS Bangalore -# CREATED: 01/02/2017 10:11:46 AM -# REVISION: --- -#=============================================================================== - -set -e -set -x - -PYTHON2="/usr/bin/python2" -PYTHON3="/usr/bin/python3" -MAKEFLAGS="-j`nproc`" - -if [ ! -n "$MAKE" ]; then - MAKE="make -j`nproc`" -else - MAKE="$MAKE -j`nproc`" -fi - -unset PYTHONPATH - -# Bug: `which python` returns /opt/bin/python* etc on travis. For which numpy -# many not be available. Therefore, it is neccessary to use fixed path for -# python executable. - -$PYTHON2 -m compileall -q . -if type $PYTHON3 > /dev/null; then $PYTHON3 -m compileall -q . ; fi - -# Python2 and GSL. -echo "Currently in `pwd`" -( - mkdir -p _GSL_BUILD && cd _GSL_BUILD - cmake -DDEBUG=ON -DPYTHON_EXECUTABLE="$PYTHON2" .. - $MAKE && ctest --output-on-failure -E ".*socket_streamer.*" - sudo make install && cd /tmp - $PYTHON2 -c 'import moose;print(moose.__file__);print(moose.version())' -) - -# Python3 with GSL and BOOST. This should be the only build after we drop -# python2 support. -echo "Python3: Removed python2-networkx and install python3" -if type $PYTHON3 > /dev/null; then - sudo apt-get remove -qq python-networkx || echo "Error with apt" - sudo apt-get install -qq python3-networkx || echo "Error with apt" - # GSL. - ( - mkdir -p _GSL_BUILD_PY3 && cd _GSL_BUILD_PY3 && \ - cmake -DWITH_NSDF=ON -DPYTHON_EXECUTABLE="$PYTHON3" -DDEBUG=ON .. - $MAKE && ctest --output-on-failure -E ".*socket_streamer.*" - ) - - # BOOST - ( - mkdir -p _BOOST_BUILD_PY3 && cd _BOOST_BUILD_PY3 && \ - cmake -DWITH_NSDF=ON -DWITH_BOOST_ODE=ON -DPYTHON_EXECUTABLE="$PYTHON3" .. - $MAKE && ctest --output-on-failure -E ".*socket_streamer.*" - ) - echo "All done" -else - echo "Python3 is not found. Build disabled" -fi diff --git a/.travis/travis_prepare_linux.sh b/.travis/travis_prepare_linux.sh deleted file mode 100755 index 49afa941..00000000 --- a/.travis/travis_prepare_linux.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash - -#=============================================================================== -# -# FILE: travis_prepare_linux.sh -# -# USAGE: ./travis_prepare_linux.sh -# -# DESCRIPTION: Prepare linux build environment on travis. -# -# OPTIONS: --- -# REQUIREMENTS: --- -# BUGS: --- -# NOTES: Always run with sudo permission. -# AUTHOR: Dilawar Singh (), dilawars@ncbs.res.in -# ORGANIZATION: NCBS Bangalore -# CREATED: 01/02/2017 10:10:02 AM -# REVISION: --- -#=============================================================================== - -set -o nounset # Treat unset variables as an error -set +e # Let installation fail in some command - -apt-get install -qq libxml2-dev libbz2-dev -apt-get install -qq make cmake -apt-get install -qq python-numpy python-matplotlib python-networkx python-pip -apt-get install -qq python3-lxml python-lxml -apt-get install -qq python3-numpy python3-matplotlib python3-dev -apt-get install -qq python-pip python3-pip -apt-get install -qq python-tk python3-tk -apt-get install -qq libgraphviz-dev - -# Gsl -apt-get install -qq libgsl0-dev || apt-get install -qq libgsl-dev - -# hdf5 -apt-get install -qq libhdf5-serial-dev - -# Boost related. -apt-get install -qq liblapack-dev -apt-get install -qq libboost-all-dev - -# Dependencies for NML2 -apt-get install -qq python-scipy python3-scipy -apt-get install -qq python-lxml python3-lxml -apt-get install -qq python-setuptools python3-setuptools -apt-get install -qq python-tornado python3-tornado -/usr/bin/python2 -m pip install pyNeuroML libNeuroML -/usr/bin/python3 -m pip install pyNeuroML libNeuroML diff --git a/CMakeLists.txt b/CMakeLists.txt index 35a86c98..d373ed26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,36 +1,40 @@ cmake_minimum_required(VERSION 2.8 FATAL_ERROR) -project(pymoose) -set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules") +# Project to build MOOSE's python module. +project(PyMOOSE) + +# cmake related macros. +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") include(CheckCXXCompiler.cmake) include(CheckIncludeFileCXX) -# getgit revision number -find_program( GIT_EXEC git ) -if(GIT_EXEC) - execute_process( - COMMAND ${GIT_EXEC} rev-parse --short HEAD - OUTPUT_VARIABLE GIT_HEAD - OUTPUT_STRIP_TRAILING_WHITESPACE - ) -else(GIT_EXEC) - set(GIT_HEAD 'HEAD') - message(STATUS "Couldn't fetch version from git repo" ) +# We find python executable here. Though mainly used inside pymoose. +# FIXME: When cmake 3.12 is widely available use the following: +# find_package(Python3 COMPONENTS Interpreter Numpy) +# set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE}) +set(Python_ADDITIONAL_VERSIONS 2.7) +find_package(PythonInterp 3.5) +if(NOT PYTHONINTERP_FOUND) + find_package(PythonInterp 2.7) endif() -# If from command line, version info is not passed, use the git to generate a -# version file. If GIT fails, use the previous known version. -if(NOT VERSION_MOOSE) - set(VERSION_MOOSE "3.2.0-${GIT_HEAD}") +# Disable rpath on OSX. +if(APPLE) + set(CMAKE_MACOSX_RPATH OFF) endif() -add_definitions( -DMOOSE_VERSION="${VERSION_MOOSE}") -message( STATUS "MOOSE Version ${VERSION_MOOSE}" ) -# Write VERSION to a file VERSION so that setup.cmake.py can use it. -set(VERSION_FILE ${CMAKE_CURRENT_SOURCE_DIR}/python/VERSION) -file(WRITE ${VERSION_FILE} ${VERSION_MOOSE} ) -message(STATUS "| Writing ${VERSION_MOOSE} to ${VERSION_FILE}" ) +# NOTE: version should be changed in setup.py file. +# If moose version is not given, use setup.py file to get the default version. +if(NOT VERSION_MOOSE) + execute_process(COMMAND ${PYTHON_EXECUTABLE} setup.py --version + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE VERSION_MOOSE + OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() + +add_definitions(-DMOOSE_VERSION="${VERSION_MOOSE}") +message(STATUS "MOOSE Version ${VERSION_MOOSE}") # This snippet is from LLVM project. # Sanity check our source directory to make sure that we are not trying to @@ -50,21 +54,6 @@ if( CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR AND NOT MSVC_IDE ) ) endif() -# uninstall target -configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" - IMMEDIATE @ONLY - ) - -add_custom_target(uninstall - COMMAND ${CMAKE_COMMAND} -P - ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake - ) - -# This is for testing purpose. -link_directories(${CMAKE_CURRENT_BINARY_DIR}) - ################################ CMAKE OPTIONS ################################## option(WITH_NSDF "Enable NSDF support. Requires hdf5" OFF ) @@ -84,7 +73,6 @@ option(WITH_ASAN "Use AddressSanitizer in DEBUG mode." OFF) # Default definitions. add_definitions(-DUSE_GENESIS_PARSER) - if(DEBUG OR "${CMAKE_BUILD_TYPE}" STREQUAL "Debug") message(STATUS "Building for Debug/Unit testing") add_definitions(-DDO_UNIT_TESTS -O) @@ -96,11 +84,7 @@ elseif(ENABLE_UNIT_TESTS) else() message(STATUS "Building for Release/No unit tests.") set(CMAKE_BUILD_TYPE Release) - add_definitions(-UDO_UNIT_TESTS -O3 -DDISABLE_DEBUG) - - # DO NOT Treat all warnings as errors. With some compilers and newer versions - # this often causes headache. - # add_definitions(-Werror) + add_definitions(-UDO_UNIT_TESTS -O3 -DDISABLE_DEBUG) endif() if(GPROF AND "${CMAKE_BUILD_TYPE}" STREQUAL "Debug") @@ -118,26 +102,24 @@ if(WITH_ASAN AND "${CMAKE_BUILD_TYPE}" STREQUAL "Debug") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -fsanitize=address") endif() +if(WITH_GSL) + set(WITH_BOOST OFF) + set(WITH_BOOST_ODE OFF) +elseif(WITH_BOOST) + set(WITH_BOOST_ODE ON) + set(WITH_GSL OFF) +endif() + ################################### TARGETS #################################### +link_directories(${CMAKE_BINARY_DIR}) add_library(libmoose SHARED basecode/main.cpp) add_executable(moose.bin basecode/main.cpp) -################################### SETUP BUILD ################################ +################################### SETUP BUILD ################################ # default include paths. include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) - -if(WITH_BOOST) - set(WITH_BOOST_ODE ON) - set(WITH_GSL OFF) -endif(WITH_BOOST) - -# If using BOOST ODE2 library to solve ODE system, then don't use GSL. -if(WITH_BOOST_ODE) - set(WITH_GSL OFF) -endif(WITH_BOOST_ODE) - set_target_properties(libmoose PROPERTIES COMPILE_DEFINITIONS "MOOSE_LIB") set_target_properties(libmoose PROPERTIES PREFIX "") @@ -170,20 +152,11 @@ if(WITH_GSL) "====================================================================\n" ) endif(NOT GSL_FOUND) - add_definitions(-DUSE_GSL) - # GSL is also used in RNG (whenever applicable), therefore include paths are - # top level. - include_directories( ${GSL_INCLUDE_DIRS} ) elseif(WITH_BOOST_ODE) find_package(Boost 1.53 REQUIRED) find_package(LAPACK REQUIRED) endif() -# if boost ode is being used, don't use GSL. -if(WITH_BOOST_ODE) - add_definitions(-DUSE_BOOST_ODE -UUSE_GSL) - include_directories(${Boost_INCLUDE_DIRS}) -endif() # Openmpi if(WITH_MPI) @@ -239,10 +212,6 @@ if(WITH_MPI) endif() endif(WITH_MPI) -# Always use private version of muparser. We have some custom edits. -add_subdirectory(external/muparser) -list(APPEND MOOSE_LIBRARIES muparser) - # Add subdirectroeis add_subdirectory(basecode) add_subdirectory(msg) @@ -259,16 +228,18 @@ add_subdirectory(ksolve) add_subdirectory(hsolve) add_subdirectory(diffusion) add_subdirectory(device) -add_subdirectory(benchmarks) add_subdirectory(kinetics) add_subdirectory(synapse) add_subdirectory(intfire) +add_subdirectory(external/libsoda) + +# development related. +add_subdirectory(devel) ###################################### LINKING ################################# list(APPEND MOOSE_LIBRARIES moose_builtins msg - benchmarks shell randnum scheduling @@ -283,6 +254,7 @@ list(APPEND MOOSE_LIBRARIES signeur diffusion ksolve + lsoda device basecode ) @@ -327,14 +299,17 @@ endif(APPLE) add_dependencies(moose.bin libmoose) target_link_libraries(moose.bin moose ${CMAKE_DL_LIBS}) + if( WITH_BOOST ) target_link_libraries( moose.bin ${Boost_LIBRARIES} ) endif( WITH_BOOST ) ######################### BUILD PYMOOSE ######################################## + + # This target is built by pymoose/CMakeLists.txt file. -add_subdirectory( pymoose ) +add_subdirectory(pymoose) # always override debian default installation directory. It will be installed in # site-packages instead of dist-packages. @@ -352,69 +327,19 @@ set(EXTRA_ARGS "--prefix ${CMAKE_INSTALL_PREFIX} ${DISTUTILS_EXTRA_ARGS}") # suitable for DEBIAN systems. if(${_platform_desc} MATCHES ".*(Ubuntu|debian).*") list(APPEND EXTRA_ARGS "--install-layout=deb") - file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/python/setup.cfg + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/setup.cfg "[install]\nprefix=/usr\ninstall-layout=deb" ) endif() -# Set PYMOOSE binary distribution build and install directories. -# Target for creating bdist. This is handy for creating bdist for packaging. -# Save the binary distribution (tar.gz) to PYMOOSE_BDIST_DIR. -find_package(PythonInterp REQUIRED) -if(NOT PYMOOSE_BDIST_DIR) - set(PYMOOSE_BDIST_DIR ${CMAKE_BINARY_DIR}/bdist) -endif( ) - -# If no one hsa set the PYMOOSE bdist installation directory, use default. -if(NOT PYMOOSE_BDIST_INSTALL_DIR) - set(PYMOOSE_BDIST_INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/pymoose_bdist_install) -endif() -file(MAKE_DIRECTORY ${PYMOOSE_BDIST_INSTALL_DIR}) - -# We need a custom name for bdist; same on all platform. -set(_platform "CMAKE" ) -set(PYMOOSE_BDIST_FILE ${PYMOOSE_BDIST_DIR}/pymoose-${VERSION_MOOSE}.${_platform}.tar.gz) -message(STATUS "binary distribution file ${PYMOOSE_BDIST_FILE}") -add_custom_target(bdist ALL DEPENDS ${PYMOOSE_BDIST_FILE} ) - -# Any command using setup.cmake.py must run in the same directory. Use option -# `--relative` to prefix is aways fixed. -add_custom_command( OUTPUT ${PYMOOSE_BDIST_FILE} - COMMAND ${PYTHON_EXECUTABLE} setup.cmake.py bdist_dumb -p ${_platform} - -d ${PYMOOSE_BDIST_DIR} --relative - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/python - COMMENT "bdist is saved to ${PYMOOSE_BDIST_DIR}" - VERBATIM - ) -add_custom_command(TARGET bdist POST_BUILD - COMMAND ${CMAKE_COMMAND} -E chdir ${PYMOOSE_BDIST_INSTALL_DIR} tar xf ${PYMOOSE_BDIST_FILE} - COMMENT "Unarchiving bdist file ${PYMOOSE_BDIST_FILE} to ${PYMOOSE_BDIST_INSTALL_DIR}" - VERBATIM - ) - -# Copy python files from source to current binary directory. Make sure to call -# this before building bdist. -file(GLOB_RECURSE PYTHON_SRCS "${CMAKE_SOURCE_DIR}/python/*") -add_custom_target(copy_pymoose DEPENDS ${PYTHON_SRCS} - COMMAND ${CMAKE_COMMAND} -E copy_directory - ${CMAKE_CURRENT_SOURCE_DIR}/python ${CMAKE_CURRENT_BINARY_DIR}/python - COMMENT "Copying required python files and other files to build directory" - VERBATIM - ) - -add_dependencies( bdist copy_pymoose ) -add_dependencies( copy_pymoose _moose ) ######################### INSTALL ############################################## install(TARGETS moose.bin DESTINATION bin CONFIGURATIONS Debug) install(TARGETS libmoose DESTINATION lib CONFIGURATIONS Debug) -# install pymoose bdist. -install(DIRECTORY ${PYMOOSE_BDIST_INSTALL_DIR}/ - DESTINATION ${CMAKE_INSTALL_PREFIX} - CONFIGURATIONS Release Debug - ) +# NOTE: Install macro for _moose (pymoose) has been moved to +# pymoose/CMakeLists.txt file. # Print message to start build process if(${CMAKE_BUILD_TOOL} MATCHES "make") @@ -429,9 +354,8 @@ endif() ############################ CTEST ###################################### include( CTest ) -# If CTEST_OUTPUT_ON_FAILURE environment variable is set, the output is printed -# onto the console if a test fails. -set(ENV{CTEST_OUTPUT_ON_FAILURE} ON) +set(CTEST_NIGHTLY_START_TIME "05:30:00 UTC") +set(CTEST_SUBMIT_URL "http://my.cdash.org/submit.php?project=moose") if(DEBUG OR "${CMAKE_BUILD_TYPE}" STREQUAL "Debug") # Run this test in debug mode. In Release mode, this does not do anything. @@ -441,33 +365,58 @@ if(DEBUG OR "${CMAKE_BUILD_TYPE}" STREQUAL "Debug") add_test(NAME moose.bin-raw-run COMMAND moose.bin -u -q) endif() -## PyMOOSE tests. -set(PYMOOSE_TEST_DIRECTORY ${CMAKE_SOURCE_DIR}/tests/python) - -# Collect all python script in tests folder and run them. +# Core tests. +set(PYMOOSE_TEST_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests/py_moose) file(GLOB PY_TEST_SCRIPTS "${PYMOOSE_TEST_DIRECTORY}/test_*.py" ) - - -# Run python tests. -foreach( _test_script ${PY_TEST_SCRIPTS} ) - get_filename_component( _test_name ${_test_script} NAME_WE) - add_test( NAME ${_test_name} +foreach(_test_script ${PY_TEST_SCRIPTS} ) + get_filename_component(_name_we ${_test_script} NAME_WE) + set(_test_name "core_${_name_we}") + add_test(NAME ${_test_name} COMMAND ${PYTHON_EXECUTABLE} ${_test_script} - WORKING_DIRECTORY ${PYMOOSE_TEST_DIRECTORY} + WORKING_DIRECTORY ${PYMOOSE_TEST_DIRECTORY}) + set_tests_properties(${_test_name} + PROPERTIES ENVIRONMENT "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}/python" ) - set_tests_properties( ${_test_name} +endforeach() + +# Tests for supported formats such as neuroml, sbml etc. +set(SUPPORT_TEST_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests/support) +file(GLOB PY_TEST_SCRIPTS "${SUPPORT_TEST_DIRECTORY}/test_*.py" ) +foreach(_test_script ${PY_TEST_SCRIPTS} ) + get_filename_component(_name_we ${_test_script} NAME_WE) + set(_test_name "support_${_name_we}") + add_test(NAME ${_test_name} + COMMAND ${PYTHON_EXECUTABLE} ${_test_script} + WORKING_DIRECTORY ${SUPPORT_TEST_DIRECTORY}) + set_tests_properties(${_test_name} PROPERTIES ENVIRONMENT "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}/python" ) -endforeach( ) - -# Alpha tests. These should not run by default. -set(MOOSE_ALPHA_TEST_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests/alpha) -file(GLOB PY_ALPHA_TEST_SCRIPTS "${PYMOOSE_ALPHA_TEST_DIRECTORY}/*.py" ) -foreach( _test_script ${PY_ALPHA_TEST_SCRIPTS} ) - get_filename_component( _test_name ${_test_script} NAME_WE) +endforeach() + +# rdesigneur tests. These tests require matplotlib. +set(RDES_TEST_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests/py_rdesigneur) +file(GLOB RDES_TEST_SCRIPTS "${RDES_TEST_DIRECTORY}/test_*.py" ) +foreach(_test_script ${RDES_TEST_SCRIPTS}) + get_filename_component(_name_we ${_test_script} NAME_WE) + set(_test_name "rdes_${_name_we}") + add_test(NAME ${_test_name} + COMMAND ${PYTHON_EXECUTABLE} ${_test_script} + WORKING_DIRECTORY ${RDES_TEST_DIRECTORY} + ) + set_tests_properties(${_test_name} PROPERTIES + ENVIRONMENT "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}/python;MOOSE_NUM_THREADS=4" + ) +endforeach() + +# FIXME TESTS. These should not run by default. We need to fix them. +set(PYMOOSE_FIXME_TEST_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/devel/fixme) +file(GLOB PY_FIXME_TEST_SCRIPTS "${PYMOOSE_FIXME_TEST_DIRECTORY}/*.py" ) +foreach( _test_script ${PY_FIXME_TEST_SCRIPTS} ) + get_filename_component( _name_we ${_test_script} NAME_WE) + set(_test_name "alpha_${_name_we}") add_test( NAME ${_test_name} COMMAND ${PYTHON_EXECUTABLE} ${_test_script} - CONFIGURATIONS Devel + CONFIGURATIONS alpha WORKING_DIRECTORY ${PYMOOSE_ALPHA_TEST_DIRECTORY} ) set_tests_properties( ${_test_name} @@ -476,25 +425,83 @@ foreach( _test_script ${PY_ALPHA_TEST_SCRIPTS} ) endforeach( ) # Regression and github issues. These should not run by default. -set(PYMOOSE_ISSUES_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests/issues) +set(PYMOOSE_ISSUES_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/devel/issues) file(GLOB PY_ISSUES_SCRIPTS "${PYMOOSE_ISSUES_DIRECTORY}/*.py" ) -foreach( _test_script ${PY_ISSUES_SCRIPTS} ) +foreach(_test_script ${PY_ISSUES_SCRIPTS}) get_filename_component( _test_name ${_test_script} NAME_WE) - add_test( NAME ${_test_name} + add_test(NAME ${_test_name} COMMAND ${PYTHON_EXECUTABLE} ${_test_script} CONFIGURATIONS Devel WORKING_DIRECTORY ${PYMOOSE_ISSUES_DIRECTORY} ) - set_tests_properties( ${_test_name} + set_tests_properties(${_test_name} PROPERTIES ENVIRONMENT "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}/python" ) -endforeach( ) - -# add pylint target. -set(PYSCRIPTS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/python ) +endforeach() + +################################# COVERAGE ################################### + +add_custom_target(coverage) +set(PYTEST_TEST_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests) +file(GLOB_RECURSE PYTEST_TEST_SCRIPTS ${PYTEST_TEST_DIRECTORY}/test_*.py) + +foreach(_test_script ${PYTEST_TEST_SCRIPTS}) + get_filename_component(_name_we ${_test_script} NAME_WE) + set(_test_name "pytest_${_name_we}") + # message(STATUS "Adding test ${_test_name}") + add_custom_target(${_test_name} + # We collect coverage data but do not show report during each test. + # We show report at the end of all tests. Set `--cov-report=` + COMMAND ${PYTHON_EXECUTABLE} -m pytest + --cov=moose --cov=rdesigneur --cov-append --cov-report= + ${_test_script} + DEPENDS _moose + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Executing ${_test_script} using pytest" + VERBATIM) + add_dependencies(coverage ${_test_name}) +endforeach() + +# Generate report at the end. +add_custom_command(TARGET coverage POST_BUILD + COMMAND ${PYTHON_EXECUTABLE} -m coverage report + COMMAND ${PYTHON_EXECUTABLE} -m coverage html + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Genearting coverage report" + VERBATIM) + + +########################### RELEASE ######################################### +set(PYMOOSE_SDIST_FILE ${CMAKE_BINARY_DIR}/pymoose-${VERSION_MOOSE}.tar.gz) +add_custom_target(sdist + COMMAND ${PYTHON_EXECUTABLE} setup.py sdist --formats=gztar + -d ${CMAKE_BINARY_DIR} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Creating sdist ${PYMOOSE_SDIST_FILE}" + VERBATIM) + +add_custom_target(upload_test DEPENDS sdist + COMMAND ${PYTHON_EXECUTABLE} -m twine upload + --user $ENV{PYMOOSE_PYPI_USER} --password $ENV{PYMOOSE_PYPI_PASSWORD} + --repository-url https://test.pypi.org/legacy/ + ${PYMOOSE_SDIST_FILE} + COMMENT "Uploading source distribution to test.pypi.org" + VERBATIM) + +add_custom_target(upload DEPENDS sdist + COMMAND ${PYTHON_EXECUTABLE} -m twine upload + --user $ENV{PYMOOSE_PYPI_USER} --password $ENV{PYMOOSE_PYPI_PASSWORD} + ${PYMOOSE_SDIST_FILE} + COMMENT "Uploading source distribution to PyPI" + VERBATIM) + +####################### DEVELOPMENT ######################################## + +# PYLINT target. +set(PYSCRIPTS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/python) file(GLOB_RECURSE PY_SCRIPTS "python/*.py") -add_custom_target( pylint ) -foreach( _py_script ${PY_SCRIPTS} ) +add_custom_target(pylint) +foreach(_py_script ${PY_SCRIPTS}) get_filename_component( _py_name ${_py_script} NAME_WE) file( READ ${_py_script} pytext) string(MD5 _md5 "${pytext}") @@ -512,6 +519,3 @@ foreach( _py_script ${PY_SCRIPTS} ) add_dependencies(pylint ${TGT_NAME} ) endforeach( ) -############################ CPACK ###################################### -# This is not maintained anymore since packaging is done using OpenBuildService -include(${CMAKE_CURRENT_SOURCE_DIR}/cmake_moose_cpack.cmake) diff --git a/CheckCXXCompiler.cmake b/CheckCXXCompiler.cmake index b1520579..5b1e7596 100644 --- a/CheckCXXCompiler.cmake +++ b/CheckCXXCompiler.cmake @@ -1,12 +1,14 @@ +# Compiler check. +# Must support c++11 +# If python2 is supported then we can not use c++17. if(COMPILER_IS_TESTED) return() endif() ########################### COMPILER MACROS ##################################### include(CheckCXXCompilerFlag) -CHECK_CXX_COMPILER_FLAG( "-std=c++11" COMPILER_SUPPORTS_CXX11 ) -CHECK_CXX_COMPILER_FLAG( "-std=c++0x" COMPILER_SUPPORTS_CXX0X ) -CHECK_CXX_COMPILER_FLAG( "-Wno-strict-aliasing" COMPILER_WARNS_STRICT_ALIASING ) +CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11 ) +CHECK_CXX_COMPILER_FLAG("-Wno-strict-aliasing" COMPILER_WARNS_STRICT_ALIASING ) # Turn warning to error: Not all of the options may be supported on all # versions of compilers. be careful here. @@ -16,13 +18,18 @@ add_definitions(-Wall -Wno-unused-function #-Wno-unused-private-field ) + if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # gcc-4.9.0 has regex supports though moose will compile with 4.8.x; + # won't work. + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.9") + message(FATAL_ERROR "Insufficient gcc version. Minimum requried 4.9") + endif() add_definitions( -Wno-unused-local-typedefs ) elseif(("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") OR ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")) add_definitions( -Wno-unused-local-typedef ) endif() - add_definitions(-fPIC) if(COMPILER_WARNS_STRICT_ALIASING) add_definitions( -Wno-strict-aliasing ) @@ -38,18 +45,13 @@ endif(COMPILER_SUPPORT_UNUSED_BUT_SET_VARIABLE_NO_WARN) if(COMPILER_SUPPORTS_CXX11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") - add_definitions( -DENABLE_CPP11 ) if(APPLE) - #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++" ) - # message(STATUS "NOTE: Making clang to inline more aggresively" ) add_definitions( -mllvm -inline-threshold=1000 ) endif(APPLE) else(COMPILER_SUPPORTS_CXX11) - add_definitions( -DBOOST_NO_CXX11_SCOPED_ENUMS -DBOOST_NO_SCOPED_ENUMS ) - message(FATAL_ERROR "\ - The compiler ${CMAKE_CXX_COMPILER} is too old. \ - Please use a compiler which has c++11 support. - ") + message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} is too old. \n" + "Please use a compiler which has c++11 support." + ) endif(COMPILER_SUPPORTS_CXX11) set(COMPILER_IS_TESTED ON) diff --git a/INSTALL.md b/INSTALL.md index 63af4f3a..faae4244 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,50 +1,71 @@ -# Building MOOSE from source +# Building MOOSE -To build `MOOSE` from source, you need `cmake`. +To build `MOOSE` from source, you need `cmake` and `python-setuptools`. We +recommend to use Python 3.5 or higher. Python 2.7 is also supported. -Download the latest source code of moose from github. - - $ git clone -b master https://github.com/BhallaLab/moose-core --depth 50 - -## Install dependencies +Before running the following command to build and install, make sure that +followings are installed. - gsl-1.16 or higher. -- libhdf5-dev (optional) -- python-dev - python-numpy -On Ubuntu-14.04 or higher, these can be installed with: +On Ubuntu-16.04 or higher, these dependencies can be installed with: - sudo apt-get install python-dev python-numpy libhdf5-dev cmake libgsl0-dev g++ +``` +sudo apt-get install python-pip python-numpy cmake libgsl-dev g++ +``` -SBML support is enabled by installing [python-libsbml](http://sbml.org/Software/libSBML/docs/python-api/libsbml-installation.html). Alternatively, it can be installed by using `python-pip` +Now use `pip` to download and install the `pymoose`. - $ sudo pip install python-libsbml +``` +$ pip install git+https://github.com/BhallaLab/moose-core --user +``` + +## Using cmake (For developers) + +`pip` builds `pymoose` with default options, it runs `cmake` behind the scene. +If you are developing moose, build it with different options, or needs to test +and profile it, `cmake` based flow is recommended. -## Use `cmake` to build moose: +Install the required dependencies and download the latest source code of moose +from github. - $ cd /path/to/moose-core + $ git clone https://github.com/BhallaLab/moose-core --depth 50 + $ cd moose-core $ mkdir _build $ cd _build $ cmake .. $ make -j3 $ ctest -j3 --output-on-failure -This will build moose, `ctest` will run few tests to check if build process was successful. +This will build moose, `ctest` will run few tests to check if build process was +successful. -To install MOOSE into non-standard directory, pass additional argument `-DCMAKE_INSTALL_PREFIX=path/to/install/dir` to cmake. +To install MOOSE into non-standard directory, pass additional argument +`-DCMAKE_INSTALL_PREFIX=path/to/install/dir` to during configuration. E.g., -### Python3 + $ mkdir _build && cd _build # inside moose-core directory. + $ cmake -DCMAKE_INSTALL_PREFIX=$HOME/.local .. + $ make && make install - cmake -DPYTHON_EXECUTABLE=/opt/bin/python3 .. +Will build and install pymoose to `~/.local`. -### Install +To use a non-default python installation, set +`PYTHON_EXECUTATBLE=/path/to/python` e.g., - $ sudo make install + $ cmake -DPYTHON_EXECUTABLE=/opt/bin/python3 .. ## Post installation Now you can import moose in a Python script or interpreter with the statement: - import moose - moose.test() # will take time. Not all tests will pass. + >>> import moose + >>> moose.test() # will take time. Not all tests will pass. + +# Notes + +SBML support is enabled by installing +[python-libsbml](http://sbml.org/Software/libSBML/docs/python-api/libsbml-installation.html). +Alternatively, it can be installed by using `python-pip` + + $ sudo pip install python-libsbml diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 00000000..c0378e2a --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,36 @@ +include AUTHORS +include CMakeLists.txt +include CONTRIBUTING.md +include CheckCXXCompiler.cmake +include INSTALL.md +include LICENSE +include MANIFEST.in +include README.md +include cmake_moose_cpack.cmake +include cmake_uninstall.cmake.in +recursive-include basecode * +recursive-include benchmarks * +recursive-include biophysics * +recursive-include builtins * +recursive-include cmake * +recursive-include device * +recursive-include diffusion * +recursive-include dist * +recursive-include examples * +recursive-include external * +recursive-include hsolve * +recursive-include intfire * +recursive-include kinetics * +recursive-include ksolve * +recursive-include mesh * +recursive-include mpi * +recursive-include msg * +recursive-include pymoose * +recursive-include python * +recursive-include randnum * +recursive-include scheduling * +recursive-include shell * +recursive-include signeur * +recursive-include synapse * +recursive-include tests * +recursive-include utility * diff --git a/basecode/EpFunc.cpp b/basecode/EpFunc.cpp index 026ca346..afb379e8 100644 --- a/basecode/EpFunc.cpp +++ b/basecode/EpFunc.cpp @@ -12,7 +12,6 @@ template<> Neutral* getEpFuncData< Neutral >( const Eref& e ) { - static Neutral dummy; - return &dummy; + static Neutral dummy; + return &dummy; } -////////////////////////////////////////////////////////////////// diff --git a/basecode/EpFunc.h b/basecode/EpFunc.h index 4dae3cd4..3fcb1e07 100644 --- a/basecode/EpFunc.h +++ b/basecode/EpFunc.h @@ -17,7 +17,7 @@ */ template< class T > T* getEpFuncData( const Eref& e ) { - return reinterpret_cast< T* >( e.data() ) ; + return reinterpret_cast< T* >( e.data() ) ; } /** @@ -36,11 +36,11 @@ template<> Neutral* getEpFuncData< Neutral >( const Eref& e ) } * Try externing the template itself. */ + template<> Neutral* getEpFuncData< Neutral >( const Eref& e ); // Function is implemented in EpFunc.cpp. - /** * This set of classes is derived from OpFunc, and take extra args * for the qinfo and Eref. @@ -48,119 +48,126 @@ template<> Neutral* getEpFuncData< Neutral >( const Eref& e ); template< class T > class EpFunc0: public OpFunc0Base { - public: - EpFunc0( void ( T::*func )( const Eref& e ) ) - : func_( func ) - {;} - - void op( const Eref& e ) const { - ( reinterpret_cast< T* >( e.data() )->*func_ )( e ); - } - - private: - void ( T::*func_ )( const Eref& e ); +public: + EpFunc0( void ( T::*func )( const Eref& e ) ) + : func_( func ) + {;} + + void op( const Eref& e ) const + { + ( reinterpret_cast< T* >( e.data() )->*func_ )( e ); + } + +private: + void ( T::*func_ )( const Eref& e ); }; template< class T, class A > class EpFunc1: public OpFunc1Base< A > { - public: - EpFunc1( void ( T::*func )( const Eref&, A ) ) - : func_( func ) - {;} - - void op( const Eref& e, A arg ) const { - ( reinterpret_cast< T* >( e.data() )->*func_ )( e, arg ); - } - - private: - void ( T::*func_ )( const Eref& e, A ); +public: + EpFunc1( void ( T::*func )( const Eref&, A ) ) + : func_( func ) + {;} + + void op( const Eref& e, A arg ) const + { + ( reinterpret_cast< T* >( e.data() )->*func_ )( e, arg ); + } + +private: + void ( T::*func_ )( const Eref& e, A ); }; template< class T, class A1, class A2 > class EpFunc2: - public OpFunc2Base< A1, A2 > + public OpFunc2Base< A1, A2 > { - public: - EpFunc2( void ( T::*func )( const Eref&, A1, A2 ) ) - : func_( func ) - {;} - - void op( const Eref& e, A1 arg1, A2 arg2 ) const { - ( reinterpret_cast< T* >( e.data() )->*func_ )( e, arg1, arg2 ); - } - - private: - void ( T::*func_ )( const Eref& e, A1, A2 ); +public: + EpFunc2( void ( T::*func )( const Eref&, A1, A2 ) ) + : func_( func ) + {;} + + void op( const Eref& e, A1 arg1, A2 arg2 ) const + { + ( reinterpret_cast< T* >( e.data() )->*func_ )( e, arg1, arg2 ); + } + +private: + void ( T::*func_ )( const Eref& e, A1, A2 ); }; template< class T, class A1, class A2, class A3 > class EpFunc3: - public OpFunc3Base< A1, A2, A3 > + public OpFunc3Base< A1, A2, A3 > { - public: - EpFunc3( void ( T::*func )( const Eref&, A1, A2, A3 ) ) - : func_( func ) - {;} - - void op( const Eref& e, A1 arg1, A2 arg2, A3 arg3 ) const { - ( reinterpret_cast< T* >( e.data() )->*func_ )( - e, arg1, arg2, arg3 ); - } - - private: - void ( T::*func_ )( const Eref& e, A1, A2, A3 ); +public: + EpFunc3( void ( T::*func )( const Eref&, A1, A2, A3 ) ) + : func_( func ) + {;} + + void op( const Eref& e, A1 arg1, A2 arg2, A3 arg3 ) const + { + ( reinterpret_cast< T* >( e.data() )->*func_ )( + e, arg1, arg2, arg3 ); + } + +private: + void ( T::*func_ )( const Eref& e, A1, A2, A3 ); }; template< class T, class A1, class A2, class A3, class A4 > class EpFunc4: - public OpFunc4Base< A1, A2, A3, A4 > + public OpFunc4Base< A1, A2, A3, A4 > { - public: - EpFunc4( void ( T::*func )( const Eref&, A1, A2, A3, A4 ) ) - : func_( func ) - {;} - - void op( const Eref& e, A1 arg1, A2 arg2, A3 arg3, A4 arg4 ) const { - ( reinterpret_cast< T* >( e.data() )->*func_ )( - e, arg1, arg2, arg3, arg4 ); - } - - private: - void ( T::*func_ )( const Eref& e, A1, A2, A3, A4 ); +public: + EpFunc4( void ( T::*func )( const Eref&, A1, A2, A3, A4 ) ) + : func_( func ) + {;} + + void op( const Eref& e, A1 arg1, A2 arg2, A3 arg3, A4 arg4 ) const + { + ( reinterpret_cast< T* >( e.data() )->*func_ )( + e, arg1, arg2, arg3, arg4 ); + } + +private: + void ( T::*func_ )( const Eref& e, A1, A2, A3, A4 ); }; template< class T, class A1, class A2, class A3, class A4, class A5 > - class EpFunc5: public OpFunc5Base< A1, A2, A3, A4, A5 > +class EpFunc5: public OpFunc5Base< A1, A2, A3, A4, A5 > { - public: - EpFunc5( void ( T::*func )( const Eref&, A1, A2, A3, A4, A5 ) ) - : func_( func ) - {;} - - void op( const Eref& e, - A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5 ) const { - ( reinterpret_cast< T* >( e.data() )->*func_ )( - e, arg1, arg2, arg3, arg4, arg5 ); - } - private: - void ( T::*func_ )( const Eref& e, A1, A2, A3, A4, A5 ); +public: + EpFunc5( void ( T::*func )( const Eref&, A1, A2, A3, A4, A5 ) ) + : func_( func ) + {;} + + void op( const Eref& e, + A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5 ) const + { + ( reinterpret_cast< T* >( e.data() )->*func_ )( + e, arg1, arg2, arg3, arg4, arg5 ); + } +private: + void ( T::*func_ )( const Eref& e, A1, A2, A3, A4, A5 ); }; template< class T, - class A1, class A2, class A3, class A4, class A5, class A6 > - class EpFunc6: public OpFunc6Base< A1, A2, A3, A4, A5, A6 > + class A1, class A2, class A3, class A4, class A5, class A6 > +class EpFunc6: public OpFunc6Base< A1, A2, A3, A4, A5, A6 > { - public: - EpFunc6( void ( T::*func )( const Eref&, A1, A2, A3, A4, A5, A6 ) ) - : func_( func ) - {;} - - void op( const Eref& e, - A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5, A6 arg6 ) - const { - ( reinterpret_cast< T* >( e.data() )->*func_ )( - e, arg1, arg2, arg3, arg4, arg5, arg6 ); - } - - private: - void ( T::*func_ )( const Eref& e, A1, A2, A3, A4, A5, A6 ); +public: + EpFunc6( void ( T::*func )( const Eref&, A1, A2, A3, A4, A5, A6 ) ) + : func_( func ) + {;} + + void op( const Eref& e, + A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5, A6 arg6 ) + const + { + ( reinterpret_cast< T* >( e.data() )->*func_ )( + e, arg1, arg2, arg3, arg4, arg5, arg6 ); + } + +private: + void ( T::*func_ )( const Eref& e, A1, A2, A3, A4, A5, A6 ); }; /** @@ -173,30 +180,31 @@ template< class T, */ template< class T, class A > class GetEpFunc: public GetOpFuncBase< A > { - public: - GetEpFunc( A ( T::*func )( const Eref& e ) const ) - : func_( func ) - {;} - - void op( const Eref& e, vector< A >* ret ) const { - ret->push_back( returnOp( e ) ); - } - /* - void op( const Eref& e, ObjId recipient, FuncId fid ) const { - const OpFunc *f = recipient.element()->cinfo()->getOpFunc( fid); - const OpFunc1Base< A >* recvOpFunc = - dynamic_cast< const OpFunc1Base< A >* >( f ); - assert( recvOpFunc ); - recvOpFunc->op( recipient.eref(), returnOp( e ) ); - } - */ - - A returnOp( const Eref& e ) const { - return ( getEpFuncData< T >( e )->*func_ )( e ); - } - - private: - A ( T::*func_ )( const Eref& e ) const; +public: + GetEpFunc( A ( T::*func )( const Eref& e ) const ) : func_( func ) + {;} + + void op( const Eref& e, vector< A >* ret ) const + { + ret->push_back( returnOp( e ) ); + } + /* + void op( const Eref& e, ObjId recipient, FuncId fid ) const { + const OpFunc *f = recipient.element()->cinfo()->getOpFunc( fid); + const OpFunc1Base< A >* recvOpFunc = + dynamic_cast< const OpFunc1Base< A >* >( f ); + assert( recvOpFunc ); + recvOpFunc->op( recipient.eref(), returnOp( e ) ); + } + */ + + A returnOp( const Eref& e ) const + { + return ( getEpFuncData< T >( e )->*func_ )( e ); + } + +private: + A ( T::*func_ )( const Eref& e ) const; }; @@ -210,30 +218,32 @@ template< class T, class A > class GetEpFunc: public GetOpFuncBase< A > * value. The EpFunc then sends back a message with the info. */ template< class T, class L, class A > class GetEpFunc1: - public LookupGetOpFuncBase< L, A > + public LookupGetOpFuncBase< L, A > { - public: - GetEpFunc1( A ( T::*func )( const Eref& e, L ) const ) - : func_( func ) - {;} - - - void op( const Eref& e, L index, ObjId recipient, FuncId fid ) - const { - const OpFunc *f = recipient.element()->cinfo()->getOpFunc( fid); - const OpFunc1Base< A >* recvOpFunc = - dynamic_cast< const OpFunc1Base< A >* >( f ); - assert( recvOpFunc ); - recvOpFunc->op( recipient.eref(), returnOp( e, index ) ); - } - - A returnOp( const Eref& e, const L& index ) const { - return ( reinterpret_cast< T* >( e.data() )->*func_)( - e, index ); - } - - private: - A ( T::*func_ )( const Eref& e, L ) const; +public: + GetEpFunc1( A ( T::*func )( const Eref& e, L ) const ) + : func_( func ) + {;} + + + void op( const Eref& e, L index, ObjId recipient, FuncId fid ) + const + { + const OpFunc *f = recipient.element()->cinfo()->getOpFunc( fid); + const OpFunc1Base< A >* recvOpFunc = + dynamic_cast< const OpFunc1Base< A >* >( f ); + assert( recvOpFunc ); + recvOpFunc->op( recipient.eref(), returnOp( e, index ) ); + } + + A returnOp( const Eref& e, const L& index ) const + { + return ( reinterpret_cast< T* >( e.data() )->*func_)( + e, index ); + } + +private: + A ( T::*func_ )( const Eref& e, L ) const; }; #endif //_EPFUNC_H diff --git a/basecode/FieldElement.h b/basecode/FieldElement.h index 02a137ed..cbcc0187 100644 --- a/basecode/FieldElement.h +++ b/basecode/FieldElement.h @@ -90,8 +90,7 @@ class FieldElement: public Element * * Returns 0 if either index is out of range. */ - char* data( unsigned int rawIndex, - unsigned int fieldIndex = 0 ) const; + char* data( unsigned int rawIndex, unsigned int fieldIndex = 0 ) const; /** * virtual diff --git a/basecode/FieldElementFinfo.cpp b/basecode/FieldElementFinfo.cpp index 0ada63b6..4d89c9cd 100644 --- a/basecode/FieldElementFinfo.cpp +++ b/basecode/FieldElementFinfo.cpp @@ -11,22 +11,23 @@ #include "../shell/Shell.h" #include "../msg/OneToOneDataIndexMsg.h" -void FieldElementFinfoBase::postCreationFunc( - Id parent, Element* parentElm ) const +void FieldElementFinfoBase::postCreationFunc( Id parent, Element* parentElm ) const { - static const Finfo* pf = Neutral::initCinfo()->findFinfo( "parentMsg" ); - static const Finfo* f1 = Neutral::initCinfo()->findFinfo( "childOut" ); + static const Finfo* pf = Neutral::initCinfo()->findFinfo( "parentMsg" ); + static const Finfo* f1 = Neutral::initCinfo()->findFinfo( "childOut" ); - if ( deferCreate_ ) - return; - Id kid = Id::nextId(); - Element* e = new FieldElement( parent, kid, fieldCinfo_, name(), this ); - Msg* m = new OneToOneDataIndexMsg( parent.eref(), Eref( e, 0 ), 0 ); - assert( m ); - if ( !f1->addMsg( pf, m->mid(), parent.element() ) ) { - cout << "FieldElementFinfoBase::postCreationFunc: Error: \n" << - " unable to add parent->child msg from " << - parent.element()->getName() << " to " << name() << "\n"; - return; - } + if ( deferCreate_ ) + return; + Id kid = Id::nextId(); + Element* e = new FieldElement( parent, kid, fieldCinfo_, name(), this ); + Msg* m = new OneToOneDataIndexMsg( parent.eref(), Eref( e, 0 ), 0 ); + assert( m ); + + if ( !f1->addMsg( pf, m->mid(), parent.element() ) ) + { + cout << "FieldElementFinfoBase::postCreationFunc: Error: \n" << + " unable to add parent->child msg from " << + parent.element()->getName() << " to " << name() << "\n"; + return; + } } diff --git a/basecode/OpFunc.h b/basecode/OpFunc.h index 27f71383..29bb891b 100644 --- a/basecode/OpFunc.h +++ b/basecode/OpFunc.h @@ -12,114 +12,121 @@ template< class T > class OpFunc0: public OpFunc0Base { - public: - OpFunc0( void ( T::*func )( ) ) - : func_( func ) - {;} - - void op( const Eref& e ) const { - (reinterpret_cast< T* >( e.data() )->*func_)(); - } - private: - void ( T::*func_ )( ); +public: + OpFunc0( void ( T::*func )( ) ) + : func_( func ) + {;} + + void op( const Eref& e ) const + { + (reinterpret_cast< T* >( e.data() )->*func_)(); + } +private: + void ( T::*func_ )( ); }; template< class T, class A > class OpFunc1: public OpFunc1Base { - public: - OpFunc1( void ( T::*func )( A ) ) - : func_( func ) - {;} - void op( const Eref& e, A arg ) const { - (reinterpret_cast< T* >( e.data() )->*func_)( arg ); - } - private: - void ( T::*func_ )( A ); +public: + OpFunc1( void ( T::*func )( A ) ) + : func_( func ) + {;} + void op( const Eref& e, A arg ) const + { + (reinterpret_cast< T* >( e.data() )->*func_)( arg ); + } +private: + void ( T::*func_ )( A ); }; template< class T, class A1, class A2 > class OpFunc2: - public OpFunc2Base< A1, A2 > + public OpFunc2Base< A1, A2 > { - public: - OpFunc2( void ( T::*func )( A1, A2 ) ) - : func_( func ) - {;} - - void op( const Eref& e, A1 arg1, A2 arg2 ) const { - (reinterpret_cast< T* >( e.data() )->*func_)( arg1, arg2 ); - } - - private: - void ( T::*func_ )( A1, A2 ); +public: + OpFunc2( void ( T::*func )( A1, A2 ) ) + : func_( func ) + {;} + + void op( const Eref& e, A1 arg1, A2 arg2 ) const + { + (reinterpret_cast< T* >( e.data() )->*func_)( arg1, arg2 ); + } + +private: + void ( T::*func_ )( A1, A2 ); }; template< class T, class A1, class A2, class A3 > class OpFunc3: - public OpFunc3Base< A1, A2, A3 > + public OpFunc3Base< A1, A2, A3 > { - public: - OpFunc3( void ( T::*func )( A1, A2, A3 ) ) - : func_( func ) - {;} - void op( const Eref& e, A1 arg1, A2 arg2, A3 arg3 ) const { - (reinterpret_cast< T* >( e.data() )->*func_)( arg1, arg2, arg3); - } - private: - void ( T::*func_ )( A1, A2, A3 ); +public: + OpFunc3( void ( T::*func )( A1, A2, A3 ) ) + : func_( func ) + {;} + void op( const Eref& e, A1 arg1, A2 arg2, A3 arg3 ) const + { + (reinterpret_cast< T* >( e.data() )->*func_)( arg1, arg2, arg3); + } +private: + void ( T::*func_ )( A1, A2, A3 ); }; template< class T, class A1, class A2, class A3, class A4 > class OpFunc4: - public OpFunc4Base< A1, A2, A3, A4 > + public OpFunc4Base< A1, A2, A3, A4 > { - public: - OpFunc4( void ( T::*func )( A1, A2, A3, A4 ) ) - : func_( func ) - {;} - - void op( const Eref& e, A1 arg1, A2 arg2, A3 arg3, A4 arg4 ) const { - (reinterpret_cast< T* >( e.data() )->*func_)( - arg1, arg2, arg3, arg4 ); - } - - private: - void ( T::*func_ )( A1, A2, A3, A4 ); +public: + OpFunc4( void ( T::*func )( A1, A2, A3, A4 ) ) + : func_( func ) + {;} + + void op( const Eref& e, A1 arg1, A2 arg2, A3 arg3, A4 arg4 ) const + { + (reinterpret_cast< T* >( e.data() )->*func_)( + arg1, arg2, arg3, arg4 ); + } + +private: + void ( T::*func_ )( A1, A2, A3, A4 ); }; template< class T, class A1, class A2, class A3, class A4, class A5 > - class OpFunc5: public OpFunc5Base< A1, A2, A3, A4, A5 > +class OpFunc5: public OpFunc5Base< A1, A2, A3, A4, A5 > { - public: - OpFunc5( void ( T::*func )( A1, A2, A3, A4, A5 ) ) - : func_( func ) - {;} - - void op( const Eref& e, - A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5 ) const { - (reinterpret_cast< T* >( e.data() )->*func_)( - arg1, arg2, arg3, arg4, arg5 ); - } - - private: - void ( T::*func_ )( A1, A2, A3, A4, A5 ); +public: + OpFunc5( void ( T::*func )( A1, A2, A3, A4, A5 ) ) + : func_( func ) + {;} + + void op( const Eref& e, + A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5 ) const + { + (reinterpret_cast< T* >( e.data() )->*func_)( + arg1, arg2, arg3, arg4, arg5 ); + } + +private: + void ( T::*func_ )( A1, A2, A3, A4, A5 ); }; template< class T, - class A1, class A2, class A3, class A4, class A5, class A6 > - class OpFunc6: public OpFunc6Base< A1, A2, A3, A4, A5, A6 > + class A1, class A2, class A3, class A4, class A5, class A6 > +class OpFunc6: public OpFunc6Base< A1, A2, A3, A4, A5, A6 > { - public: - OpFunc6( void ( T::*func )( A1, A2, A3, A4, A5, A6 ) ) - : func_( func ) - {;} - - void op( const Eref& e, A1 arg1, A2 arg2, A3 arg3, A4 arg4, - A5 arg5, A6 arg6 ) const { - (reinterpret_cast< T* >( e.data() )->*func_)( - arg1, arg2, arg3, arg4, arg5, arg6 ); - } - - private: - void ( T::*func_ )( A1, A2, A3, A4, A5, A6 ); +public: + OpFunc6( void ( T::*func )( A1, A2, A3, A4, A5, A6 ) ) + : func_( func ) + {;} + + void op( const Eref& e, A1 arg1, A2 arg2, A3 arg3, A4 arg4, + A5 arg5, A6 arg6 ) const + { + (reinterpret_cast< T* >( e.data() )->*func_)( + arg1, arg2, arg3, arg4, arg5, arg6 ); + } + +private: + void ( T::*func_ )( A1, A2, A3, A4, A5, A6 ); }; @@ -133,21 +140,22 @@ template< class T, */ template< class T, class A > class GetOpFunc: public GetOpFuncBase< A > { - public: - GetOpFunc( A ( T::*func )() const ) - : func_( func ) - {;} - - void op( const Eref& e, vector< A >* ret ) const { - ret->push_back( returnOp( e ) ); - } - - A returnOp( const Eref& e ) const { - return ( reinterpret_cast< T* >( e.data() )->*func_)(); - } - - private: - A ( T::*func_ )() const; +public: + GetOpFunc( A ( T::*func )() const ) : func_( func ) + {;} + + void op( const Eref& e, vector< A >* ret ) const + { + ret->push_back( returnOp( e ) ); + } + + A returnOp( const Eref& e ) const + { + return ( reinterpret_cast< T* >( e.data() )->*func_)(); + } + +private: + A ( T::*func_ )() const; }; /** @@ -162,40 +170,42 @@ template< class T, class A > class GetOpFunc: public GetOpFuncBase< A > * L is the lookup index. */ template< class T, class L, class A > class GetOpFunc1: - public LookupGetOpFuncBase< L, A > + public LookupGetOpFuncBase< L, A > { - public: - GetOpFunc1( A ( T::*func )( L ) const ) - : func_( func ) - {;} - - /** - * The buf just contains the funcid on the src element that is - * ready to receive the returned data. - * Also we are returning the data along the Msg that brought in - * the request, so we don't need to scan through all Msgs in - * the Element to find the right one. - * So we bypass the usual SrcFinfo::sendTo, and instead go - * right to the Qinfo::addToQ to send off data. - * Finally, the data is copied back-and-forth about 3 times. - * Wasteful, but the 'get' function is not to be heavily used. - */ - void op( const Eref& e, L index, ObjId recipient, FuncId fid ) - const { - const OpFunc *f = recipient.element()->cinfo()->getOpFunc( fid); - const OpFunc1Base< A >* recvOpFunc = - dynamic_cast< const OpFunc1Base< A >* >( f ); - assert( recvOpFunc ); - recvOpFunc->op( recipient.eref(), returnOp( e, index ) ); - } - - /// Distinct reduceOp with the index. - A returnOp( const Eref& e, const L& index ) const { - return ( reinterpret_cast< T* >( e.data() )->*func_)( index ); - } - - private: - A ( T::*func_ )( L ) const; +public: + GetOpFunc1( A ( T::*func )( L ) const ) + : func_( func ) + {;} + + /** + * The buf just contains the funcid on the src element that is + * ready to receive the returned data. + * Also we are returning the data along the Msg that brought in + * the request, so we don't need to scan through all Msgs in + * the Element to find the right one. + * So we bypass the usual SrcFinfo::sendTo, and instead go + * right to the Qinfo::addToQ to send off data. + * Finally, the data is copied back-and-forth about 3 times. + * Wasteful, but the 'get' function is not to be heavily used. + */ + void op( const Eref& e, L index, ObjId recipient, FuncId fid ) + const + { + const OpFunc *f = recipient.element()->cinfo()->getOpFunc( fid); + const OpFunc1Base< A >* recvOpFunc = + dynamic_cast< const OpFunc1Base< A >* >( f ); + assert( recvOpFunc ); + recvOpFunc->op( recipient.eref(), returnOp( e, index ) ); + } + + /// Distinct reduceOp with the index. + A returnOp( const Eref& e, const L& index ) const + { + return ( reinterpret_cast< T* >( e.data() )->*func_)( index ); + } + +private: + A ( T::*func_ )( L ) const; }; #endif // _OPFUNC_H diff --git a/basecode/OpFuncBase.h b/basecode/OpFuncBase.h index 8fac1064..d35ce46e 100644 --- a/basecode/OpFuncBase.h +++ b/basecode/OpFuncBase.h @@ -22,376 +22,382 @@ extern const unsigned char MooseTestHop; class HopIndex { - public: - HopIndex( unsigned short bindIndex, - unsigned char hopType = MooseSendHop) - : bindIndex_( bindIndex ), - hopType_( hopType ) - {;} - - unsigned short bindIndex() const { - return bindIndex_; - } - - unsigned char hopType() const { - return hopType_; - } - private: - unsigned short bindIndex_; - unsigned char hopType_; +public: + HopIndex( unsigned short bindIndex, + unsigned char hopType = MooseSendHop) + : bindIndex_( bindIndex ), + hopType_( hopType ) + {;} + + unsigned short bindIndex() const + { + return bindIndex_; + } + + unsigned char hopType() const + { + return hopType_; + } +private: + unsigned short bindIndex_; + unsigned char hopType_; }; class OpFunc { - public: - OpFunc(); +public: + OpFunc(); - virtual ~OpFunc() - {;} - virtual bool checkFinfo( const Finfo* s) const = 0; + virtual ~OpFunc() + {;} + virtual bool checkFinfo( const Finfo* s) const = 0; - virtual string rttiType() const = 0; + virtual string rttiType() const = 0; - virtual const OpFunc* makeHopFunc( HopIndex hopIndex) const =0; + virtual const OpFunc* makeHopFunc( HopIndex hopIndex) const =0; - /// Executes the OpFunc by converting args. - virtual void opBuffer( const Eref& e, double* buf ) const = 0; + /// Executes the OpFunc by converting args. + virtual void opBuffer( const Eref& e, double* buf ) const = 0; - /// Executes the OpFunc for all data by converting a vector of args. - virtual void opVecBuffer( const Eref& e, double* buf ) const - {;} + /// Executes the OpFunc for all data by converting a vector of args. + virtual void opVecBuffer( const Eref& e, double* buf ) const + {;} - static const OpFunc* lookop( unsigned int opIndex ); + static const OpFunc* lookop( unsigned int opIndex ); - unsigned int opIndex() const { - return opIndex_; - } + unsigned int opIndex() const + { + return opIndex_; + } - /// Used when rebuilding the Fid->OpFunc mapping. - bool setIndex( unsigned int i ); - /// cleans out the entire Ops vector. Returns size of orig vector. - static unsigned int rebuildOpIndex(); - private: - unsigned int opIndex_; - static vector< OpFunc* >& ops(); + /// Used when rebuilding the Fid->OpFunc mapping. + bool setIndex( unsigned int i ); + /// cleans out the entire Ops vector. Returns size of orig vector. + static unsigned int rebuildOpIndex(); +private: + unsigned int opIndex_; + static vector< OpFunc* >& ops(); }; class OpFunc0Base: public OpFunc { - public: - bool checkFinfo( const Finfo* s ) const { - return dynamic_cast< const SrcFinfo0* >( s ); - } +public: + bool checkFinfo( const Finfo* s ) const + { + return dynamic_cast< const SrcFinfo0* >( s ); + } - virtual void op( const Eref& e ) const = 0; + virtual void op( const Eref& e ) const = 0; - const OpFunc* makeHopFunc( HopIndex hopIndex) const; + const OpFunc* makeHopFunc( HopIndex hopIndex) const; - void opBuffer( const Eref& e, double* buf ) const; + void opBuffer( const Eref& e, double* buf ) const; - string rttiType() const { - return "void"; - } + string rttiType() const + { + return "void"; + } }; template< class A > class OpFunc1Base: public OpFunc { - public: - - bool checkFinfo( const Finfo* s ) const { - return dynamic_cast< const SrcFinfo1< A >* >( s ); - } - - virtual void op( const Eref& e, A arg ) const = 0; - - const OpFunc* makeHopFunc( HopIndex hopIndex) const; - - void opBuffer( const Eref& e, double* buf ) const { - op( e, Conv< A >::buf2val( &buf ) ); - } - - void opVecBuffer( const Eref& e, double* buf ) const { - vector< A > temp = Conv< vector< A > >::buf2val( &buf ); - Element* elm = e.element(); - if ( elm->hasFields() ) { // Assignment is to field array. - unsigned int di = e.dataIndex(); - unsigned int nf = elm->numField( di - - elm->localDataStart() ); - for ( unsigned int i = 0; i < nf; ++i) { - Eref er( elm, di, i ); - op( er, temp[ i % temp.size() ] ); - } - } else { // Assignment is to data entries. - unsigned int k = 0; - unsigned int start = elm->localDataStart(); - unsigned int end = start + elm->numLocalData(); - for ( unsigned int i = start; i < end; ++i) { - Eref er( elm, i, 0 ); - op( er, temp[ k % temp.size() ] ); - ++k; - } - } - } - - virtual void opVec( const Eref& e, const vector< A >& arg, - const OpFunc1Base< A >* op ) const - { ; } // overridden in HopFuncs. - - string rttiType() const { - return Conv< A >::rttiType(); - } +public: + + bool checkFinfo( const Finfo* s ) const + { + return dynamic_cast< const SrcFinfo1< A >* >( s ); + } + + virtual void op( const Eref& e, A arg ) const = 0; + + const OpFunc* makeHopFunc( HopIndex hopIndex) const; + + void opBuffer( const Eref& e, double* buf ) const + { + op( e, Conv< A >::buf2val( &buf ) ); + } + + void opVecBuffer( const Eref& e, double* buf ) const + { + vector< A > temp = Conv< vector< A > >::buf2val( &buf ); + Element* elm = e.element(); + if ( elm->hasFields() ) // Assignment is to field array. + { + unsigned int di = e.dataIndex(); + unsigned int nf = elm->numField( di - + elm->localDataStart() ); + for ( unsigned int i = 0; i < nf; ++i) + { + Eref er( elm, di, i ); + op( er, temp[ i % temp.size() ] ); + } + } + else // Assignment is to data entries. + { + unsigned int k = 0; + unsigned int start = elm->localDataStart(); + unsigned int end = start + elm->numLocalData(); + for ( unsigned int i = start; i < end; ++i) + { + Eref er( elm, i, 0 ); + op( er, temp[ k % temp.size() ] ); + ++k; + } + } + } + + virtual void opVec( const Eref& e, const vector< A >& arg, + const OpFunc1Base< A >* op ) const + { ; } // overridden in HopFuncs. + + string rttiType() const + { + return Conv< A >::rttiType(); + } }; template< class A1, class A2 > class OpFunc2Base: public OpFunc { - public: - bool checkFinfo( const Finfo* s ) const { - return dynamic_cast< const SrcFinfo2< A1, A2 >* >( s ); - } - - virtual void op( const Eref& e, A1 arg1, A2 arg2 ) - const = 0; - - const OpFunc* makeHopFunc( HopIndex hopIndex) const; - - void opBuffer( const Eref& e, double* buf ) const { - const A1& arg1 = Conv< A1 >::buf2val( &buf ); - op( e, - arg1, Conv< A2 >::buf2val( &buf ) ); - } - - void opVecBuffer( const Eref& e, double* buf ) const { - vector< A1 > temp1 = Conv< vector< A1 > >::buf2val( &buf ); - vector< A2 > temp2 = Conv< vector< A2 > >::buf2val( &buf ); - Element* elm = e.element(); - assert( temp1.size() >= elm->numLocalData() ); - unsigned int k = 0; - unsigned int start = elm->localDataStart(); - unsigned int end = start + elm->numLocalData(); - for ( unsigned int i = start; i < end; ++i) { - unsigned int nf = elm->numField( i - start ); - for ( unsigned int j = 0; j < nf; ++j) { - Eref er( elm, i, j ); - op( er, temp1[ k % temp1.size() ], - temp2[ k % temp2.size() ] ); - ++k; - } - } - } - - virtual void opVec( const Eref& e, - const vector< A1 >& arg1, - const vector< A2 >& arg2, - const OpFunc2Base< A1, A2 >* op ) const - { ; } // overridden in HopFuncs. - - string rttiType() const { - return Conv< A1 >::rttiType() + "," + Conv< A2 >::rttiType(); - } +public: + bool checkFinfo( const Finfo* s ) const + { + return dynamic_cast< const SrcFinfo2< A1, A2 >* >( s ); + } + + virtual void op( const Eref& e, A1 arg1, A2 arg2 ) + const = 0; + + const OpFunc* makeHopFunc( HopIndex hopIndex) const; + + void opBuffer( const Eref& e, double* buf ) const + { + const A1& arg1 = Conv< A1 >::buf2val( &buf ); + op( e, + arg1, Conv< A2 >::buf2val( &buf ) ); + } + + void opVecBuffer( const Eref& e, double* buf ) const + { + vector< A1 > temp1 = Conv< vector< A1 > >::buf2val( &buf ); + vector< A2 > temp2 = Conv< vector< A2 > >::buf2val( &buf ); + Element* elm = e.element(); + assert( temp1.size() >= elm->numLocalData() ); + unsigned int k = 0; + unsigned int start = elm->localDataStart(); + unsigned int end = start + elm->numLocalData(); + for ( unsigned int i = start; i < end; ++i) + { + unsigned int nf = elm->numField( i - start ); + for ( unsigned int j = 0; j < nf; ++j) + { + Eref er( elm, i, j ); + op( er, temp1[ k % temp1.size() ], + temp2[ k % temp2.size() ] ); + ++k; + } + } + } + + virtual void opVec( const Eref& e, + const vector< A1 >& arg1, + const vector< A2 >& arg2, + const OpFunc2Base< A1, A2 >* op ) const + { ; } // overridden in HopFuncs. + + string rttiType() const + { + return Conv< A1 >::rttiType() + "," + Conv< A2 >::rttiType(); + } }; template< class A1, class A2, class A3 > class OpFunc3Base: - public OpFunc + public OpFunc { - public: - bool checkFinfo( const Finfo* s ) const { - return dynamic_cast< const SrcFinfo3< A1, A2, A3 >* >( s ); - } - - virtual void op( const Eref& e, A1 arg1, A2 arg2, A3 arg3 ) - const = 0; - - const OpFunc* makeHopFunc( HopIndex hopIndex) const; - - void opBuffer( const Eref& e, double* buf ) const { - const A1& arg1 = Conv< A1 >::buf2val( &buf ); - const A2& arg2 = Conv< A2 >::buf2val( &buf ); - op( e, - arg1, arg2, Conv< A3 >::buf2val( &buf ) ); - } - - string rttiType() const { - return Conv< A1 >::rttiType() + "," + Conv< A2 >::rttiType() + - "," + Conv< A3 >::rttiType(); - } +public: + bool checkFinfo( const Finfo* s ) const + { + return dynamic_cast< const SrcFinfo3< A1, A2, A3 >* >( s ); + } + + virtual void op( const Eref& e, A1 arg1, A2 arg2, A3 arg3 ) + const = 0; + + const OpFunc* makeHopFunc( HopIndex hopIndex) const; + + void opBuffer( const Eref& e, double* buf ) const + { + const A1& arg1 = Conv< A1 >::buf2val( &buf ); + const A2& arg2 = Conv< A2 >::buf2val( &buf ); + op( e, + arg1, arg2, Conv< A3 >::buf2val( &buf ) ); + } + + string rttiType() const + { + return Conv< A1 >::rttiType() + "," + Conv< A2 >::rttiType() + + "," + Conv< A3 >::rttiType(); + } }; template< class A1, class A2, class A3, class A4 > - class OpFunc4Base: public OpFunc +class OpFunc4Base: public OpFunc { - public: - bool checkFinfo( const Finfo* s ) const { - return dynamic_cast< const SrcFinfo4< A1, A2, A3, A4 >* >( s ); - } - - virtual void op( const Eref& e, - A1 arg1, A2 arg2, A3 arg3, A4 arg4 ) const = 0; - - const OpFunc* makeHopFunc( HopIndex hopIndex) const; - - void opBuffer( const Eref& e, double* buf ) const { - const A1& arg1 = Conv< A1 >::buf2val( &buf ); - const A2& arg2 = Conv< A2 >::buf2val( &buf ); - const A3& arg3 = Conv< A3 >::buf2val( &buf ); - op( e, - arg1, arg2, arg3, Conv< A4 >::buf2val( &buf ) ); - } - - string rttiType() const { - return Conv< A1 >::rttiType() + "," + Conv< A2 >::rttiType() + - "," + Conv::rttiType() + "," + Conv::rttiType(); - } +public: + bool checkFinfo( const Finfo* s ) const + { + return dynamic_cast< const SrcFinfo4< A1, A2, A3, A4 >* >( s ); + } + + virtual void op( const Eref& e, + A1 arg1, A2 arg2, A3 arg3, A4 arg4 ) const = 0; + + const OpFunc* makeHopFunc( HopIndex hopIndex) const; + + void opBuffer( const Eref& e, double* buf ) const + { + const A1& arg1 = Conv< A1 >::buf2val( &buf ); + const A2& arg2 = Conv< A2 >::buf2val( &buf ); + const A3& arg3 = Conv< A3 >::buf2val( &buf ); + op( e, + arg1, arg2, arg3, Conv< A4 >::buf2val( &buf ) ); + } + + string rttiType() const + { + return Conv< A1 >::rttiType() + "," + Conv< A2 >::rttiType() + + "," + Conv::rttiType() + "," + Conv::rttiType(); + } }; template< class A1, class A2, class A3, class A4, class A5 > - class OpFunc5Base: public OpFunc +class OpFunc5Base: public OpFunc { - public: - bool checkFinfo( const Finfo* s ) const { - return dynamic_cast< const SrcFinfo5< A1, A2, A3, A4, A5 >* >( s ); - } - - virtual void op( const Eref& e, - A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5 ) const = 0; - - const OpFunc* makeHopFunc( HopIndex hopIndex) const; - - void opBuffer( const Eref& e, double* buf ) const { - const A1& arg1 = Conv< A1 >::buf2val( &buf ); - const A2& arg2 = Conv< A2 >::buf2val( &buf ); - const A3& arg3 = Conv< A3 >::buf2val( &buf ); - const A4& arg4 = Conv< A4 >::buf2val( &buf ); - op( e, - arg1, arg2, arg3, arg4, Conv< A5 >::buf2val( &buf ) ); - } - - string rttiType() const { - return Conv< A1 >::rttiType() + "," + Conv< A2 >::rttiType() + - "," + Conv::rttiType() + "," + Conv::rttiType() + - "," + Conv::rttiType(); - } +public: + bool checkFinfo( const Finfo* s ) const + { + return dynamic_cast< const SrcFinfo5< A1, A2, A3, A4, A5 >* >( s ); + } + + virtual void op( const Eref& e, + A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5 ) const = 0; + + const OpFunc* makeHopFunc( HopIndex hopIndex) const; + + void opBuffer( const Eref& e, double* buf ) const + { + const A1& arg1 = Conv< A1 >::buf2val( &buf ); + const A2& arg2 = Conv< A2 >::buf2val( &buf ); + const A3& arg3 = Conv< A3 >::buf2val( &buf ); + const A4& arg4 = Conv< A4 >::buf2val( &buf ); + op( e, + arg1, arg2, arg3, arg4, Conv< A5 >::buf2val( &buf ) ); + } + + string rttiType() const + { + return Conv< A1 >::rttiType() + "," + Conv< A2 >::rttiType() + + "," + Conv::rttiType() + "," + Conv::rttiType() + + "," + Conv::rttiType(); + } }; template< class A1, class A2, class A3, class A4, class A5, class A6 > - class OpFunc6Base: public OpFunc +class OpFunc6Base: public OpFunc { - public: - bool checkFinfo( const Finfo* s ) const { - return dynamic_cast< const SrcFinfo6< A1, A2, A3, A4, A5, A6 >* >( s ); - } - - virtual void op( const Eref& e, A1 arg1, A2 arg2, A3 arg3, A4 arg4, - A5 arg5, A6 arg6 ) const = 0; - - const OpFunc* makeHopFunc( HopIndex hopIndex) const; - - void opBuffer( const Eref& e, double* buf ) const { - const A1& arg1 = Conv< A1 >::buf2val( &buf ); - const A2& arg2 = Conv< A2 >::buf2val( &buf ); - const A3& arg3 = Conv< A3 >::buf2val( &buf ); - const A4& arg4 = Conv< A4 >::buf2val( &buf ); - const A5& arg5 = Conv< A5 >::buf2val( &buf ); - op( e, - arg1, arg2, arg3, arg4, arg5, Conv< A6 >::buf2val( &buf ) ); - } - - string rttiType() const { - return Conv< A1 >::rttiType() + "," + Conv< A2 >::rttiType() + - "," + Conv::rttiType() + "," + Conv::rttiType() + - "," + Conv::rttiType() + "," + Conv::rttiType(); - } +public: + bool checkFinfo( const Finfo* s ) const + { + return dynamic_cast< const SrcFinfo6< A1, A2, A3, A4, A5, A6 >* >( s ); + } + + virtual void op( const Eref& e, A1 arg1, A2 arg2, A3 arg3, A4 arg4, + A5 arg5, A6 arg6 ) const = 0; + + const OpFunc* makeHopFunc( HopIndex hopIndex) const; + + void opBuffer( const Eref& e, double* buf ) const + { + const A1& arg1 = Conv< A1 >::buf2val( &buf ); + const A2& arg2 = Conv< A2 >::buf2val( &buf ); + const A3& arg3 = Conv< A3 >::buf2val( &buf ); + const A4& arg4 = Conv< A4 >::buf2val( &buf ); + const A5& arg5 = Conv< A5 >::buf2val( &buf ); + op( e, + arg1, arg2, arg3, arg4, arg5, Conv< A6 >::buf2val( &buf ) ); + } + + string rttiType() const + { + return Conv< A1 >::rttiType() + "," + Conv< A2 >::rttiType() + + "," + Conv::rttiType() + "," + Conv::rttiType() + + "," + Conv::rttiType() + "," + Conv::rttiType(); + } }; /** * This is the base class for all GetOpFuncs. */ -template< class A > class GetOpFuncBase: public OpFunc1Base< vector< A >* > +template< class A > +class GetOpFuncBase: public OpFunc1Base< vector< A >* > { - public: - /* - bool checkFinfo( const Finfo* s ) const { - return ( dynamic_cast< const SrcFinfo1< A >* >( s ) - || dynamic_cast< const SrcFinfo1< FuncId >* >( s ) ); - } - */ - - virtual A returnOp( const Eref& e ) const = 0; - - // This returns an OpFunc1< A* > so we can pass back the arg A - const OpFunc* makeHopFunc( HopIndex hopIndex) const; - - // This is called on the target node when a remoteGet happens. - // It needs to do the 'get' function and stuff the data into the - // buffer for sending back. - void opBuffer( const Eref& e, double* buf ) const { - A ret = returnOp( e ); - buf[0] = Conv::size( ret ); - buf++; - Conv< A >::val2buf( ret, &buf ); - } - - /* - string rttiType() const { - return Conv< A >::rttiType(); - } - */ -}; -/* -template< class A > class GetOpFuncBase: public OpFunc -{ - public: - bool checkFinfo( const Finfo* s ) const { - return ( dynamic_cast< const SrcFinfo1< A >* >( s ) - || dynamic_cast< const SrcFinfo1< FuncId >* >( s ) ); - } - - virtual void op( const Eref& e, ObjId recipient, FuncId fid ) - const = 0; - - virtual A returnOp( const Eref& e ) const = 0; +public: + virtual A returnOp( const Eref& e ) const = 0; + + // This returns an OpFunc1< A* > so we can pass back the arg A + const OpFunc* makeHopFunc( HopIndex hopIndex) const; + + // This is called on the target node when a remoteGet happens. + // It needs to do the 'get' function and stuff the data into the + // buffer for sending back. + void opBuffer( const Eref& e, double* buf ) const + { + A ret = returnOp( e ); + buf[0] = Conv::size( ret ); + buf++; + Conv< A >::val2buf( ret, &buf ); + } - string rttiType() const { - return Conv< A >::rttiType(); - } }; -*/ /** * This is the base class for all LookupGetOpFuncs. */ template< class L, class A > class LookupGetOpFuncBase: public OpFunc { - public: - bool checkFinfo( const Finfo* s ) const { - return ( dynamic_cast< const SrcFinfo1< A >* >( s ) - || dynamic_cast< const SrcFinfo2< FuncId, L >* >( s ) ); - } - - virtual void op( const Eref& e, L index, - ObjId recipient, FuncId fid ) const = 0; - - virtual A returnOp( const Eref& e, const L& index ) const = 0; - - const OpFunc* makeHopFunc( HopIndex hopIndex) const - { - // Perhaps later we can put in something for x-node gets. - return 0; - } - - const OpFunc* makeHopFunc( HopIndex hopIndex, const L& index ) const - { - // We need to convert the index and pass it into the HopFunc - // to pass on to target node. - return 0; - } - - void opBuffer( const Eref& e, double* buf ) const { - // Later figure out how to handle. - } - - string rttiType() const { - return Conv< A >::rttiType(); - } +public: + bool checkFinfo( const Finfo* s ) const + { + return ( dynamic_cast< const SrcFinfo1< A >* >( s ) + || dynamic_cast< const SrcFinfo2< FuncId, L >* >( s ) ); + } + + virtual void op( const Eref& e, L index, + ObjId recipient, FuncId fid ) const = 0; + + virtual A returnOp( const Eref& e, const L& index ) const = 0; + + const OpFunc* makeHopFunc( HopIndex hopIndex) const + { + // Perhaps later we can put in something for x-node gets. + return 0; + } + + const OpFunc* makeHopFunc( HopIndex hopIndex, const L& index ) const + { + // We need to convert the index and pass it into the HopFunc + // to pass on to target node. + return 0; + } + + void opBuffer( const Eref& e, double* buf ) const + { + // Later figure out how to handle. + } + + string rttiType() const + { + return Conv< A >::rttiType(); + } }; #endif // _OPFUNCBASE_H diff --git a/basecode/SetGet.cpp b/basecode/SetGet.cpp index aa50ec6c..c684c156 100644 --- a/basecode/SetGet.cpp +++ b/basecode/SetGet.cpp @@ -12,58 +12,55 @@ #include "../shell/Shell.h" #include "../shell/Neutral.h" -const OpFunc* SetGet::checkSet( - const string& field, ObjId& tgt, FuncId& fid ) +const OpFunc* SetGet::checkSet( const string& field, ObjId& tgt, FuncId& fid ) { - // string field = "set_" + destField; - const Finfo* f = tgt.element()->cinfo()->findFinfo( field ); - if ( !f ) { // Could be a child element? Note that field name will - // change from set_ to just - string f2 = field.substr( 3 ); - Id child = Neutral::child( tgt.eref(), f2 ); - if ( child == Id() ) { - cout << "Error: SetGet:checkSet:: No field or child named '" << - field << "' was found on\n" << tgt.id.path() << endl; - } else { - if ( field.substr( 0, 3 ) == "set" ) - f = child.element()->cinfo()->findFinfo( "setThis" ); - else if ( field.substr( 0, 3 ) == "get" ) - f = child.element()->cinfo()->findFinfo( "getThis" ); - assert( f ); // should always work as Neutral has the field. - if ( child.element()->numData() == tgt.element()->numData() ) { - tgt = ObjId( child, tgt.dataIndex, tgt.fieldIndex ); - if ( !tgt.isDataHere() ) - return 0; - } else if ( child.element()->numData() <= 1 ) { - tgt = ObjId( child, 0 ); - if ( !tgt.isDataHere() ) - return 0; - } else { - cout << "SetGet::checkSet: child index mismatch\n"; - return 0; - } - } - } + // string field = "set_" + destField; + const Finfo* f = tgt.element()->cinfo()->findFinfo( field ); + if ( !f ) // Could be a child element? Note that field name will + { + // change from set_ to just + string f2 = field.substr( 3 ); + Id child = Neutral::child( tgt.eref(), f2 ); + if ( child == Id() ) + { + cout << "Error: SetGet:checkSet:: No field or child named '" << + field << "' was found on\n" << tgt.id.path() << endl; + } + else + { + if ( field.substr( 0, 3 ) == "set" ) + f = child.element()->cinfo()->findFinfo( "setThis" ); + else if ( field.substr( 0, 3 ) == "get" ) + f = child.element()->cinfo()->findFinfo( "getThis" ); + assert( f ); // should always work as Neutral has the field. + if ( child.element()->numData() == tgt.element()->numData() ) + { + tgt = ObjId( child, tgt.dataIndex, tgt.fieldIndex ); + if ( !tgt.isDataHere() ) + return 0; + } + else if ( child.element()->numData() <= 1 ) + { + tgt = ObjId( child, 0 ); + if ( !tgt.isDataHere() ) + return 0; + } + else + { + cout << "SetGet::checkSet: child index mismatch\n"; + return 0; + } + } + } - const DestFinfo* df = dynamic_cast< const DestFinfo* >( f ); - if ( !df ) - return 0; + const DestFinfo* df = dynamic_cast< const DestFinfo* >( f ); + if ( !df ) + return 0; - fid = df->getFid(); - const OpFunc* func = df->getOpFunc(); - assert( func ); - return func; - - /* - // This is the crux of the function: typecheck for the field. - // if ( func->checkSet( this ) ) - if ( checkOpClass( func ) ) { - return func; - } else { - cout << "set::Type mismatch" << oid_ << "." << field << endl; - return 0; - } - */ + fid = df->getFid(); + const OpFunc* func = df->getOpFunc(); + assert( func ); + return func; } ///////////////////////////////////////////////////////////////////////// @@ -71,24 +68,26 @@ const OpFunc* SetGet::checkSet( // Static function bool SetGet::strGet( const ObjId& tgt, const string& field, string& ret ) { - const Finfo* f = tgt.element()->cinfo()->findFinfo( field ); - if ( !f ) { - cout << Shell::myNode() << ": Error: SetGet::strGet: Field " << - field << " not found on Element " << tgt.element()->getName() << - endl; - return 0; - } - return f->strGet( tgt.eref(), field, ret ); + const Finfo* f = tgt.element()->cinfo()->findFinfo( field ); + if ( !f ) + { + cout << Shell::myNode() << ": Error: SetGet::strGet: Field " << + field << " not found on Element " << tgt.element()->getName() << + endl; + return 0; + } + return f->strGet( tgt.eref(), field, ret ); } bool SetGet::strSet( const ObjId& tgt, const string& field, const string& v) { - const Finfo* f = tgt.element()->cinfo()->findFinfo( field ); - if ( !f ) { - cout << Shell::myNode() << ": Error: SetGet::strSet: Field " << - field << " not found on Element " << tgt.element()->getName() << - endl; - return 0; - } - return f->strSet( tgt.eref(), field, v ); + const Finfo* f = tgt.element()->cinfo()->findFinfo( field ); + if ( !f ) + { + cout << Shell::myNode() << ": Error: SetGet::strSet: Field " << + field << " not found on Element " << tgt.element()->getName() << + endl; + return 0; + } + return f->strSet( tgt.eref(), field, v ); } diff --git a/basecode/SetGet.h b/basecode/SetGet.h index 1788d6ad..fe55f6e0 100644 --- a/basecode/SetGet.h +++ b/basecode/SetGet.h @@ -10,6 +10,12 @@ #ifndef _SETGET_H #define _SETGET_H +#ifndef NDEBUG +#include +using namespace std; +#endif + + // Forward declaration needed for localGet() template< class T, class A > class GetOpFunc; @@ -277,8 +283,7 @@ template< class A > class Field: public SetGet1< A > return SetGet1< A >::setVec( destId, temp, arg ); } - static bool setRepeat( ObjId destId, const string& field, - A arg ) + static bool setRepeat( ObjId destId, const string& field, A arg ) { string temp = "set" + field; temp[3] = std::toupper( temp[3] ); @@ -288,8 +293,7 @@ template< class A > class Field: public SetGet1< A > /** * Blocking call using string conversion */ - static bool innerStrSet( const ObjId& dest, const string& field, - const string& arg ) + static bool innerStrSet( const ObjId& dest, const string& field, const string& arg ) { A val; // Do NOT add 'set_' to the field name, as the 'set' func @@ -299,17 +303,17 @@ template< class A > class Field: public SetGet1< A > } ////////////////////////////////////////////////////////////////// - // Returns a field value. static A get( const ObjId& dest, const string& field) { ObjId tgt( dest ); FuncId fid; + string fullFieldName = "get" + field; fullFieldName[3] = std::toupper( fullFieldName[3] ); + const OpFunc* func = SetGet::checkSet( fullFieldName, tgt, fid ); - const GetOpFuncBase< A >* gof = - dynamic_cast< const GetOpFuncBase< A >* >( func ); + const GetOpFuncBase< A >* gof = dynamic_cast< const GetOpFuncBase< A >* >( func ); if ( gof ) { if ( tgt.isDataHere() ) diff --git a/basecode/global.cpp b/basecode/global.cpp index c2c36542..c5035f45 100644 --- a/basecode/global.cpp +++ b/basecode/global.cpp @@ -144,6 +144,22 @@ namespace moose { if( p.size() == 0 ) return true; +#ifdef USE_BOOST_FILESYSTEM + try + { + boost::filesystem::path pdirs( p ); + boost::filesystem::create_directories( pdirs ); + LOG( moose::info, "Created directory " << p ); + return true; + } + catch(const boost::filesystem::filesystem_error& e) + { + LOG( moose::warning, "create_directories(" << p << ") failed with " + << e.code().message() + ); + return false; + } +#else /* ----- not USE_BOOST_FILESYSTEM ----- */ string command( "mkdir -p "); command += p; int ret = system( command.c_str() ); @@ -163,6 +179,7 @@ namespace moose { LOG( moose::warning, p << " is no directory" ); return false; } +#endif /* ----- not USE_BOOST_FILESYSTEM ----- */ return true; } diff --git a/basecode/global.h b/basecode/global.h index 3beab75d..76ca1cdd 100644 --- a/basecode/global.h +++ b/basecode/global.h @@ -17,7 +17,12 @@ #include #include -#include "../randnum/RNG.h" /* Use inbuilt rng */ + +#ifdef USE_BOOST_FILESYSTEM +#include +#endif + +#include "randnum/RNG.h" /* Use inbuilt rng */ #include "../utility/print_function.hpp" using namespace std; diff --git a/basecode/main.cpp b/basecode/main.cpp index dc194c08..162f57ea 100644 --- a/basecode/main.cpp +++ b/basecode/main.cpp @@ -35,7 +35,6 @@ int testIndex = 0; f; \ cout << std::right << " [DONE]" << endl; \ -extern void testSync(); extern void testAsync(); extern void testSyncArray( unsigned int size, unsigned int method ); extern void testShell(); @@ -67,17 +66,15 @@ extern void testSigNeurProcess(); extern unsigned int initMsgManagers(); extern void destroyMsgManagers(); // void regressionTests(); -#endif -extern void speedTestMultiNodeIntFireNetwork( - unsigned int size, unsigned int runsteps ); +#endif // DO_UNIT_TESTS + +extern void speedTestMultiNodeIntFireNetwork(unsigned int size, unsigned int runsteps); #ifdef USE_SMOLDYN extern void testSmoldyn(); #endif // bool benchmarkTests( int argc, char** argv ); -extern void mooseBenchmarks( unsigned int option ); - ////////////////////////////////////////////////////////////////// // System-dependent function here ////////////////////////////////////////////////////////////////// @@ -133,39 +130,26 @@ void checkChildren( Id parent, const string& info ) } -Id init( int argc, char** argv, bool& doUnitTests, bool& doRegressionTests, - unsigned int& benchmark ) +Id init(int argc, char** argv, bool& doUnitTests) { unsigned int numCores = getNumCores(); int numNodes = 1; int myNode = 0; bool isInfinite = 0; int opt; - benchmark = 0; // Default, means don't do any benchmarks. Cinfo::rebuildOpIndex(); + #ifdef USE_MPI - /* - // OpenMPI does not use argc or argv. - // unsigned int temp_argc = 1; - int provided; - MPI_Init_thread( &argc, &argv, MPI_THREAD_SERIALIZED, &provided ); - */ MPI_Init( &argc, &argv ); - MPI_Comm_size( MPI_COMM_WORLD, &numNodes ); MPI_Comm_rank( MPI_COMM_WORLD, &myNode ); - /* - if ( provided < MPI_THREAD_SERIALIZED && myNode == 0 ) { - cout << "Warning: This MPI implementation does not like multithreading: " << provided << "\n"; - } - */ - // myNode = MPI::COMM_WORLD.Get_rank(); #endif + /** * Here we allow the user to override the automatic identification * of processor configuration */ - while ( ( opt = getopt( argc, argv, "hiqurn:b:B:" ) ) != -1 ) + while ( ( opt = getopt( argc, argv, "hiqun:b:B:" ) ) != -1 ) { switch ( opt ) { @@ -174,40 +158,18 @@ Id init( int argc, char** argv, bool& doUnitTests, bool& doRegressionTests, break; case 'n': // Multiple nodes numNodes = (unsigned int)atoi( optarg ); - break; - case 'b': // Benchmark: - { - string s(optarg); - if ( s == "ee" ) - benchmark = 1; - else if ( s == "gsl" ) - benchmark = 2; - else if ( s == "gssa" ) - benchmark = 3; - else if ( s[0] == 'i' ) - benchmark = 4; - else if ( s[0] == 'h' ) - benchmark = 5; - else if ( s[0] == 'm' ) - benchmark = 6; - else - cout << "Unknown benchmark, " << optarg << ", skipping\n"; - } break; case 'B': // Benchmark plus dump data: handle later. break; case 'u': // Do unit tests, pass back. - doUnitTests = 1; - break; - case 'r': // Do regression tests: pass back - doRegressionTests = 1; + doUnitTests = true; break; case 'q': // quit immediately after completion. quitFlag = 1; break; case 'h': // help default: - cout << "Usage: moose -help -infiniteLoop -unit_tests -regression_tests -quit -n numNodes -benchmark [ee gsl gssa intFire hhNet msg__]\n"; + cout << "Usage: moose -help -infiniteLoop -unit_tests -quit -n numNodes\n"; exit( 1 ); } @@ -246,10 +208,6 @@ Id init( int argc, char** argv, bool& doUnitTests, bool& doRegressionTests, assert( classMasterId == Id( 2 ) ); assert( postMasterId == Id( 3 ) ); - - - // s->connectMasterMsg(); - Shell::adopt( shellId, clockId, numMsg++ ); Shell::adopt( shellId, classMasterId, numMsg++ ); Shell::adopt( shellId, postMasterId, numMsg++ ); @@ -258,16 +216,6 @@ Id init( int argc, char** argv, bool& doUnitTests, bool& doRegressionTests, Cinfo::makeCinfoElements( classMasterId ); - - // This will be initialized within the Process loop, and better there - // as it flags attempts to call the Reduce operations before ProcessLoop - // Qinfo::clearReduceQ( numCores ); // Initialize the ReduceQ entry. - - - // SetGet::setShell(); - // Msg* m = new OneToOneMsg( shelle, shelle ); - // assert ( m != 0 ); - while ( isInfinite ) // busy loop for debugging under gdb and MPI. ; @@ -304,9 +252,6 @@ void nonMpiTests( Shell* s ) MOOSE_TEST("testMesh", testMesh()); MOOSE_TEST("testSynapse", testSynapse()); MOOSE_TEST( "testSigneur", testSigNeur()); -#ifdef USE_SMOLDYN - //MOOSE_TEST(testSmoldyn()); -#endif s->setHardware( numCores, numNodes, 0 ); } #endif @@ -321,10 +266,7 @@ void processTests( Shell* s ) #ifdef DO_UNIT_TESTS MOOSE_TEST( "testSchedulingProcess", testSchedulingProcess()); MOOSE_TEST( "testBuiltinsProcess", testBuiltinsProcess()); - // MOOSE_TEST( "testKineticsProcess", testKineticsProcess()); MOOSE_TEST( "testBiophysicsProcess", testBiophysicsProcess()); - // MOOSE_TEST( "testKineticSolversProcess", testKineticSolversProcess()); - // MOOSE_TEST( "testSimManager", testSimManager()); MOOSE_TEST( "testSigNeurProcess", testSigNeurProcess()); #endif } @@ -350,7 +292,7 @@ int main( int argc, char** argv ) unsigned int benchmark = 0; // This reorders the OpFunc to Fid mapping to ensure it is node and // compiler independent. - Id shellId = init( argc, argv, doUnitTests, doRegressionTests, benchmark ); + Id shellId = init(argc, argv, doUnitTests); // Note that the main loop remains the parser loop, though it may // spawn a lot of other stuff. Element* shelle = shellId.element(); @@ -374,23 +316,11 @@ int main( int argc, char** argv ) mpiTests(); processTests( s ); } - // if ( doRegressionTests ) regressionTests(); #endif - // These are outside unit tests because they happen in optimized - // mode, using a command-line argument. As soon as they are done - // the system quits, in order to estimate timing. - if ( benchmark != 0 ) - { - mooseBenchmarks( benchmark ); - s->doQuit(); - } - else - { - // Here we set off a little event loop to poll user input. - // It deals with the doQuit call too. - if(! quitFlag) - Shell::launchParser(); - } + // Here we set off a little event loop to poll user input. + // It deals with the doQuit call too. + if(! quitFlag) + Shell::launchParser(); } else { diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt deleted file mode 100644 index ab846b73..00000000 --- a/benchmarks/CMakeLists.txt +++ /dev/null @@ -1,29 +0,0 @@ -cmake_minimum_required(VERSION 2.8) - -include( ${CMAKE_CURRENT_SOURCE_DIR}/../CheckCXXCompiler.cmake ) - -add_library(benchmarks - benchmarks.cpp - kineticMarks.cpp - ) - -if(ENABLE_BENCHMARKS) - # This target run benchmarks. Not a part of moose distribution - add_executable( - randnum_benchmark - ${CMAKE_CURRENT_SOURCE_DIR}/benchmark_random_numbers.cpp - ) - target_link_libraries(randnum_benchmark randnum ) - - if(GSL_FOUND) - target_link_libraries(randnum_benchmark ${GSL_LIBRARIES}) - endif(GSL_FOUND) - - # Add a targe to run the benchmarks. - #MESSAGE(STATUS "CMAKE_CURRENT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}") - add_custom_target( run_randnum_benchmark ALL) - add_custom_command( TARGET run_randnum_benchmark POST_BUILD - COMMAND ${CMAKE_BINARY_DIR}/benchmarks/randnum_benchmark - WORKING_DIR ${CMAKE_BINARY_DIR} - ) -endif(ENABLE_BENCHMARKS) diff --git a/benchmarks/benchmarks.cpp b/benchmarks/benchmarks.cpp deleted file mode 100644 index 74e8195a..00000000 --- a/benchmarks/benchmarks.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment. -** Copyright (C) 2003-2014 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU Lesser General Public License version 2.1 -** See the file COPYING.LIB for the full notice. -**********************************************************************/ - -#include -using namespace std; - -void runKineticsBenchmark1( const string& method ); -void testIntFireNetwork( unsigned int runsteps ); - -void mooseBenchmarks( unsigned int option ) -{ - switch ( option ) { - case 1: - cout << "Kinetics benchmark 1: small model, Exp Euler, 10Ksec, OSC_Cspace.g\n"; - runKineticsBenchmark1( "ee" ); - break; - case 2: - cout << "Kinetics benchmark 1: small model, Gsl Runge Kutta Fehlberg, 10Ksec, OSC_Cspace.g\n"; - runKineticsBenchmark1( "gsl" ); - break; - case 3: - cout << "Kinetics benchmark 1: small model, Gssa, 10Ksec, OSC_Cspace.g\n"; - runKineticsBenchmark1( "gssa" ); - break; - - case 4: - cout << "intFire benchmark: 104576 synapses, pconnect = 0.1, 2e5 timesteps\n"; - testIntFireNetwork( 200000 ); - break; - default: - cout << "Unknown benchmark specified, quitting\n"; - break; - } -} diff --git a/benchmarks/kineticMarks.cpp b/benchmarks/kineticMarks.cpp deleted file mode 100644 index 370cb000..00000000 --- a/benchmarks/kineticMarks.cpp +++ /dev/null @@ -1,22 +0,0 @@ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment. -** Copyright (C) 2003-2014 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU Lesser General Public License version 2.1 -** See the file COPYING.LIB for the full notice. -**********************************************************************/ - -#include "../basecode/header.h" -#include "../shell/Shell.h" - -/// Small model, long runtime. -void runKineticsBenchmark1( const string& method ) -{ - Shell* s = reinterpret_cast< Shell* >( ObjId().data() ); - Id mgr = s->doLoadModel( "../Demos/Genesis_files/OSC_Cspace.g", "/model", method ); - assert( mgr != Id() ); - s->doReinit(); - s->doStart( 10000.0 ); -} - diff --git a/biophysics/CMakeLists.txt b/biophysics/CMakeLists.txt index 390117a9..0c02172b 100644 --- a/biophysics/CMakeLists.txt +++ b/biophysics/CMakeLists.txt @@ -2,7 +2,11 @@ cmake_minimum_required(VERSION 2.8) include(${CMAKE_CURRENT_SOURCE_DIR}/../CheckCXXCompiler.cmake) if(WITH_GSL) + find_package(GSL 1.16) include_directories(${GSL_INCLUDE_DIRS}) +elseif(WITH_BOOST_ODE) + find_package(Boost) + include_directories(${Boost_INCLUDE_DIRS}) endif(WITH_GSL) set(BIOPHYSICS_SRCS @@ -32,7 +36,6 @@ set(BIOPHYSICS_SRCS ReadSwc.cpp SynChan.cpp NMDAChan.cpp - testBiophysics.cpp IzhikevichNrn.cpp DifShellBase.cpp DifShell.cpp @@ -48,10 +51,9 @@ set(BIOPHYSICS_SRCS MarkovSolver.cpp VClamp.cpp Spine.cpp + MarkovOdeSolver.cpp + testBiophysics.cpp ) -if(WITH_GSL) - list(APPEND BIOPHYSICS_SRCS MarkovGslSolver.cpp) -endif(WITH_GSL) +add_library(biophysics ${BIOPHYSICS_SRCS}) -add_library( biophysics ${BIOPHYSICS_SRCS} ) diff --git a/biophysics/CaConcBase.cpp b/biophysics/CaConcBase.cpp index 1f974bb3..fb6d07ec 100644 --- a/biophysics/CaConcBase.cpp +++ b/biophysics/CaConcBase.cpp @@ -24,178 +24,179 @@ * Ca concentration to the recipients. */ // Static function. -SrcFinfo1< double >* CaConcBase::concOut() { - static SrcFinfo1< double > concOut( "concOut", - "Concentration of Ca in pool" ); - return &concOut; +SrcFinfo1< double >* CaConcBase::concOut() +{ + static SrcFinfo1< double > concOut( "concOut", + "Concentration of Ca in pool" ); + return &concOut; } const Cinfo* CaConcBase::initCinfo() { - /////////////////////////////////////////////////////// - // Shared message definitions - /////////////////////////////////////////////////////// - static DestFinfo process( "process", - "Handles process call", - new ProcOpFunc< CaConcBase >( &CaConcBase::process ) ); - static DestFinfo reinit( "reinit", - "Handles reinit call", - new ProcOpFunc< CaConcBase >( &CaConcBase::reinit ) ); - - static Finfo* processShared[] = + /////////////////////////////////////////////////////// + // Shared message definitions + /////////////////////////////////////////////////////// + static DestFinfo process( "process", + "Handles process call", + new ProcOpFunc< CaConcBase >( &CaConcBase::process ) ); + static DestFinfo reinit( "reinit", + "Handles reinit call", + new ProcOpFunc< CaConcBase >( &CaConcBase::reinit ) ); + + static Finfo* processShared[] = { - &process, &reinit + &process, &reinit }; - static SharedFinfo proc( "proc", - "Shared message to receive Process message from scheduler", - processShared, sizeof( processShared ) / sizeof( Finfo* ) ); - - /////////////////////////////////////////////////////// - // Field definitions - /////////////////////////////////////////////////////// - static ElementValueFinfo< CaConcBase, double > Ca( "Ca", - "Calcium concentration.", - &CaConcBase::setCa, - &CaConcBase::getCa - ); - static ElementValueFinfo< CaConcBase, double > CaBasal( "CaBasal", - "Basal Calcium concentration.", - &CaConcBase::setCaBasal, - &CaConcBase::getCaBasal - ); - static ElementValueFinfo< CaConcBase, double > Ca_base( "Ca_base", - "Basal Calcium concentration, synonym for CaBasal", - &CaConcBase::setCaBasal, - &CaConcBase::getCaBasal - ); - static ElementValueFinfo< CaConcBase, double > tau( "tau", - "Settling time for Ca concentration", - &CaConcBase::setTau, - &CaConcBase::getTau - ); - static ElementValueFinfo< CaConcBase, double > B( "B", - "Volume scaling factor. " - "Deprecated. This is a legacy field from GENESIS and exposes " - "internal calculations. Please do not use. \n" - "B = 1/(vol * F* VALENCE) so that it obeys:\n" - "dC/dt = B*I_Ca - C/tau", - &CaConcBase::setB, - &CaConcBase::getB - ); - static ElementValueFinfo< CaConcBase, double > thick( "thick", - "Thickness of Ca shell, assumed cylindrical. Legal range is between 0 \n" - "and the radius. If outside this range it is taken as the radius. \n" - " Default zero, ie, the shell is the entire thickness of the cylinder \n", - &CaConcBase::setThickness, - &CaConcBase::getThickness - ); - static ElementValueFinfo< CaConcBase, double > length( "length", - "Length of Ca shell, assumed cylindrical", - &CaConcBase::setLength, - &CaConcBase::getLength - ); - static ElementValueFinfo< CaConcBase, double > diameter( "diameter", - "Diameter of Ca shell, assumed cylindrical", - &CaConcBase::setDiameter, - &CaConcBase::getDiameter - ); - static ElementValueFinfo< CaConcBase, double > ceiling( "ceiling", - "Ceiling value for Ca concentration. If Ca > ceiling, Ca = ceiling. \n" - "If ceiling <= 0.0, there is no upper limit on Ca concentration value.", - &CaConcBase::setCeiling, - &CaConcBase::getCeiling - ); - static ElementValueFinfo< CaConcBase, double > floor( "floor", - "Floor value for Ca concentration. If Ca < floor, Ca = floor", - &CaConcBase::setFloor, - &CaConcBase::getFloor - ); - - /////////////////////////////////////////////////////// - // MsgDest definitions - /////////////////////////////////////////////////////// - - static DestFinfo current( "current", - "Calcium Ion current, due to be converted to conc.", - new EpFunc1< CaConcBase, double >( &CaConcBase::current ) - ); - - static DestFinfo currentFraction( "currentFraction", - "Fraction of total Ion current, that is carried by Ca2+.", - new EpFunc2< CaConcBase, double, double >( &CaConcBase::currentFraction ) - ); - - static DestFinfo increase( "increase", - "Any input current that increases the concentration.", - new EpFunc1< CaConcBase, double >( &CaConcBase::increase ) - ); - - static DestFinfo decrease( "decrease", - "Any input current that decreases the concentration.", - new EpFunc1< CaConcBase, double >( &CaConcBase::decrease ) - ); - - static DestFinfo basal( "basal", - "Synonym for assignment of basal conc.", - new EpFunc1< CaConcBase, double >( &CaConcBase::setCaBasal ) - ); - - static Finfo* CaConcBaseFinfos[] = + static SharedFinfo proc( "proc", + "Shared message to receive Process message from scheduler", + processShared, sizeof( processShared ) / sizeof( Finfo* ) ); + + /////////////////////////////////////////////////////// + // Field definitions + /////////////////////////////////////////////////////// + static ElementValueFinfo< CaConcBase, double > Ca( "Ca", + "Calcium concentration.", + &CaConcBase::setCa, + &CaConcBase::getCa + ); + static ElementValueFinfo< CaConcBase, double > CaBasal( "CaBasal", + "Basal Calcium concentration.", + &CaConcBase::setCaBasal, + &CaConcBase::getCaBasal + ); + static ElementValueFinfo< CaConcBase, double > Ca_base( "Ca_base", + "Basal Calcium concentration, synonym for CaBasal", + &CaConcBase::setCaBasal, + &CaConcBase::getCaBasal + ); + static ElementValueFinfo< CaConcBase, double > tau( "tau", + "Settling time for Ca concentration", + &CaConcBase::setTau, + &CaConcBase::getTau + ); + static ElementValueFinfo< CaConcBase, double > B( "B", + "Volume scaling factor. " + "Deprecated. This is a legacy field from GENESIS and exposes " + "internal calculations. Please do not use. \n" + "B = 1/(vol * F* VALENCE) so that it obeys:\n" + "dC/dt = B*I_Ca - C/tau", + &CaConcBase::setB, + &CaConcBase::getB + ); + static ElementValueFinfo< CaConcBase, double > thick( "thick", + "Thickness of Ca shell, assumed cylindrical. Legal range is between 0 \n" + "and the radius. If outside this range it is taken as the radius. \n" + " Default zero, ie, the shell is the entire thickness of the cylinder \n", + &CaConcBase::setThickness, + &CaConcBase::getThickness + ); + static ElementValueFinfo< CaConcBase, double > length( "length", + "Length of Ca shell, assumed cylindrical", + &CaConcBase::setLength, + &CaConcBase::getLength + ); + static ElementValueFinfo< CaConcBase, double > diameter( "diameter", + "Diameter of Ca shell, assumed cylindrical", + &CaConcBase::setDiameter, + &CaConcBase::getDiameter + ); + static ElementValueFinfo< CaConcBase, double > ceiling( "ceiling", + "Ceiling value for Ca concentration. If Ca > ceiling, Ca = ceiling. \n" + "If ceiling <= 0.0, there is no upper limit on Ca concentration value.", + &CaConcBase::setCeiling, + &CaConcBase::getCeiling + ); + static ElementValueFinfo< CaConcBase, double > floor( "floor", + "Floor value for Ca concentration. If Ca < floor, Ca = floor", + &CaConcBase::setFloor, + &CaConcBase::getFloor + ); + + /////////////////////////////////////////////////////// + // MsgDest definitions + /////////////////////////////////////////////////////// + + static DestFinfo current( "current", + "Calcium Ion current, due to be converted to conc.", + new EpFunc1< CaConcBase, double >( &CaConcBase::current ) + ); + + static DestFinfo currentFraction( "currentFraction", + "Fraction of total Ion current, that is carried by Ca2+.", + new EpFunc2< CaConcBase, double, double >( &CaConcBase::currentFraction ) + ); + + static DestFinfo increase( "increase", + "Any input current that increases the concentration.", + new EpFunc1< CaConcBase, double >( &CaConcBase::increase ) + ); + + static DestFinfo decrease( "decrease", + "Any input current that decreases the concentration.", + new EpFunc1< CaConcBase, double >( &CaConcBase::decrease ) + ); + + static DestFinfo basal( "basal", + "Synonym for assignment of basal conc.", + new EpFunc1< CaConcBase, double >( &CaConcBase::setCaBasal ) + ); + + static Finfo* CaConcBaseFinfos[] = { - &proc, // Shared - concOut(), // Src - &Ca, // Value - &CaBasal, // Value - &Ca_base, // Value - &tau, // Value - &B, // Value - &thick, // Value - &diameter, // Value - &length, // Value - &ceiling, // Value - &floor, // Value - ¤t, // Dest - ¤tFraction, // Dest - &increase, // Dest - &decrease, // Dest - &basal, // Dest + &proc, // Shared + concOut(), // Src + &Ca, // Value + &CaBasal, // Value + &Ca_base, // Value + &tau, // Value + &B, // Value + &thick, // Value + &diameter, // Value + &length, // Value + &ceiling, // Value + &floor, // Value + ¤t, // Dest + ¤tFraction, // Dest + &increase, // Dest + &decrease, // Dest + &basal, // Dest }; - // We want the Ca updates before channel updates, so along with compts. - // static SchedInfo schedInfo[] = { { process, 0, 0 } }; + // We want the Ca updates before channel updates, so along with compts. + // static SchedInfo schedInfo[] = { { process, 0, 0 } }; - static string doc[] = + static string doc[] = { - "Name", "CaConcBase", - "Author", "Upinder S. Bhalla, 2014, NCBS", - "Description", - "CaConcBase: Base class for Calcium concentration pool. \n" - "Takes current from a channel and keeps track of calcium buildup and \n" - " depletion by a single exponential process. ", + "Name", "CaConcBase", + "Author", "Upinder S. Bhalla, 2014, NCBS", + "Description", + "CaConcBase: Base class for Calcium concentration pool. \n" + "Takes current from a channel and keeps track of calcium buildup and \n" + " depletion by a single exponential process. ", }; - static ZeroSizeDinfo< int > dinfo; + static ZeroSizeDinfo< int > dinfo; - static Cinfo CaConcBaseCinfo( - "CaConcBase", - Neutral::initCinfo(), - CaConcBaseFinfos, - sizeof( CaConcBaseFinfos )/sizeof(Finfo *), - &dinfo, - doc, - sizeof(doc)/sizeof(string) - ); + static Cinfo CaConcBaseCinfo( + "CaConcBase", + Neutral::initCinfo(), + CaConcBaseFinfos, + sizeof( CaConcBaseFinfos )/sizeof(Finfo *), + &dinfo, + doc, + sizeof(doc)/sizeof(string) + ); - return &CaConcBaseCinfo; + return &CaConcBaseCinfo; } /////////////////////////////////////////////////// static const Cinfo* caConcCinfo = CaConcBase::initCinfo(); CaConcBase::CaConcBase() - : - thickness_( 0.0 ) + : + thickness_( 0.0 ) {;} /////////////////////////////////////////////////// @@ -204,98 +205,99 @@ CaConcBase::CaConcBase() void CaConcBase::setCa( const Eref& e, double Ca ) { - vSetCa( e, Ca ); + vSetCa( e, Ca ); } double CaConcBase::getCa( const Eref& e ) const { - return vGetCa( e ); + return vGetCa( e ); } void CaConcBase::setCaBasal( const Eref& e, double CaBasal ) { - vSetCaBasal( e, CaBasal ); + vSetCaBasal( e, CaBasal ); } double CaConcBase::getCaBasal( const Eref& e ) const { - return vGetCaBasal( e ); + return vGetCaBasal( e ); } void CaConcBase::setTau( const Eref& e, double tau ) { - vSetTau( e, tau ); + vSetTau( e, tau ); } double CaConcBase::getTau( const Eref& e ) const { - return vGetTau( e ); + return vGetTau( e ); } void CaConcBase::setB( const Eref& e, double B ) { - vSetB( e, B ); + vSetB( e, B ); } double CaConcBase::getB( const Eref& e ) const { - return vGetB( e ); + return vGetB( e ); } void CaConcBase::setCeiling( const Eref& e, double ceiling ) { - vSetCeiling( e, ceiling ); + vSetCeiling( e, ceiling ); } double CaConcBase::getCeiling( const Eref& e ) const { - return vGetCeiling( e ); + return vGetCeiling( e ); } void CaConcBase::setFloor( const Eref& e, double floor ) { - vSetFloor( e, floor ); + vSetFloor( e, floor ); } double CaConcBase::getFloor( const Eref& e ) const { - return vGetFloor( e ); + return vGetFloor( e ); } void CaConcBase::updateDimensions( const Eref& e ) { - double vol = PI * diameter_ * diameter_ * length_ * 0.25; - if ( thickness_ > 0 && thickness_ < diameter_/2.0 ) { - double coreRadius = diameter_ / 2.0 - thickness_; - vol -= PI * coreRadius * coreRadius * length_; - } - double B = 1.0 / ( VALENCE* FaradayConst * vol ); - vSetB( e, B ); + double vol = PI * diameter_ * diameter_ * length_ * 0.25; + if ( thickness_ > 0 && thickness_ < diameter_/2.0 ) + { + double coreRadius = diameter_ / 2.0 - thickness_; + vol -= PI * coreRadius * coreRadius * length_; + } + double B = 1.0 / ( VALENCE* FaradayConst * vol ); + vSetB( e, B ); } void CaConcBase::setThickness( const Eref& e, double thickness ) { - thickness_ = thickness; - updateDimensions( e ); + thickness_ = thickness; + updateDimensions( e ); } double CaConcBase::getThickness( const Eref& e ) const { - return thickness_; + return thickness_; } void CaConcBase::setDiameter( const Eref& e, double diameter ) { - diameter_ = diameter; - updateDimensions( e ); + diameter_ = diameter; + updateDimensions( e ); } double CaConcBase::getDiameter( const Eref& e ) const { - return diameter_; + return diameter_; } void CaConcBase::setLength( const Eref& e, double length ) { - length_ = length; - updateDimensions( e ); + length_ = length; + updateDimensions( e ); } double CaConcBase::getLength( const Eref& e ) const { - return length_; + return length_; } /////////////////////////////////////////////////// @@ -304,32 +306,32 @@ double CaConcBase::getLength( const Eref& e ) const void CaConcBase::reinit( const Eref& e, ProcPtr p ) { - vReinit( e, p ); + vReinit( e, p ); } void CaConcBase::process( const Eref& e, ProcPtr p ) { - vProcess( e, p ); + vProcess( e, p ); } void CaConcBase::current( const Eref& e, double I ) { - vCurrent( e, I ); + vCurrent( e, I ); } void CaConcBase::currentFraction( const Eref& e, double I, double fraction ) { - vCurrentFraction( e, I, fraction ); + vCurrentFraction( e, I, fraction ); } void CaConcBase::increase( const Eref& e, double I ) { - vIncrease( e, I ); + vIncrease( e, I ); } void CaConcBase::decrease( const Eref& e, double I ) { - vDecrease( e, I ); + vDecrease( e, I ); } ///////////////////////////////////////////////////// @@ -342,48 +344,48 @@ void CaConcBase::vSetSolver( const Eref& e, Id hsolve ) {;} // static func -void CaConcBase::zombify( Element* orig, const Cinfo* zClass, - Id hsolve ) +void CaConcBase::zombify( Element* orig, const Cinfo* zClass, Id hsolve ) { - if ( orig->cinfo() == zClass ) - return; - unsigned int start = orig->localDataStart(); - unsigned int num = orig->numLocalData(); - if ( num == 0 ) - return; - vector< double > data( num * 9 ); - - unsigned int j = 0; - for ( unsigned int i = 0; i < num; ++i ) { - Eref er( orig, i + start ); - const CaConcBase* cb = - reinterpret_cast< const CaConcBase* >( er.data() ); - data[j + 0] = cb->getCa( er ); - data[j + 1] = cb->getCaBasal( er ); - data[j + 2] = cb->getTau( er ); - data[j + 3] = cb->getB( er ); - data[j + 4] = cb->getCeiling( er ); - data[j + 5] = cb->getFloor( er ); - data[j + 6] = cb->getThickness( er ); - data[j + 7] = cb->getLength( er ); - data[j + 8] = cb->getDiameter( er ); - j += 9; - } - orig->zombieSwap( zClass ); - j = 0; - for ( unsigned int i = 0; i < num; ++i ) { - Eref er( orig, i + start ); - CaConcBase* cb = reinterpret_cast< CaConcBase* >( er.data() ); - cb->vSetSolver( er, hsolve ); - cb->setCa( er, data[j + 0] ); - cb->setCaBasal( er, data[j + 1] ); - cb->setTau( er, data[j + 2] ); - cb->setB( er, data[j + 3] ); - cb->setCeiling( er, data[j + 4] ); - cb->setFloor( er, data[j + 5] ); - cb->setThickness( er, data[j + 6] ); - cb->setLength( er, data[j + 7] ); - cb->setDiameter( er, data[j + 8] ); - j += 9; //was 7? - } + if ( orig->cinfo() == zClass ) + return; + unsigned int start = orig->localDataStart(); + unsigned int num = orig->numLocalData(); + if ( num == 0 ) + return; + vector< double > data( num * 9 ); + + unsigned int j = 0; + for ( unsigned int i = 0; i < num; ++i ) + { + Eref er( orig, i + start ); + const CaConcBase* cb = reinterpret_cast(er.data()); + data[j + 0] = cb->getCa( er ); + data[j + 1] = cb->getCaBasal( er ); + data[j + 2] = cb->getTau( er ); + data[j + 3] = cb->getB( er ); + data[j + 4] = cb->getCeiling( er ); + data[j + 5] = cb->getFloor( er ); + data[j + 6] = cb->getThickness( er ); + data[j + 7] = cb->getLength( er ); + data[j + 8] = cb->getDiameter( er ); + j += 9; + } + orig->zombieSwap( zClass ); + j = 0; + for ( unsigned int i = 0; i < num; ++i ) + { + Eref er( orig, i + start ); + CaConcBase* cb = reinterpret_cast< CaConcBase* >( er.data() ); + cb->vSetSolver( er, hsolve ); + cb->setCa( er, data[j + 0] ); + cb->setCaBasal( er, data[j + 1] ); + cb->setTau( er, data[j + 2] ); + cb->setB( er, data[j + 3] ); + cb->setCeiling( er, data[j + 4] ); + cb->setFloor( er, data[j + 5] ); + cb->setThickness( er, data[j + 6] ); + cb->setLength( er, data[j + 7] ); + cb->setDiameter( er, data[j + 8] ); + j += 9; //was 7? + } } diff --git a/biophysics/MarkovChannel.cpp b/biophysics/MarkovChannel.cpp index a79b17b4..bca0cc25 100644 --- a/biophysics/MarkovChannel.cpp +++ b/biophysics/MarkovChannel.cpp @@ -21,207 +21,207 @@ const Cinfo* MarkovChannel::initCinfo() { - /////////////////////// - //Field information. - /////////////////////// - static ValueFinfo< MarkovChannel, double > ligandconc( "ligandConc", - "Ligand concentration.", - &MarkovChannel::setLigandConc, - &MarkovChannel::getLigandConc - ); - - static ValueFinfo< MarkovChannel, double > vm( "Vm", - "Membrane voltage.", - &MarkovChannel::setVm, - &MarkovChannel::getVm - ); - - static ValueFinfo< MarkovChannel, unsigned int > numstates( "numStates", - "The number of states that the channel can occupy.", - &MarkovChannel::setNumStates, - &MarkovChannel::getNumStates - ); - - - static ValueFinfo< MarkovChannel, unsigned int > numopenstates( "numOpenStates", - "The number of states which are open/conducting.", - &MarkovChannel::setNumOpenStates, - &MarkovChannel::getNumOpenStates - ); - - static ValueFinfo< MarkovChannel, vector< string > > labels("labels", - "Labels for each state.", - &MarkovChannel::setStateLabels, - &MarkovChannel::getStateLabels - ); - - static ReadOnlyValueFinfo< MarkovChannel, vector< double > > state( "state", - "This is a row vector that contains the probabilities of finding the channel in each state.", - &MarkovChannel::getState - ); - - static ValueFinfo< MarkovChannel, vector< double > > initialstate( "initialState", - "This is a row vector that contains the probabilities of finding the channel in each state at t = 0. The state of the channel is reset to this value during a call to reinit()", - &MarkovChannel::setInitialState, - &MarkovChannel::getInitialState - ); - - static ValueFinfo< MarkovChannel, vector< double > > gbar( "gbar", - "A row vector containing the conductance associated with each of the open/conducting states.", - &MarkovChannel::setGbars, - &MarkovChannel::getGbars - ); - - //MsgDest functions - static DestFinfo handleligandconc( "handleLigandConc", - "Deals with incoming messages containing information of ligand concentration", - new OpFunc1< MarkovChannel, double >(&MarkovChannel::handleLigandConc) ); - - static DestFinfo handlestate("handleState", - "Deals with incoming message from MarkovSolver object containing state information of the channel.\n", - new OpFunc1< MarkovChannel, vector< double > >(&MarkovChannel::handleState) ); - - /////////////////////////////////////////// - static Finfo* MarkovChannelFinfos[] = - { - &ligandconc, - &vm, - &numstates, - &numopenstates, - &state, - &initialstate, - &labels, - &gbar, - &handleligandconc, - &handlestate, - }; - - static string doc[] = - { - "Name", "MarkovChannel", - "Author", "Vishaka Datta S, 2011, NCBS", - "Description", "MarkovChannel : Multistate ion channel class." - "It deals with ion channels which can be found in one of multiple states, " - "some of which are conducting. This implementation assumes the occurence " - "of first order kinetics to calculate the probabilities of the channel " - "being found in all states. Further, the rates of transition between these " - "states can be constant, voltage-dependent or ligand dependent (only one " - "ligand species). The current flow obtained from the channel is calculated " - "in a deterministic method by solving the system of differential equations " - "obtained from the assumptions above." - }; - - static Dinfo< MarkovChannel > dinfo; - static Cinfo MarkovChannelCinfo( - "MarkovChannel", - ChanBase::initCinfo(), - MarkovChannelFinfos, - sizeof( MarkovChannelFinfos )/ sizeof( Finfo* ), - &dinfo, + /////////////////////// + //Field information. + /////////////////////// + static ValueFinfo< MarkovChannel, double > ligandconc( "ligandConc", + "Ligand concentration.", + &MarkovChannel::setLigandConc, + &MarkovChannel::getLigandConc + ); + + static ValueFinfo< MarkovChannel, double > vm( "Vm", + "Membrane voltage.", + &MarkovChannel::setVm, + &MarkovChannel::getVm + ); + + static ValueFinfo< MarkovChannel, unsigned int > numstates( "numStates", + "The number of states that the channel can occupy.", + &MarkovChannel::setNumStates, + &MarkovChannel::getNumStates + ); + + + static ValueFinfo< MarkovChannel, unsigned int > numopenstates( "numOpenStates", + "The number of states which are open/conducting.", + &MarkovChannel::setNumOpenStates, + &MarkovChannel::getNumOpenStates + ); + + static ValueFinfo< MarkovChannel, vector< string > > labels("labels", + "Labels for each state.", + &MarkovChannel::setStateLabels, + &MarkovChannel::getStateLabels + ); + + static ReadOnlyValueFinfo< MarkovChannel, vector< double > > state( "state", + "This is a row vector that contains the probabilities of finding the channel in each state.", + &MarkovChannel::getState + ); + + static ValueFinfo< MarkovChannel, vector< double > > initialstate( "initialState", + "This is a row vector that contains the probabilities of finding the channel in each state at t = 0. The state of the channel is reset to this value during a call to reinit()", + &MarkovChannel::setInitialState, + &MarkovChannel::getInitialState + ); + + static ValueFinfo< MarkovChannel, vector< double > > gbar( "gbar", + "A row vector containing the conductance associated with each of the open/conducting states.", + &MarkovChannel::setGbars, + &MarkovChannel::getGbars + ); + + //MsgDest functions + static DestFinfo handleligandconc( "handleLigandConc", + "Deals with incoming messages containing information of ligand concentration", + new OpFunc1< MarkovChannel, double >(&MarkovChannel::handleLigandConc) ); + + static DestFinfo handlestate("handleState", + "Deals with incoming message from MarkovSolver object containing state information of the channel.\n", + new OpFunc1< MarkovChannel, vector< double > >(&MarkovChannel::handleState) ); + + /////////////////////////////////////////// + static Finfo* MarkovChannelFinfos[] = + { + &ligandconc, + &vm, + &numstates, + &numopenstates, + &state, + &initialstate, + &labels, + &gbar, + &handleligandconc, + &handlestate, + }; + + static string doc[] = + { + "Name", "MarkovChannel", + "Author", "Vishaka Datta S, 2011, NCBS Bangalore", + "Description", "MarkovChannel.\n" + "It deals with ion channels which can be found in one of multiple states, " + "some of which are conducting. This implementation assumes the occurence " + "of first order kinetics to calculate the probabilities of the channel " + "being found in all states. Further, the rates of transition between these " + "states can be constant, voltage-dependent or ligand dependent (only one " + "ligand species). The current flow obtained from the channel is calculated " + "in a deterministic method by solving the system of differential equations " + "obtained from the assumptions above." + }; + + static Dinfo< MarkovChannel > dinfo; + static Cinfo MarkovChannelCinfo( + "MarkovChannel", + ChanBase::initCinfo(), + MarkovChannelFinfos, + sizeof( MarkovChannelFinfos )/ sizeof( Finfo* ), + &dinfo, doc, sizeof(doc) / sizeof(string) - ); + ); - return &MarkovChannelCinfo; + return &MarkovChannelCinfo; } static const Cinfo* markovChannelCinfo = MarkovChannel::initCinfo(); MarkovChannel::MarkovChannel() : - g_(0), - ligandConc_(0), - numStates_(0), - numOpenStates_(0) + g_(0), + ligandConc_(0), + numStates_(0), + numOpenStates_(0) { ; } MarkovChannel::MarkovChannel(unsigned int numStates, unsigned int numOpenStates) : - g_(0), ligandConc_(0), numStates_(numStates), numOpenStates_(numOpenStates) + g_(0), ligandConc_(0), numStates_(numStates), numOpenStates_(numOpenStates) { - stateLabels_.resize( numStates ); - state_.resize( numStates ); - initialState_.resize( numStates ); - Gbars_.resize( numOpenStates ) ; + stateLabels_.resize( numStates ); + state_.resize( numStates ); + initialState_.resize( numStates ); + Gbars_.resize( numOpenStates ) ; } MarkovChannel::~MarkovChannel( ) { - ; + ; } double MarkovChannel::getVm( ) const { - return Vm_; + return Vm_; } void MarkovChannel::setVm( double Vm ) { - Vm_ = Vm; + Vm_ = Vm; } double MarkovChannel::getLigandConc( ) const { - return ligandConc_; + return ligandConc_; } void MarkovChannel::setLigandConc( double ligandConc ) { - ligandConc_ = ligandConc; + ligandConc_ = ligandConc; } unsigned int MarkovChannel::getNumStates( ) const { - return numStates_; + return numStates_; } void MarkovChannel::setNumStates( unsigned int numStates ) { - numStates_ = numStates; + numStates_ = numStates; } unsigned int MarkovChannel::getNumOpenStates( ) const { - return numOpenStates_; + return numOpenStates_; } void MarkovChannel::setNumOpenStates( unsigned int numOpenStates ) { - numOpenStates_ = numOpenStates; + numOpenStates_ = numOpenStates; } vector< string > MarkovChannel::getStateLabels( ) const { - return stateLabels_; + return stateLabels_; } void MarkovChannel::setStateLabels( vector< string > stateLabels ) { - stateLabels_ = stateLabels; + stateLabels_ = stateLabels; } vector< double > MarkovChannel::getState ( ) const { - return state_; + return state_; } vector< double > MarkovChannel::getInitialState() const { - return initialState_; + return initialState_; } void MarkovChannel::setInitialState( vector< double > initialState ) { - initialState_ = initialState; - state_ = initialState; + initialState_ = initialState; + state_ = initialState; } vector< double > MarkovChannel::getGbars() const { - return Gbars_; + return Gbars_; } void MarkovChannel::setGbars( vector< double > Gbars ) { - Gbars_ = Gbars; + Gbars_ = Gbars; } ///////////////////////////// @@ -230,41 +230,41 @@ void MarkovChannel::setGbars( vector< double > Gbars ) void MarkovChannel::vProcess( const Eref& e, const ProcPtr p ) { - g_ = 0.0; + g_ = 0.0; - //Cannot use the Gbar_ variable of the ChanBase class. The conductance - //Gk_ calculated here is the "expected conductance" of the channel due to its - //stochastic nature. + //Cannot use the Gbar_ variable of the ChanBase class. The conductance + //Gk_ calculated here is the "expected conductance" of the channel due to its + //stochastic nature. - for( unsigned int i = 0; i < numOpenStates_; ++i ) - g_ += Gbars_[i] * state_[i]; + for( unsigned int i = 0; i < numOpenStates_; ++i ) + g_ += Gbars_[i] * state_[i]; - setGk( e, g_ ); - updateIk(); + setGk( e, g_ ); + updateIk(); - sendProcessMsgs( e, p ); + sendProcessMsgs( e, p ); } void MarkovChannel::vReinit( const Eref& e, const ProcPtr p ) { - g_ = 0.0; + g_ = 0.0; - if ( initialState_.empty() ) - { - cerr << "MarkovChannel::reinit : Initial state has not been set.!\n"; - return; - } - state_ = initialState_; + if ( initialState_.empty() ) + { + cerr << "MarkovChannel::reinit : Initial state has not been set.!\n"; + return; + } + state_ = initialState_; - sendReinitMsgs( e, p ); + sendReinitMsgs( e, p ); } void MarkovChannel::handleLigandConc( double ligandConc ) { - ligandConc_ = ligandConc; + ligandConc_ = ligandConc; } void MarkovChannel::handleState( vector< double > state ) { - state_ = state; + state_ = state; } diff --git a/biophysics/MarkovGslSolver.cpp b/biophysics/MarkovGslSolver.cpp deleted file mode 100644 index ca90e7a3..00000000 --- a/biophysics/MarkovGslSolver.cpp +++ /dev/null @@ -1,350 +0,0 @@ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment. -** Copyright (C) 2003-2011 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU Lesser General Public License version 2.1 -** See the file COPYING.LIB for the full notice. -**********************************************************************/ - -#include "../basecode/header.h" -#include -#include -#include "MarkovGslSolver.h" - -static SrcFinfo1< vector >* stateOut() -{ - static SrcFinfo1< vector< double > > stateOut( "stateOut", - "Sends updated state to the MarkovChannel class." ); - return &stateOut; -} - -const Cinfo* MarkovGslSolver::initCinfo() -{ - /////////////////////////////////////////////////////// - // Field definitions - /////////////////////////////////////////////////////// - static ReadOnlyValueFinfo< MarkovGslSolver, bool > isInitialized( - "isInitialized", - "True if the message has come in to set solver parameters.", - &MarkovGslSolver::getIsInitialized - ); - static ValueFinfo< MarkovGslSolver, string > method( "method", - "Numerical method to use.", - &MarkovGslSolver::setMethod, - &MarkovGslSolver::getMethod - ); - static ValueFinfo< MarkovGslSolver, double > relativeAccuracy( - "relativeAccuracy", - "Accuracy criterion", - &MarkovGslSolver::setRelativeAccuracy, - &MarkovGslSolver::getRelativeAccuracy - ); - static ValueFinfo< MarkovGslSolver, double > absoluteAccuracy( - "absoluteAccuracy", - "Another accuracy criterion", - &MarkovGslSolver::setAbsoluteAccuracy, - &MarkovGslSolver::getAbsoluteAccuracy - ); - static ValueFinfo< MarkovGslSolver, double > internalDt( - "internalDt", - "internal timestep to use.", - &MarkovGslSolver::setInternalDt, - &MarkovGslSolver::getInternalDt - ); - - /////////////////////////////////////////////////////// - // DestFinfo definitions - /////////////////////////////////////////////////////// - static DestFinfo init( "init", - "Initialize solver parameters.", - new OpFunc1< MarkovGslSolver, vector< double > > - ( &MarkovGslSolver::init ) - ); - - static DestFinfo handleQ( "handleQ", - "Handles information regarding the instantaneous rate matrix from " - "the MarkovRateTable class.", - new OpFunc1< MarkovGslSolver, vector< vector< double > > >( &MarkovGslSolver::handleQ) ); - - static DestFinfo process( "process", - "Handles process call", - new ProcOpFunc< MarkovGslSolver >( &MarkovGslSolver::process ) ); - static DestFinfo reinit( "reinit", - "Handles reinit call", - new ProcOpFunc< MarkovGslSolver >( &MarkovGslSolver::reinit ) ); - /////////////////////////////////////////////////////// - // Shared definitions - /////////////////////////////////////////////////////// - static Finfo* procShared[] = { - &process, &reinit - }; - static SharedFinfo proc( "proc", - "Shared message for process and reinit", - procShared, sizeof( procShared ) / sizeof( const Finfo* ) - ); - - static Finfo* MarkovGslFinfos[] = - { - &isInitialized, // ValueFinfo - &method, // ValueFinfo - &relativeAccuracy, // ValueFinfo - &absoluteAccuracy, // ValueFinfo - &internalDt, // ValueFinfo - &init, // DestFinfo - &handleQ, // DestFinfo - &proc, // SharedFinfo - stateOut(), // SrcFinfo - }; - - static string doc[] = - { - "Name", "MarkovGslSolver", - "Author", "Vishaka Datta S, 2011, NCBS", - "Description", "Solver for Markov Channel." - }; - - static Dinfo< MarkovGslSolver > dinfo; - static Cinfo MarkovGslSolverCinfo( - "MarkovGslSolver", - Neutral::initCinfo(), - MarkovGslFinfos, - sizeof(MarkovGslFinfos)/sizeof(Finfo *), - &dinfo, - doc, - sizeof(doc) / sizeof(string) - ); - - return &MarkovGslSolverCinfo; -} - -static const Cinfo* MarkovGslSolverCinfo = MarkovGslSolver::initCinfo(); - -/////////////////////////////////////////////////// -// Basic class function definitions -/////////////////////////////////////////////////// - -MarkovGslSolver::MarkovGslSolver() -{ - isInitialized_ = 0; - method_ = "rk5"; - gslStepType_ = gsl_odeiv_step_rkf45; - gslStep_ = 0; - nVars_ = 0; - absAccuracy_ = 1.0e-8; - relAccuracy_ = 1.0e-8; - internalStepSize_ = 1.0e-6; - stateGsl_ = 0; - gslEvolve_ = NULL; - gslControl_ = NULL; -} - -MarkovGslSolver::~MarkovGslSolver() -{ - if ( gslEvolve_ ) - gsl_odeiv_evolve_free( gslEvolve_ ); - if ( gslControl_ ) - gsl_odeiv_control_free( gslControl_ ); - if ( gslStep_ ) - gsl_odeiv_step_free( gslStep_ ); - - if ( stateGsl_ ) - delete[] stateGsl_; -} - -int MarkovGslSolver::evalSystem( double t, const double* state, double* f, void *params) -{ - vector< vector< double > >* Q = static_cast< vector< vector< double > >* >( params ); - unsigned int nVars = Q->size(); - - //Matrix being accessed along columns, which is a very bad thing in terms of - //cache optimality. Transposing the matrix during reinit() would be a good idea. - for ( unsigned int i = 0; i < nVars; ++i) - { - f[i] = 0; - for ( unsigned int j = 0; j < nVars; ++j) - f[i] += state[j] * ((*Q)[j][i]); - } - - return GSL_SUCCESS; -} - -/////////////////////////////////////////////////// -// Field function definitions -/////////////////////////////////////////////////// - -bool MarkovGslSolver::getIsInitialized() const -{ - return isInitialized_; -} - -string MarkovGslSolver::getMethod() const -{ - return method_; -} - -void MarkovGslSolver::setMethod( string method ) -{ - method_ = method; - gslStepType_ = 0; - - if ( method == "rk2" ) { - gslStepType_ = gsl_odeiv_step_rk2; - } else if ( method == "rk4" ) { - gslStepType_ = gsl_odeiv_step_rk4; - } else if ( method == "rk5" ) { - gslStepType_ = gsl_odeiv_step_rkf45; - } else if ( method == "rkck" ) { - gslStepType_ = gsl_odeiv_step_rkck; - } else if ( method == "rk8pd" ) { - gslStepType_ = gsl_odeiv_step_rk8pd; - } else if ( method == "rk2imp" ) { - gslStepType_ = gsl_odeiv_step_rk2imp; - } else if ( method == "rk4imp" ) { - gslStepType_ = gsl_odeiv_step_rk4imp; - } else if ( method == "bsimp" ) { - gslStepType_ = gsl_odeiv_step_rk4imp; - cout << "Warning: implicit Bulirsch-Stoer method not yet implemented: needs Jacobian\n"; - } else if ( method == "gear1" ) { - gslStepType_ = gsl_odeiv_step_gear1; - } else if ( method == "gear2" ) { - gslStepType_ = gsl_odeiv_step_gear2; - } else { - cout << "Warning: MarkovGslSolver::innerSetMethod: method '" << - method << "' not known, using rk5\n"; - gslStepType_ = gsl_odeiv_step_rkf45; - } -} - -double MarkovGslSolver::getRelativeAccuracy() const -{ - return relAccuracy_; -} - -void MarkovGslSolver::setRelativeAccuracy( double value ) -{ - relAccuracy_ = value; -} - -double MarkovGslSolver::getAbsoluteAccuracy() const -{ - return absAccuracy_; -} -void MarkovGslSolver::setAbsoluteAccuracy( double value ) -{ - absAccuracy_ = value; -} - -double MarkovGslSolver::getInternalDt() const -{ - return internalStepSize_; -} - -void MarkovGslSolver::setInternalDt( double value ) -{ - internalStepSize_ = value; -} - -/////////////////////////////////////////////////// -// Dest function definitions -/////////////////////////////////////////////////// - -//Handles data from MarkovChannel class. -void MarkovGslSolver::init( vector< double > initialState ) -{ - nVars_ = initialState.size(); - - if ( stateGsl_ == 0 ) - stateGsl_ = new double[ nVars_ ]; - - state_ = initialState; - initialState_ = initialState; - - Q_.resize( nVars_ ); - - for ( unsigned int i = 0; i < nVars_; ++i ) - Q_[i].resize( nVars_, 0.0 ); - - isInitialized_ = 1; - - assert( gslStepType_ != 0 ); - if ( gslStep_ ) - gsl_odeiv_step_free(gslStep_); - - gslStep_ = gsl_odeiv_step_alloc( gslStepType_, nVars_ ); - assert( gslStep_ != 0 ); - - if ( !gslEvolve_ ) - gslEvolve_ = gsl_odeiv_evolve_alloc(nVars_); - else - gsl_odeiv_evolve_reset(gslEvolve_); - - assert(gslEvolve_ != 0); - - if ( !gslControl_ ) - gslControl_ = gsl_odeiv_control_y_new( absAccuracy_, relAccuracy_ ); - else - gsl_odeiv_control_init(gslControl_,absAccuracy_, relAccuracy_, 1, 0); - - assert(gslControl_!= 0); - - gslSys_.function = &MarkovGslSolver::evalSystem; - gslSys_.jacobian = 0; - gslSys_.dimension = nVars_; - gslSys_.params = static_cast< void * >( &Q_ ); -} - -////////////////////////// -//MsgDest functions. -///////////////////////// -void MarkovGslSolver::process( const Eref& e, ProcPtr info ) -{ - double nextt = info->currTime + info->dt; - double t = info->currTime; - double sum = 0; - - for ( unsigned int i = 0; i < nVars_; ++i ) - stateGsl_[i] = state_[i]; - - while ( t < nextt ) { - int status = gsl_odeiv_evolve_apply ( - gslEvolve_, gslControl_, gslStep_, &gslSys_, - &t, nextt, - &internalStepSize_, stateGsl_); - - //Simple idea borrowed from Dieter Jaeger's implementation of a Markov - //channel to deal with potential round-off error. - sum = 0; - for ( unsigned int i = 0; i < nVars_; i++ ) - sum += stateGsl_[i]; - - for ( unsigned int i = 0; i < nVars_; i++ ) - stateGsl_[i] /= sum; - - if ( status != GSL_SUCCESS ) - break; - } - - for ( unsigned int i = 0; i < nVars_; ++i ) - state_[i] = stateGsl_[i]; - - stateOut()->send( e, state_ ); -} - -void MarkovGslSolver::reinit( const Eref& e, ProcPtr info ) -{ - state_ = initialState_; - if ( initialState_.empty() ) - { - cerr << "MarkovGslSolver::reinit : " - "Initial state has not been set. Solver has not been initialized." - "Call init() before running.\n"; - } - - stateOut()->send( e, state_ ); -} - -void MarkovGslSolver::handleQ( vector< vector< double > > Q ) -{ - Q_ = Q; -} diff --git a/biophysics/MarkovGslSolver.h b/biophysics/MarkovGslSolver.h deleted file mode 100644 index a1ae31f1..00000000 --- a/biophysics/MarkovGslSolver.h +++ /dev/null @@ -1,78 +0,0 @@ -/********************************************************************** -** This program is part of 'MOOSE', the -** Messaging Object Oriented Simulation Environment. -** Copyright (C) 2003-2011 Upinder S. Bhalla. and NCBS -** It is made available under the terms of the -** GNU Lesser General Public License version 2.1 -** See the file COPYING.LIB for the full notice. -**********************************************************************/ - -#ifndef _MARKOVGSLSOLVER_H -#define _MARKOVGSLSOLVER_H - -//////////////////////////////////////////////////// -// Class : MarkovGslSolver -// Author : Vishaka Datta S, 2011, NCBS. -// -// The GslIntegrator class in ksolve deals with a system whose coefficients stay -// constant. In the case of a Markov channel, the coefficients of the system -// vary with time. -// -// This makes it necessary for the system to keep track of changes in the system -// matrix, which is implemented by the message handler. -/////////////////////////////////////////////////// - -class MarkovGslSolver -{ - public: - MarkovGslSolver(); - ~MarkovGslSolver(); - -/////////////////////////////////////////////////// -// Field function definitions -/////////////////////////////////////////////////// - bool getIsInitialized() const; - string getMethod() const; - void setMethod( string method ); - double getRelativeAccuracy() const; - void setRelativeAccuracy( double value ); - double getAbsoluteAccuracy() const; - void setAbsoluteAccuracy( double value ); - double getInternalDt() const; - void setInternalDt( double value ); - -/////////////////////////////////////////////////// -// Dest function definitions -/////////////////////////////////////////////////// - - void process( const Eref& e, ProcPtr info ); - void reinit( const Eref& e, ProcPtr info ); - - void init( vector< double > ); - void handleQ( vector< vector< double > > ); - - static const Cinfo* initCinfo(); - private: - bool isInitialized_; - string method_; - double absAccuracy_; - double relAccuracy_; - double internalStepSize_; - double* stateGsl_; - - //The following four variables should be members of any solver class that - //will be implmented. - unsigned int nVars_; - vector< double > state_; - vector< double > initialState_; - vector< vector< double > > Q_; - - const gsl_odeiv_step_type* gslStepType_; - gsl_odeiv_step* gslStep_; - gsl_odeiv_control* gslControl_; - gsl_odeiv_evolve* gslEvolve_; - gsl_odeiv_system gslSys_; - - static int evalSystem( double, const double*, double*, void* ); -}; -#endif diff --git a/biophysics/MarkovOdeSolver.cpp b/biophysics/MarkovOdeSolver.cpp new file mode 100644 index 00000000..9e951e74 --- /dev/null +++ b/biophysics/MarkovOdeSolver.cpp @@ -0,0 +1,439 @@ +/********************************************************************** +** This program is part of 'MOOSE', the +** Messaging Object Oriented Simulation Environment. +** Copyright (C) 2003-2011 Upinder S. Bhalla. and NCBS +** It is made available under the terms of the +** GNU Lesser General Public License version 2.1 +** See the file COPYING.LIB for the full notice. +**********************************************************************/ + +#include "../basecode/header.h" +#if USE_BOOSE_ODE +#include "../utility/boost_ode.h" +#endif +#include "MarkovOdeSolver.h" + +#ifdef USE_GSL +#include +#include +#endif /* ----- not USE_GSL ----- */ + +#ifdef USE_BOOST_ODE +#include +using namespace boost::numeric; +#endif /* ----- not USE_BOOST_ODE ----- */ + +static SrcFinfo1< vector >* stateOut() +{ + static SrcFinfo1< vector< double > > stateOut( "stateOut", + "Sends updated state to the MarkovChannel class." ); + return &stateOut; +} + +const Cinfo* MarkovOdeSolver::initCinfo() +{ + /////////////////////////////////////////////////////// + // Field definitions + /////////////////////////////////////////////////////// + static ReadOnlyValueFinfo< MarkovOdeSolver, bool > isInitialized( + "isInitialized", + "True if the message has come in to set solver parameters.", + &MarkovOdeSolver::getIsInitialized + ); + static ValueFinfo< MarkovOdeSolver, string > method( "method", + "Numerical method to use.", + &MarkovOdeSolver::setMethod, + &MarkovOdeSolver::getMethod + ); + static ValueFinfo< MarkovOdeSolver, double > relativeAccuracy( + "relativeAccuracy", + "Accuracy criterion", + &MarkovOdeSolver::setRelativeAccuracy, + &MarkovOdeSolver::getRelativeAccuracy + ); + static ValueFinfo< MarkovOdeSolver, double > absoluteAccuracy( + "absoluteAccuracy", + "Another accuracy criterion", + &MarkovOdeSolver::setAbsoluteAccuracy, + &MarkovOdeSolver::getAbsoluteAccuracy + ); + static ValueFinfo< MarkovOdeSolver, double > internalDt( + "internalDt", + "internal timestep to use.", + &MarkovOdeSolver::setInternalDt, + &MarkovOdeSolver::getInternalDt + ); + + /////////////////////////////////////////////////////// + // DestFinfo definitions + /////////////////////////////////////////////////////// + static DestFinfo init( "init", + "Initialize solver parameters.", + new OpFunc1< MarkovOdeSolver, vector< double > > + ( &MarkovOdeSolver::init ) + ); + + static DestFinfo handleQ( "handleQ", + "Handles information regarding the instantaneous rate matrix from " + "the MarkovRateTable class.", + new OpFunc1< MarkovOdeSolver, vector< vector< double > > >( &MarkovOdeSolver::handleQ) ); + + static DestFinfo process( "process", + "Handles process call", + new ProcOpFunc< MarkovOdeSolver >( &MarkovOdeSolver::process ) ); + static DestFinfo reinit( "reinit", + "Handles reinit call", + new ProcOpFunc< MarkovOdeSolver >( &MarkovOdeSolver::reinit ) ); + /////////////////////////////////////////////////////// + // Shared definitions + /////////////////////////////////////////////////////// + static Finfo* procShared[] = + { + &process, &reinit + }; + static SharedFinfo proc( "proc", + "Shared message for process and reinit", + procShared, sizeof( procShared ) / sizeof( const Finfo* ) + ); + + static Finfo* MarkovOdeFinfos[] = + { + &isInitialized, // ValueFinfo + &method, // ValueFinfo + &relativeAccuracy, // ValueFinfo + &absoluteAccuracy, // ValueFinfo + &internalDt, // ValueFinfo + &init, // DestFinfo + &handleQ, // DestFinfo + &proc, // SharedFinfo + stateOut(), // SrcFinfo + }; + + static string doc[] = + { + "Name", "MarkovOdeSolver", + "Author", "Vishaka Datta (c) 2011, Dilawar Singh (c) 2018", + "Description", "Solver for Markov Channel." + }; + + static Dinfo< MarkovOdeSolver > dinfo; + static Cinfo MarkovOdeSolverCinfo( + "MarkovOdeSolver", + Neutral::initCinfo(), + MarkovOdeFinfos, + sizeof(MarkovOdeFinfos)/sizeof(Finfo *), + &dinfo, + doc, + sizeof(doc) / sizeof(string) + ); + + return &MarkovOdeSolverCinfo; +} + +static const Cinfo* MarkovOdeSolverCinfo = MarkovOdeSolver::initCinfo(); + +/////////////////////////////////////////////////// +// Basic class function definitions +/////////////////////////////////////////////////// + +MarkovOdeSolver::MarkovOdeSolver() +{ + isInitialized_ = 0; + method_ = "rk5"; +#ifdef USE_GSL + gslStepType_ = gsl_odeiv_step_rkf45; + gslEvolve_ = NULL; + gslControl_ = NULL; + gslStep_ = 0; +#endif /* ----- not USE_GSL ----- */ + nVars_ = 0; + absAccuracy_ = 1e-8; + relAccuracy_ = 1e-8; + internalStepSize_ = 1.0e-6; +} + +MarkovOdeSolver::~MarkovOdeSolver() +{ +#ifdef USE_GSL + if ( gslEvolve_ ) + gsl_odeiv_evolve_free( gslEvolve_ ); + if ( gslControl_ ) + gsl_odeiv_control_free( gslControl_ ); + if ( gslStep_ ) + gsl_odeiv_step_free( gslStep_ ); +#endif /* ----- not USE_GSL ----- */ +} + +#ifdef USE_GSL +int MarkovOdeSolver::evalSystem( double t, const double* state, double* f, void *params) +{ + vector< vector< double > >* Q = static_cast< vector< vector< double > >* >( params ); + unsigned int nVars = Q->size(); + + //Matrix being accessed along columns, which is a very bad thing in terms of + //cache optimality. Transposing the matrix during reinit() would be a good idea. + for ( unsigned int i = 0; i < nVars; ++i) + { + f[i] = 0; + for ( unsigned int j = 0; j < nVars; ++j) + f[i] += state[j] * ((*Q)[j][i]); + } + return 0; +} +#endif /* ----- not USE_GSL ----- */ + +#ifdef USE_BOOST_ODE +/* --------------------------------------------------------------------------*/ +/** + * @Synopsis OdeSystem. Similar to MarkovOdeSolver::evalSystem + * + * @Param y + * @Param dydt + */ +/* ----------------------------------------------------------------------------*/ +void MarkovOdeSolver::OdeSystem( const vector& y, vector& dydt ) +{ + unsigned int nVars = Q_.size(); + //Matrix being accessed along columns, which is a very bad thing in terms of + //cache optimality. Transposing the matrix during reinit() would be a good idea. + for ( unsigned int i = 0; i < nVars; ++i) + { + dydt[i] = 0; + for ( unsigned int j = 0; j < nVars; ++j) + dydt[i] += y[j] * Q_[j][i]; + } +} +#endif + +/////////////////////////////////////////////////// +// Field function definitions +/////////////////////////////////////////////////// + +bool MarkovOdeSolver::getIsInitialized() const +{ + return isInitialized_; +} + +string MarkovOdeSolver::getMethod() const +{ + return method_; +} + +void MarkovOdeSolver::setMethod( string method ) +{ + method_ = method; +#ifdef USE_GSL + gslStepType_ = 0; + + if ( method == "rk2" ) + { + gslStepType_ = gsl_odeiv_step_rk2; + } + else if ( method == "rk4" ) + { + gslStepType_ = gsl_odeiv_step_rk4; + } + else if ( method == "rk5" ) + { + gslStepType_ = gsl_odeiv_step_rkf45; + } + else if ( method == "rkck" ) + { + gslStepType_ = gsl_odeiv_step_rkck; + } + else if ( method == "rk8pd" ) + { + gslStepType_ = gsl_odeiv_step_rk8pd; + } + else if ( method == "rk2imp" ) + { + gslStepType_ = gsl_odeiv_step_rk2imp; + } + else if ( method == "rk4imp" ) + { + gslStepType_ = gsl_odeiv_step_rk4imp; + } + else if ( method == "bsimp" ) + { + gslStepType_ = gsl_odeiv_step_rk4imp; + cout << "Warning: implicit Bulirsch-Stoer method not yet implemented: needs Jacobian\n"; + } + else if ( method == "gear1" ) + { + gslStepType_ = gsl_odeiv_step_gear1; + } + else if ( method == "gear2" ) + { + gslStepType_ = gsl_odeiv_step_gear2; + } + else + { + cout << "Warning: MarkovOdeSolver::innerSetMethod: method '" << + method << "' not known, using rk5\n"; + gslStepType_ = gsl_odeiv_step_rkf45; + } +#endif +} + +double MarkovOdeSolver::getRelativeAccuracy() const +{ + return relAccuracy_; +} + +void MarkovOdeSolver::setRelativeAccuracy( double value ) +{ + relAccuracy_ = value; +} + +double MarkovOdeSolver::getAbsoluteAccuracy() const +{ + return absAccuracy_; +} +void MarkovOdeSolver::setAbsoluteAccuracy( double value ) +{ + absAccuracy_ = value; +} + +double MarkovOdeSolver::getInternalDt() const +{ + return internalStepSize_; +} + +void MarkovOdeSolver::setInternalDt( double value ) +{ + internalStepSize_ = value; +} + +/////////////////////////////////////////////////// +// Dest function definitions +/////////////////////////////////////////////////// + +//Handles data from MarkovChannel class. +void MarkovOdeSolver::init( vector< double > initialState ) +{ + + nVars_ = initialState.size(); + state_ = initialState; + initialState_ = initialState; + Q_.resize( nVars_ ); + for ( unsigned int i = 0; i < nVars_; ++i ) + Q_[i].resize( nVars_, 0.0 ); + + stateOde_.resize( nVars_ ); + isInitialized_ = 1; + +#ifdef USE_GSL + assert( gslStepType_ != 0 ); + if ( gslStep_ ) + gsl_odeiv_step_free(gslStep_); + gslStep_ = gsl_odeiv_step_alloc( gslStepType_, nVars_ ); + assert( gslStep_ != 0 ); + if ( !gslEvolve_ ) + gslEvolve_ = gsl_odeiv_evolve_alloc(nVars_); + else + gsl_odeiv_evolve_reset(gslEvolve_); + assert(gslEvolve_ != 0); + if ( !gslControl_ ) + gslControl_ = gsl_odeiv_control_y_new( absAccuracy_, relAccuracy_ ); + else + gsl_odeiv_control_init(gslControl_,absAccuracy_, relAccuracy_, 1, 0); + assert(gslControl_!= 0); + gslSys_.function = &MarkovOdeSolver::evalSystem; + gslSys_.jacobian = 0; + gslSys_.dimension = nVars_; + gslSys_.params = static_cast< void * >( &Q_ ); +#endif /* ----- not USE_GSL ----- */ + +} + +////////////////////////// +//MsgDest functions. +///////////////////////// +void MarkovOdeSolver::process( const Eref& e, ProcPtr p ) +{ + double nextt = p->currTime + p->dt; + double t = p->currTime; + double sum = 0; + + for ( unsigned int i = 0; i < nVars_; ++i ) + stateOde_[i] = state_[i]; + + +#ifdef USE_GSL + while( t < nextt ) + { + int status = gsl_odeiv_evolve_apply ( gslEvolve_, gslControl_, gslStep_, &gslSys_, + &t, nextt, &internalStepSize_, &stateOde_[0] + ); + //Simple idea borrowed from Dieter Jaeger's implementation of a Markov + //channel to deal with potential round-off error. + sum = 0; + for ( unsigned int i = 0; i < nVars_; i++ ) + sum += stateOde_[i]; + + for ( unsigned int i = 0; i < nVars_; i++ ) + stateOde_[i] /= sum; + + if( status != GSL_SUCCESS ) + break; + } +#endif + +#if USE_BOOST_ODE + auto sys = [this](const vector& dy, vector& dydt, const double t) + { + this->OdeSystem(dy, dydt); + }; + + // It works well in practice for this setup. + if( method_ == "rk5" || method_ == "gsl" || method_ == "boost" ) + odeint::integrate( sys, stateOde_, t, nextt, p->dt ); + else if( method_ == "rk5a" || method_ == "adaptive" ) + odeint::integrate_adaptive( + odeint::make_controlled( absAccuracy_, relAccuracy_ ) + , sys, stateOde_, t, nextt, p->dt + ); + else if( method_ == "rk4" ) + odeint::integrate_const( rk4_stepper_type_() + , sys, stateOde_, t, nextt, p->dt + ); + else if ("rk54" == method_ ) + odeint::integrate_const( rk_karp_stepper_type_() + , sys, stateOde_, t, nextt, p->dt + ); + else if ("rkck" == method_ || "rkcka" == method_) + odeint::integrate_adaptive( + odeint::make_controlled( absAccuracy_, relAccuracy_ ) + , sys, stateOde_, t, nextt, p->dt + ); + else if( method_ == "rk8a" || "rk8" == method_ ) + odeint::integrate_adaptive( rk_felhberg_stepper_type_() + , sys, stateOde_, t, nextt, p->dt + ); + else + odeint::integrate( sys, stateOde_, t, nextt, p->dt ); +#endif /* ----- not USE_GSL ----- */ + + + for ( unsigned int i = 0; i < nVars_; ++i ) + state_[i] = stateOde_[i]; + + stateOut()->send( e, state_ ); +} + +void MarkovOdeSolver::reinit( const Eref& e, ProcPtr info ) +{ + state_ = initialState_; + if ( initialState_.empty() ) + { + cerr << "MarkovOdeSolver::reinit : " + "Initial state has not been set. Solver has not been initialized." + "Call init() before running.\n"; + } + stateOut()->send( e, state_ ); +} + +void MarkovOdeSolver::handleQ( vector< vector< double > > Q ) +{ + Q_ = Q; +} diff --git a/biophysics/MarkovOdeSolver.h b/biophysics/MarkovOdeSolver.h new file mode 100644 index 00000000..a12c1ea1 --- /dev/null +++ b/biophysics/MarkovOdeSolver.h @@ -0,0 +1,88 @@ +/********************************************************************** +** This program is part of 'MOOSE', the +** Messaging Object Oriented Simulation Environment. +** Copyright (C) 2003-2011 Upinder S. Bhalla. and NCBS +** It is made available under the terms of the +** GNU Lesser General Public License version 2.1 +** See the file COPYING.LIB for the full notice. +**********************************************************************/ + +#ifndef _MARKOVGSLSOLVER_H +#define _MARKOVGSLSOLVER_H + +//////////////////////////////////////////////////// +// Class : MarkovOdeSolver +// Author : Vishaka Datta S, 2011, NCBS. +// +// The GslIntegrator class in ksolve deals with a system whose coefficients stay +// constant. In the case of a Markov channel, the coefficients of the system +// vary with time. +// +// This makes it necessary for the system to keep track of changes in the system +// matrix, which is implemented by the message handler. +/////////////////////////////////////////////////// +// +#ifdef USE_GSL +#include +#include +#endif /* ----- not USE_GSL ----- */ + +class MarkovOdeSolver +{ +public: + MarkovOdeSolver(); + ~MarkovOdeSolver(); + +/////////////////////////////////////////////////// +// Field function definitions +/////////////////////////////////////////////////// + bool getIsInitialized() const; + string getMethod() const; + void setMethod( string method ); + double getRelativeAccuracy() const; + void setRelativeAccuracy( double value ); + double getAbsoluteAccuracy() const; + void setAbsoluteAccuracy( double value ); + double getInternalDt() const; + void setInternalDt( double value ); + +/////////////////////////////////////////////////// +// Dest function definitions +/////////////////////////////////////////////////// + + void process( const Eref& e, ProcPtr info ); + void reinit( const Eref& e, ProcPtr info ); + + void init( vector< double > ); + void handleQ( vector< vector< double > > ); + + static const Cinfo* initCinfo(); + +private: + bool isInitialized_; + string method_; + double absAccuracy_; + double relAccuracy_; + double internalStepSize_; + vector stateOde_; + + //The following four variables should be members of any solver class that + //will be implmented. + unsigned int nVars_; + vector< double > state_; + vector< double > initialState_; + vector< vector< double > > Q_; + +#ifdef USE_GSL + const gsl_odeiv_step_type* gslStepType_; + gsl_odeiv_step* gslStep_; + gsl_odeiv_control* gslControl_; + gsl_odeiv_evolve* gslEvolve_; + gsl_odeiv_system gslSys_; + static int evalSystem( double, const double*, double*, void* ); +#else /* ----- not USE_GSL ----- */ + // Using Boost + void OdeSystem( const vector& y, vector& dydt ); +#endif /* ----- not USE_GSL ----- */ +}; +#endif diff --git a/biophysics/MarkovSolver.cpp b/biophysics/MarkovSolver.cpp index 3f1a0e00..2d368010 100644 --- a/biophysics/MarkovSolver.cpp +++ b/biophysics/MarkovSolver.cpp @@ -7,7 +7,6 @@ ** See the file COPYING.LIB for the full notice. **********************************************************************/ -#include //Needed for DBL_MAX and DBL_MIN #include "../basecode/header.h" #include "MatrixOps.h" @@ -20,264 +19,264 @@ const Cinfo* MarkovSolver::initCinfo() { - ////////////////////// - //DestFinfos - ////////////////////// - - static DestFinfo process( "process", - "Handles process call", - new ProcOpFunc< MarkovSolver >( &MarkovSolver::process ) ); - - static DestFinfo reinit( "reinit", - "Handles reinit call", - new ProcOpFunc< MarkovSolver >( &MarkovSolver::reinit ) ); - - static Finfo* processShared[] = - { - &process, &reinit - }; - - static SharedFinfo proc( "proc", - "This is a shared message to receive Process message from the" - "scheduler. The first entry is a MsgDest for the Process " - "operation. It has a single argument, ProcInfo, which " - "holds lots of information about current time, thread, dt and" - "so on. The second entry is a MsgDest for the Reinit " - "operation. It also uses ProcInfo.", - processShared, sizeof( processShared ) / sizeof( Finfo* ) - ); - - - static Finfo* markovSolverFinfos[] = - { - &proc, //SharedFinfo - }; - - static Dinfo < MarkovSolver > dinfo; - static Cinfo markovSolverCinfo( - "MarkovSolver", - MarkovSolverBase::initCinfo(), - markovSolverFinfos, - sizeof( markovSolverFinfos ) / sizeof( Finfo* ), - &dinfo - ); - - return &markovSolverCinfo; + ////////////////////// + //DestFinfos + ////////////////////// + + static DestFinfo process( "process", + "Handles process call", + new ProcOpFunc< MarkovSolver >( &MarkovSolver::process ) ); + + static DestFinfo reinit( "reinit", + "Handles reinit call", + new ProcOpFunc< MarkovSolver >( &MarkovSolver::reinit ) ); + + static Finfo* processShared[] = + { + &process, &reinit + }; + + static SharedFinfo proc( "proc", + "This is a shared message to receive Process message from the" + "scheduler. The first entry is a MsgDest for the Process " + "operation. It has a single argument, ProcInfo, which " + "holds lots of information about current time, thread, dt and" + "so on. The second entry is a MsgDest for the Reinit " + "operation. It also uses ProcInfo.", + processShared, sizeof( processShared ) / sizeof( Finfo* ) + ); + + + static Finfo* markovSolverFinfos[] = + { + &proc, //SharedFinfo + }; + + static Dinfo < MarkovSolver > dinfo; + static Cinfo markovSolverCinfo( + "MarkovSolver", + MarkovSolverBase::initCinfo(), + markovSolverFinfos, + sizeof( markovSolverFinfos ) / sizeof( Finfo* ), + &dinfo + ); + + return &markovSolverCinfo; } static const Cinfo* markovSolverCinfo = MarkovSolver::initCinfo(); MarkovSolver::MarkovSolver() { - ; + ; } MarkovSolver::~MarkovSolver() { - ; + ; } Matrix* MarkovSolver::computePadeApproximant( Matrix* Q1, - unsigned int degreeIndex ) + unsigned int degreeIndex ) { - Matrix *expQ; - Matrix *U, *VplusU, *VminusU, *invVminusU, *Qpower; - vector< unsigned int >* swaps = new vector< unsigned int >; - unsigned int n = Q1->size(); - unsigned int degree = mCandidates[degreeIndex]; - double *padeCoeffs = NULL; - Matrix *V = matAlloc(n); - - //Vector of Matrix pointers. Each entry is an even power of Q. - vector< Matrix* > QevenPowers; - - //Selecting the right coefficient array. - switch (degree) - { - case 13: - padeCoeffs = b13; - break; - - case 9: - padeCoeffs = b9; - break; - - case 7: - padeCoeffs = b7; - break; - - case 5: - padeCoeffs = b5; - break; - - case 3: - padeCoeffs = b3; - break; - } - - - ///////// - //Q2 = Q^2 is computed for all degrees. - //Q4 = Q^4 = Q^2 * Q^2 is computed when degree = 5,7,9,13. - //Q6 = Q^6 = Q^4 * Q^2 is computed when degree = 7,9,13. - //Q8 = Q^8 = Q^4 * Q^4 is computed when degree = 7,9. - //Note that the formula for the 13th degree approximant used here - //is different from the one used for smaller degrees. - //////// - switch( degree ) - { - case 3 : - case 5 : - case 7 : - case 9 : - U = matAlloc( n ); - - QevenPowers.push_back( Q1 ); - - for( unsigned int i = 1; i < (degree + 1)/2 ; ++i ) - { - Qpower = QevenPowers.back(); - QevenPowers.push_back( matMatMul( Qpower, Qpower ) ); - } - - //Computation of U. - for ( int i = degree; i > 1; i -= 2 ) - matMatAdd( U, QevenPowers[i/2], 1.0, padeCoeffs[i], FIRST ); - - //Adding b0 * I . - matEyeAdd( U, padeCoeffs[1], 0 ); - matMatMul( Q1, U, SECOND ); - - //Computation of V. - for ( int i = degree - 1; i > 0; i -= 2 ) - matMatAdd( V, QevenPowers[i/2], 1.0, padeCoeffs[i], FIRST ); - - //Adding b1 * I - matEyeAdd( V, padeCoeffs[0], DUMMY ); - - while (!QevenPowers.empty()) - { - delete QevenPowers.back(); - QevenPowers.pop_back(); - } - break; - - case 13: - Matrix *Q2, *Q4, *Q6; - Matrix *temp; - - Q2 = matMatMul( Q1, Q1 ); - Q4 = matMatMul( Q2, Q2 ); - Q6 = matMatMul( Q4, Q2 ); - - //Long and rather messy expression for U and V. - //Refer paper mentioned in header for more details. - //Storing the result in temporaries is a better idea as it gives us - //control on how many temporaries are being created and also to - //help in memory deallocation. - - //Computation of U. - temp = matScalShift( Q6, b13[13], 0.0 ); - matMatAdd( temp, Q4, 1.0, b13[11], FIRST ); - matMatAdd( temp, Q2, 1.0, b13[9], FIRST ); - - matMatMul( Q6, temp, SECOND ); - - matMatAdd( temp, Q6, 1.0, b13[7], FIRST ); - matMatAdd( temp, Q4, 1.0, b13[5], FIRST ); - matMatAdd( temp, Q2, 1.0, b13[3], FIRST ); - matEyeAdd( temp, b13[1], DUMMY ); - U = matMatMul( Q1, temp ); - delete temp; - - //Computation of V - temp = matScalShift( Q6, b13[12], 0.0 ); - matMatAdd( temp, Q4, 1.0, b13[10], FIRST ); - matMatAdd( temp, Q2, 1.0, b13[8], FIRST ); - matMatMul( Q6, temp, SECOND ); - matMatAdd( temp, Q6, 1.0, b13[6], FIRST ); - matMatAdd( temp, Q4, 1.0, b13[4], FIRST ); - matMatAdd( temp, Q2, 1.0, b13[2], FIRST ); - delete( V ); - V = matEyeAdd( temp, b13[0] ); - delete temp; - - delete Q2; - delete Q4; - delete Q6; - break; - } - - VplusU = matMatAdd( U, V, 1.0, 1.0 ); - VminusU = matMatAdd( U, V, -1.0, 1.0 ); - - invVminusU = matAlloc( n ); - matInv( VminusU, swaps, invVminusU ); - expQ = matMatMul( invVminusU, VplusU ); - - - //Memory cleanup. - delete U; - delete V; - delete VplusU; - delete VminusU; - delete invVminusU; - delete swaps; - - return expQ; + Matrix *expQ; + Matrix *U, *VplusU, *VminusU, *invVminusU, *Qpower; + vector< unsigned int >* swaps = new vector< unsigned int >; + unsigned int n = Q1->size(); + unsigned int degree = mCandidates[degreeIndex]; + double *padeCoeffs = NULL; + Matrix *V = matAlloc(n); + + //Vector of Matrix pointers. Each entry is an even power of Q. + vector< Matrix* > QevenPowers; + + //Selecting the right coefficient array. + switch (degree) + { + case 13: + padeCoeffs = b13; + break; + + case 9: + padeCoeffs = b9; + break; + + case 7: + padeCoeffs = b7; + break; + + case 5: + padeCoeffs = b5; + break; + + case 3: + padeCoeffs = b3; + break; + } + + + ///////// + //Q2 = Q^2 is computed for all degrees. + //Q4 = Q^4 = Q^2 * Q^2 is computed when degree = 5,7,9,13. + //Q6 = Q^6 = Q^4 * Q^2 is computed when degree = 7,9,13. + //Q8 = Q^8 = Q^4 * Q^4 is computed when degree = 7,9. + //Note that the formula for the 13th degree approximant used here + //is different from the one used for smaller degrees. + //////// + switch( degree ) + { + case 3 : + case 5 : + case 7 : + case 9 : + U = matAlloc( n ); + + QevenPowers.push_back( Q1 ); + + for( unsigned int i = 1; i < (degree + 1)/2 ; ++i ) + { + Qpower = QevenPowers.back(); + QevenPowers.push_back( matMatMul( Qpower, Qpower ) ); + } + + //Computation of U. + for ( int i = degree; i > 1; i -= 2 ) + matMatAdd( U, QevenPowers[i/2], 1.0, padeCoeffs[i], FIRST ); + + //Adding b0 * I . + matEyeAdd( U, padeCoeffs[1], 0 ); + matMatMul( Q1, U, SECOND ); + + //Computation of V. + for ( int i = degree - 1; i > 0; i -= 2 ) + matMatAdd( V, QevenPowers[i/2], 1.0, padeCoeffs[i], FIRST ); + + //Adding b1 * I + matEyeAdd( V, padeCoeffs[0], DUMMY ); + + while (!QevenPowers.empty()) + { + delete QevenPowers.back(); + QevenPowers.pop_back(); + } + break; + + case 13: + Matrix *Q2, *Q4, *Q6; + Matrix *temp; + + Q2 = matMatMul( Q1, Q1 ); + Q4 = matMatMul( Q2, Q2 ); + Q6 = matMatMul( Q4, Q2 ); + + //Long and rather messy expression for U and V. + //Refer paper mentioned in header for more details. + //Storing the result in temporaries is a better idea as it gives us + //control on how many temporaries are being created and also to + //help in memory deallocation. + + //Computation of U. + temp = matScalShift( Q6, b13[13], 0.0 ); + matMatAdd( temp, Q4, 1.0, b13[11], FIRST ); + matMatAdd( temp, Q2, 1.0, b13[9], FIRST ); + + matMatMul( Q6, temp, SECOND ); + + matMatAdd( temp, Q6, 1.0, b13[7], FIRST ); + matMatAdd( temp, Q4, 1.0, b13[5], FIRST ); + matMatAdd( temp, Q2, 1.0, b13[3], FIRST ); + matEyeAdd( temp, b13[1], DUMMY ); + U = matMatMul( Q1, temp ); + delete temp; + + //Computation of V + temp = matScalShift( Q6, b13[12], 0.0 ); + matMatAdd( temp, Q4, 1.0, b13[10], FIRST ); + matMatAdd( temp, Q2, 1.0, b13[8], FIRST ); + matMatMul( Q6, temp, SECOND ); + matMatAdd( temp, Q6, 1.0, b13[6], FIRST ); + matMatAdd( temp, Q4, 1.0, b13[4], FIRST ); + matMatAdd( temp, Q2, 1.0, b13[2], FIRST ); + delete( V ); + V = matEyeAdd( temp, b13[0] ); + delete temp; + + delete Q2; + delete Q4; + delete Q6; + break; + } + + VplusU = matMatAdd( U, V, 1.0, 1.0 ); + VminusU = matMatAdd( U, V, -1.0, 1.0 ); + + invVminusU = matAlloc( n ); + matInv( VminusU, swaps, invVminusU ); + expQ = matMatMul( invVminusU, VplusU ); + + + //Memory cleanup. + delete U; + delete V; + delete VplusU; + delete VminusU; + delete invVminusU; + delete swaps; + + return expQ; } Matrix* MarkovSolver::computeMatrixExponential() { - double mu, norm; - unsigned int n = Q_->size(); - Matrix *expQ, *Q1; - - mu = matTrace( Q_ )/n; - - //Q1 <- Q - mu*I - //This reduces the norm of the matrix. The idea is that a lower - //order approximant will suffice if the norm is smaller. - Q1 = matEyeAdd( Q_, -mu ); - - //We cycle through the first four candidate values of m. The moment the norm - //satisfies the theta_M bound, we choose that m and compute the Pade' - //approximant to the exponential. We can then directly return the exponential. - norm = matColNorm( Q1 ); - for ( unsigned int i = 0; i < 4; ++i ) - { - if ( norm < thetaM[i] ) - { - expQ = computePadeApproximant( Q1, i ); - matScalShift( expQ, exp( mu ), 0, DUMMY ); - return expQ; - } - } - - //In case none of the candidates were satisfactory, we scale down the norm - //by dividing A by 2^s until ||A|| < 1. We then use a 13th degree - //Pade approximant. - double sf = ceil( log( norm / thetaM[4] ) / log( (double)2 ) ); - unsigned int s = 0; - - if ( sf > 0 ) - { - s = static_cast< unsigned int >( sf ); - matScalShift( Q1, 1.0/(2 << (s - 1)), 0, DUMMY ); - } - expQ = computePadeApproximant( Q1, 4 ); - - //Upto this point, the matrix stored in expQ is r13, the 13th degree - //Pade approximant corresponding to A/2^s, not A. - //Now we repeatedly square r13 's' times to get the exponential - //of A. - for ( unsigned int i = 0; i < s; ++i ) - matMatMul( expQ, expQ, FIRST ); - - matScalShift( expQ, exp( mu ), 0, DUMMY ); - - delete Q1; - return expQ; + double mu, norm; + unsigned int n = Q_->size(); + Matrix *expQ, *Q1; + + mu = matTrace( Q_ )/n; + + //Q1 <- Q - mu*I + //This reduces the norm of the matrix. The idea is that a lower + //order approximant will suffice if the norm is smaller. + Q1 = matEyeAdd( Q_, -mu ); + + //We cycle through the first four candidate values of m. The moment the norm + //satisfies the theta_M bound, we choose that m and compute the Pade' + //approximant to the exponential. We can then directly return the exponential. + norm = matColNorm( Q1 ); + for ( unsigned int i = 0; i < 4; ++i ) + { + if ( norm < thetaM[i] ) + { + expQ = computePadeApproximant( Q1, i ); + matScalShift( expQ, exp( mu ), 0, DUMMY ); + return expQ; + } + } + + //In case none of the candidates were satisfactory, we scale down the norm + //by dividing A by 2^s until ||A|| < 1. We then use a 13th degree + //Pade approximant. + double sf = ceil( log( norm / thetaM[4] ) / log( (double)2 ) ); + unsigned int s = 0; + + if ( sf > 0 ) + { + s = static_cast< unsigned int >( sf ); + matScalShift( Q1, 1.0/(2 << (s - 1)), 0, DUMMY ); + } + expQ = computePadeApproximant( Q1, 4 ); + + //Upto this point, the matrix stored in expQ is r13, the 13th degree + //Pade approximant corresponding to A/2^s, not A. + //Now we repeatedly square r13 's' times to get the exponential + //of A. + for ( unsigned int i = 0; i < s; ++i ) + matMatMul( expQ, expQ, FIRST ); + + matScalShift( expQ, exp( mu ), 0, DUMMY ); + + delete Q1; + return expQ; } /////////////// @@ -285,22 +284,22 @@ Matrix* MarkovSolver::computeMatrixExponential() ////////////// void MarkovSolver::reinit( const Eref& e, ProcPtr p ) { - MarkovSolverBase::reinit( e, p ); + MarkovSolverBase::reinit( e, p ); } void MarkovSolver::process( const Eref& e, ProcPtr p ) { - MarkovSolverBase::process( e, p ); + MarkovSolverBase::process( e, p ); } #ifdef DO_UNIT_TESTS void assignMat( Matrix* A, double testMat[3][3] ) { - for ( unsigned int i = 0; i < 3; ++i ) - { - for ( unsigned int j = 0; j < 3; ++j ) - (*A)[i][j] = testMat[i][j]; - } + for ( unsigned int i = 0; i < 3; ++i ) + { + for ( unsigned int j = 0; j < 3; ++j ) + (*A)[i][j] = testMat[i][j]; + } } #if 0 @@ -308,219 +307,227 @@ void assignMat( Matrix* A, double testMat[3][3] ) //we test out all degrees of the Pade approximant. void testMarkovSolver() { - MarkovSolver solver; - - Matrix *expQ; - - solver.Q_ = matAlloc( 3 ); - - double testMats[5][3][3] = { - { //Will require 3rd degree Pade approximant. - { 0.003859554140797, 0.003828667792972, 0.000567545354509 }, - { 0.000630452326710, 0.001941502594891, 0.001687045130505 }, - { 0.003882371127042, 0.003201121875555, 0.003662942100756 } - }, - { //Will require 5th degree Pade approximant. - { 0.009032772098686, 0.000447799046538, 0.009951718245937 }, - { 0.004122293240791, 0.005703676675533, 0.010337598714782 }, - { 0.012352886634899, 0.004960259942209, 0.002429343859207 } - }, - { //Will require 7th degree Pade approximant. - { 0.249033679156721, 0.026663192545146, 0.193727616177876 }, - { 0.019543882188296, 0.240474520213763, 0.204325805163358 }, - { 0.110669567443862, 0.001158556033517, 0.217173676340877 } - }, - { //Will require 9th degree Pade approximant. - { 0.708590392291234, 0.253289557366033, 0.083402066470341 }, - { 0.368148069351060, 0.675040384813246, 0.585189051240853 }, - { 0.366939478800014, 0.276935085840161, 0.292304127720940 }, - }, - { //Will require 13th degree Pade approximant., - { 5.723393958255834, 2.650265678621879, 2.455089725038183 }, - { 5.563819918184171, 5.681063207977340, 6.573010933999208 }, - { 4.510226911355842, 3.729779121596184, 6.131599680450886 } - } - }; - - double correctExps[5][3][3] = { - { - { 1.003869332885896, 0.003840707339656, 0.000572924780299 }, - { 0.000635569997632, 1.001947309951925, 0.001691961742250 }, - { 0.003898019965821, 0.003217566115560, 1.003673477658833 } - }, - { - { 1.009136553319587, 0.000475947724581, 0.010011555682222 }, - { 0.004217120071231, 1.005746704105642, 0.010400661735110 }, - { 0.012434554824033, 0.004983402186283, 1.002519822649746 } - }, - { - { 1.296879503336410, 0.034325768324765, 0.248960074106229 }, - { 0.039392602584525, 1.272463533413523, 0.260228538022164 }, - { 0.140263068698347, 0.003332731847933, 1.256323839764616 } - }, - { - { 2.174221102665550, 0.550846463313377, 0.279203836454105 }, - { 0.963674962388503, 2.222317715620410, 1.033020817699738 }, - { 0.733257221615105, 0.559435366776953, 1.508376826849517 } - }, - { - { 3.274163243250245e5, 2.405867301580962e5, 3.034390382218154e5 }, - { 5.886803379935408e5, 4.325844111569120e5, 5.456065763194024e5 }, - { 4.671930521670584e5, 3.433084310645007e5, 4.330101744194682e5 } - } - }; - - double correctColumnNorms[5] = { - 1.009005583407142, - 1.025788228214852, - 1.765512451893010, - 3.871153286669158, - 1.383289714485624e+06 - }; - - for ( unsigned int i = 0; i < 5; ++i ) - { - assignMat( solver.Q_, testMats[i] ); - expQ = solver.computeMatrixExponential(); - assert( doubleEq( matColNorm( expQ ), correctColumnNorms[i] ) ); - - //Comparing termwise just to be doubly sure. - for( unsigned int j = 0; j < 3; ++j ) - { - for( unsigned int k = 0; k < 3; ++k ) - assert( doubleEq( (*expQ)[j][k], correctExps[i][j][k] ) ); - } - - delete expQ; - } - - ///////////////// - //Testing state space interpolation. - //////////////// - const Cinfo* rateTableCinfo = MarkovRateTable::initCinfo(); - const Cinfo* interpol2dCinfo = Interpol2D::initCinfo(); - const Cinfo* vectorTableCinfo = VectorTable::initCinfo(); - const Cinfo* markovSolverCinfo = MarkovSolver::initCinfo(); - - vector< DimInfo > single; - - Id rateTable2dId = Id::nextId(); - Id rateTable1dId = Id::nextId(); - Id int2dId = Id::nextId(); - Id vecTableId = Id::nextId(); - Id solver2dId = Id::nextId(); - Id solver1dId = Id::nextId(); - - ObjId eRateTable2d = Element( rateTable2dId, rateTableCinfo, - "rateTable2d", single, 1, true ); - Element *eRateTable1d = new Element( rateTable1dId, rateTableCinfo, - "rateTable1d", single, 1, true ); - Element *eInt2d = new Element( int2dId, interpol2dCinfo, "int2d", single, 1 ); - Element *eVecTable = new Element( vecTableId, vectorTableCinfo, "vecTable", - single, 1, true ); - Element *eSolver2d = new Element( solver2dId, markovSolverCinfo, - "solver2d", single, 1, true ); - Element *eSolver1d = new Element( solver1dId, markovSolverCinfo, - "solver1d", single, 1, true ); - - Eref rateTable2dEref( eRateTable2d, 0 ); - Eref rateTable1dEref( eRateTable1d, 0 ); - Eref int2dEref( eInt2d, 0 ); - Eref vecTableEref( eVecTable, 0 ); - Eref solver2dEref( eSolver2d, 0 ); - Eref solver1dEref( eSolver1d, 0 ); - - vector< double > table1d; - vector< vector< double > > table2d; - double v, conc; - - MarkovRateTable* rateTable2d = reinterpret_cast< MarkovRateTable* > - ( rateTable2dEref.data() ); - MarkovRateTable* rateTable1d = reinterpret_cast< MarkovRateTable* > - ( rateTable1dEref.data() ); - VectorTable* vecTable = reinterpret_cast< VectorTable* > - ( vecTableEref.data() ); - Interpol2D* int2d = reinterpret_cast< Interpol2D* > - ( int2dEref.data() ); - MarkovSolver* markovSolver2d = reinterpret_cast< MarkovSolver* > - ( solver2dEref.data() ); - MarkovSolver* markovSolver1d = reinterpret_cast< MarkovSolver* > - ( solver1dEref.data() ); - - rateTable2d->init( 3 ); - rateTable1d->init( 3 ); - - vecTable->setMin( -0.10 ); - vecTable->setMax( 0.10 ); - vecTable->setDiv( 200 ); - - v = vecTable->getMin(); - for ( unsigned int i = 0; i < 201; ++i ) - { - table1d.push_back( 1e3 * exp( 9 * v - 0.45 ) ); - v += 0.001; - } - - vecTable->setTable( table1d ); - - rateTable2d->setVtChildTable( 1, 3, vecTableId, 0 ); - rateTable1d->setVtChildTable( 1, 3, vecTableId, 0 ); - - int2d->setXmin( -0.10 ); - int2d->setXmax( 0.10 ); - int2d->setYmin( 0 ); - int2d->setYmax( 50e-6 ); - - v = int2d->getXmin(); - table2d.resize( 201 ); - for ( unsigned int i = 0; i < 201; ++i ) - { - conc = int2d->getYmin(); - for ( unsigned int j = 0; j < 50; ++j ) - { - table2d[i].push_back( 1e3 * conc * exp( -45 * v + 0.65 ) ); - conc += 1e-6; - } - v += 0.001; - } - - int2d->setTableVector( table2d ); - - rateTable2d->setInt2dChildTable( 2, 3, int2dId ); - - rateTable2d->setConstantRate( 3, 1, 0.652 ); - rateTable2d->setConstantRate( 2, 1, 1.541 ); - - rateTable1d->setConstantRate( 3, 1, 0.652 ); - rateTable1d->setConstantRate( 2, 1, 1.541 ); - - markovSolver2d->init( rateTable2dId, 0.1 ); - markovSolver1d->init( rateTable1dId, 0.1 ); - - markovSolver2d->setVm( 0.0533 ); - markovSolver2d->setLigandConc( 3.41e-6 ); - - markovSolver1d->setVm( 0.0533 ); - - Vector initState; - - initState.push_back( 0.2 ); - initState.push_back( 0.4 ); - initState.push_back( 0.4 ); - - markovSolver2d->setInitialState( initState ); - markovSolver2d->computeState(); - - Vector interpState = markovSolver2d->getState(); - - rateTable2dId.destroy(); - rateTable1dId.destroy(); - int2dId.destroy(); - vecTableId.destroy(); - solver2dId.destroy(); - solver1dId.destroy(); - - cout << "." << flush; + MarkovSolver solver; + + Matrix *expQ; + + solver.Q_ = matAlloc( 3 ); + + double testMats[5][3][3] = + { + { + //Will require 3rd degree Pade approximant. + { 0.003859554140797, 0.003828667792972, 0.000567545354509 }, + { 0.000630452326710, 0.001941502594891, 0.001687045130505 }, + { 0.003882371127042, 0.003201121875555, 0.003662942100756 } + }, + { + //Will require 5th degree Pade approximant. + { 0.009032772098686, 0.000447799046538, 0.009951718245937 }, + { 0.004122293240791, 0.005703676675533, 0.010337598714782 }, + { 0.012352886634899, 0.004960259942209, 0.002429343859207 } + }, + { + //Will require 7th degree Pade approximant. + { 0.249033679156721, 0.026663192545146, 0.193727616177876 }, + { 0.019543882188296, 0.240474520213763, 0.204325805163358 }, + { 0.110669567443862, 0.001158556033517, 0.217173676340877 } + }, + { + //Will require 9th degree Pade approximant. + { 0.708590392291234, 0.253289557366033, 0.083402066470341 }, + { 0.368148069351060, 0.675040384813246, 0.585189051240853 }, + { 0.366939478800014, 0.276935085840161, 0.292304127720940 }, + }, + { + //Will require 13th degree Pade approximant., + { 5.723393958255834, 2.650265678621879, 2.455089725038183 }, + { 5.563819918184171, 5.681063207977340, 6.573010933999208 }, + { 4.510226911355842, 3.729779121596184, 6.131599680450886 } + } + }; + + double correctExps[5][3][3] = + { + { + { 1.003869332885896, 0.003840707339656, 0.000572924780299 }, + { 0.000635569997632, 1.001947309951925, 0.001691961742250 }, + { 0.003898019965821, 0.003217566115560, 1.003673477658833 } + }, + { + { 1.009136553319587, 0.000475947724581, 0.010011555682222 }, + { 0.004217120071231, 1.005746704105642, 0.010400661735110 }, + { 0.012434554824033, 0.004983402186283, 1.002519822649746 } + }, + { + { 1.296879503336410, 0.034325768324765, 0.248960074106229 }, + { 0.039392602584525, 1.272463533413523, 0.260228538022164 }, + { 0.140263068698347, 0.003332731847933, 1.256323839764616 } + }, + { + { 2.174221102665550, 0.550846463313377, 0.279203836454105 }, + { 0.963674962388503, 2.222317715620410, 1.033020817699738 }, + { 0.733257221615105, 0.559435366776953, 1.508376826849517 } + }, + { + { 3.274163243250245e5, 2.405867301580962e5, 3.034390382218154e5 }, + { 5.886803379935408e5, 4.325844111569120e5, 5.456065763194024e5 }, + { 4.671930521670584e5, 3.433084310645007e5, 4.330101744194682e5 } + } + }; + + double correctColumnNorms[5] = + { + 1.009005583407142, + 1.025788228214852, + 1.765512451893010, + 3.871153286669158, + 1.383289714485624e+06 + }; + + for ( unsigned int i = 0; i < 5; ++i ) + { + assignMat( solver.Q_, testMats[i] ); + expQ = solver.computeMatrixExponential(); + assert( doubleEq( matColNorm( expQ ), correctColumnNorms[i] ) ); + + //Comparing termwise just to be doubly sure. + for( unsigned int j = 0; j < 3; ++j ) + { + for( unsigned int k = 0; k < 3; ++k ) + assert( doubleEq( (*expQ)[j][k], correctExps[i][j][k] ) ); + } + + delete expQ; + } + + ///////////////// + //Testing state space interpolation. + //////////////// + const Cinfo* rateTableCinfo = MarkovRateTable::initCinfo(); + const Cinfo* interpol2dCinfo = Interpol2D::initCinfo(); + const Cinfo* vectorTableCinfo = VectorTable::initCinfo(); + const Cinfo* markovSolverCinfo = MarkovSolver::initCinfo(); + + vector< DimInfo > single; + + Id rateTable2dId = Id::nextId(); + Id rateTable1dId = Id::nextId(); + Id int2dId = Id::nextId(); + Id vecTableId = Id::nextId(); + Id solver2dId = Id::nextId(); + Id solver1dId = Id::nextId(); + + ObjId eRateTable2d = Element( rateTable2dId, rateTableCinfo, + "rateTable2d", single, 1, true ); + Element *eRateTable1d = new Element( rateTable1dId, rateTableCinfo, + "rateTable1d", single, 1, true ); + Element *eInt2d = new Element( int2dId, interpol2dCinfo, "int2d", single, 1 ); + Element *eVecTable = new Element( vecTableId, vectorTableCinfo, "vecTable", + single, 1, true ); + Element *eSolver2d = new Element( solver2dId, markovSolverCinfo, + "solver2d", single, 1, true ); + Element *eSolver1d = new Element( solver1dId, markovSolverCinfo, + "solver1d", single, 1, true ); + + Eref rateTable2dEref( eRateTable2d, 0 ); + Eref rateTable1dEref( eRateTable1d, 0 ); + Eref int2dEref( eInt2d, 0 ); + Eref vecTableEref( eVecTable, 0 ); + Eref solver2dEref( eSolver2d, 0 ); + Eref solver1dEref( eSolver1d, 0 ); + + vector< double > table1d; + vector< vector< double > > table2d; + double v, conc; + + MarkovRateTable* rateTable2d = reinterpret_cast< MarkovRateTable* > + ( rateTable2dEref.data() ); + MarkovRateTable* rateTable1d = reinterpret_cast< MarkovRateTable* > + ( rateTable1dEref.data() ); + VectorTable* vecTable = reinterpret_cast< VectorTable* > + ( vecTableEref.data() ); + Interpol2D* int2d = reinterpret_cast< Interpol2D* > + ( int2dEref.data() ); + MarkovSolver* markovSolver2d = reinterpret_cast< MarkovSolver* > + ( solver2dEref.data() ); + MarkovSolver* markovSolver1d = reinterpret_cast< MarkovSolver* > + ( solver1dEref.data() ); + + rateTable2d->init( 3 ); + rateTable1d->init( 3 ); + + vecTable->setMin( -0.10 ); + vecTable->setMax( 0.10 ); + vecTable->setDiv( 200 ); + + v = vecTable->getMin(); + for ( unsigned int i = 0; i < 201; ++i ) + { + table1d.push_back( 1e3 * exp( 9 * v - 0.45 ) ); + v += 0.001; + } + + vecTable->setTable( table1d ); + + rateTable2d->setVtChildTable( 1, 3, vecTableId, 0 ); + rateTable1d->setVtChildTable( 1, 3, vecTableId, 0 ); + + int2d->setXmin( -0.10 ); + int2d->setXmax( 0.10 ); + int2d->setYmin( 0 ); + int2d->setYmax( 50e-6 ); + + v = int2d->getXmin(); + table2d.resize( 201 ); + for ( unsigned int i = 0; i < 201; ++i ) + { + conc = int2d->getYmin(); + for ( unsigned int j = 0; j < 50; ++j ) + { + table2d[i].push_back( 1e3 * conc * exp( -45 * v + 0.65 ) ); + conc += 1e-6; + } + v += 0.001; + } + + int2d->setTableVector( table2d ); + + rateTable2d->setInt2dChildTable( 2, 3, int2dId ); + + rateTable2d->setConstantRate( 3, 1, 0.652 ); + rateTable2d->setConstantRate( 2, 1, 1.541 ); + + rateTable1d->setConstantRate( 3, 1, 0.652 ); + rateTable1d->setConstantRate( 2, 1, 1.541 ); + + markovSolver2d->init( rateTable2dId, 0.1 ); + markovSolver1d->init( rateTable1dId, 0.1 ); + + markovSolver2d->setVm( 0.0533 ); + markovSolver2d->setLigandConc( 3.41e-6 ); + + markovSolver1d->setVm( 0.0533 ); + + Vector initState; + + initState.push_back( 0.2 ); + initState.push_back( 0.4 ); + initState.push_back( 0.4 ); + + markovSolver2d->setInitialState( initState ); + markovSolver2d->computeState(); + + Vector interpState = markovSolver2d->getState(); + + rateTable2dId.destroy(); + rateTable1dId.destroy(); + int2dId.destroy(); + vecTableId.destroy(); + solver2dId.destroy(); + solver1dId.destroy(); + + cout << "." << flush; } #endif // #if 0 diff --git a/biophysics/Neuron.cpp b/biophysics/Neuron.cpp index fc72bf01..29c74c52 100644 --- a/biophysics/Neuron.cpp +++ b/biophysics/Neuron.cpp @@ -21,11 +21,11 @@ #include "../builtins/MooseParser.h" -class nuParser: public MooseParser +class nuParser: public moose::MooseParser { public: nuParser( const string& expr ): - MooseParser(), + moose::MooseParser(), p(0.0), // geometrical path distance wound through dendrite g(0.0), // geometrical path distance direct from soma. L(0.0), // electrical distance arg @@ -40,21 +40,23 @@ class nuParser: public MooseParser oldVal(0.0), // Original value of field, if needed. useOldVal( false ) // is the 'orig' field needed? { - DefineVar( "p", &p ); - DefineVar( "g", &g ); - DefineVar( "L", &L ); - DefineVar( "len", &len ); - DefineVar( "dia", &dia ); - DefineVar( "maxP", &maxP ); - DefineVar( "maxG", &maxG ); - DefineVar( "maxL", &maxL ); - DefineVar( "x", &x ); - DefineVar( "y", &y ); - DefineVar( "z", &z ); + DefineVar( "p", &p ); + DefineVar( "g", &g ); + DefineVar( "L", &L ); + DefineVar( "len", &len ); + DefineVar( "dia", &dia ); + DefineVar( "maxP", &maxP ); + DefineVar( "maxG", &maxG ); + DefineVar( "maxL", &maxL ); + DefineVar( "x", &x ); + DefineVar( "y", &y ); + DefineVar( "z", &z ); DefineVar( "oldVal", &oldVal ); - DefineFun( "H", nuParser::H ); + DefineFun1( "H", nuParser::H ); + if ( expr.find( "oldVal" ) != string::npos ) useOldVal = true; + SetExpr( expr ); } @@ -109,40 +111,40 @@ const Cinfo* Neuron::initCinfo() // ValueFinfos ///////////////////////////////////////////////////////////////////// static ValueFinfo< Neuron, double > RM( "RM", - "Membrane resistivity, in ohm.m^2. Default value is 1.0.", - &Neuron::setRM, - &Neuron::getRM - ); + "Membrane resistivity, in ohm.m^2. Default value is 1.0.", + &Neuron::setRM, + &Neuron::getRM + ); static ValueFinfo< Neuron, double > RA( "RA", - "Axial resistivity of cytoplasm, in ohm.m. Default value is 1.0.", - &Neuron::setRA, - &Neuron::getRA - ); + "Axial resistivity of cytoplasm, in ohm.m. Default value is 1.0.", + &Neuron::setRA, + &Neuron::getRA + ); static ValueFinfo< Neuron, double > CM( "CM", - "Membrane Capacitance, in F/m^2. Default value is 0.01", - &Neuron::setCM, - &Neuron::getCM - ); + "Membrane Capacitance, in F/m^2. Default value is 0.01", + &Neuron::setCM, + &Neuron::getCM + ); static ValueFinfo< Neuron, double > Em( "Em", - "Resting membrane potential of compartments, in Volts. " - "Default value is -0.065.", - &Neuron::setEm, - &Neuron::getEm - ); + "Resting membrane potential of compartments, in Volts. " + "Default value is -0.065.", + &Neuron::setEm, + &Neuron::getEm + ); static ValueFinfo< Neuron, double > theta( "theta", "Angle to rotate cell geometry, around long axis of neuron. " "Think Longitude. Units are radians. " "Default value is zero, which means no rotation. ", &Neuron::setTheta, &Neuron::getTheta - ); + ); static ValueFinfo< Neuron, double > phi( "phi", "Angle to rotate cell geometry, around elevation of neuron. " "Think Latitude. Units are radians. " "Default value is zero, which means no rotation. ", &Neuron::setPhi, &Neuron::getPhi - ); + ); static ValueFinfo< Neuron, string > sourceFile( "sourceFile", "Name of source file from which to load a model. " @@ -151,317 +153,317 @@ const Cinfo* Neuron::initCinfo() "definitions should have been loaded into /library. ", &Neuron::setSourceFile, &Neuron::getSourceFile - ); + ); static ValueFinfo< Neuron, double > compartmentLengthInLambdas( - "compartmentLengthInLambdas", - "Units: meters (SI). \n" - "Electrotonic length to use for the largest compartment in the " - "model. Used to define subdivision of branches into compartments. " - "For example, if we set *compartmentLengthInLambdas* to 0.1, " - "and *lambda* (electrotonic length) is 250 microns, then it " - "sets the compartment length to 25 microns. Thus a dendritic " - "branch of 500 microns is subdivided into 20 commpartments. " - "If the branch is shorter than *compartmentLengthInLambdas*, " - "then it is not subdivided. " - "If *compartmentLengthInLambdas* is set to 0 then the original " - "compartmental structure of the model is preserved. " - " Note that this routine does NOT merge branches, even if " - "*compartmentLengthInLambdas* is bigger than the branch. " - "While all this subdivision is being done, the Neuron class " - "preserves as detailed a geometry as it can, so it can rebuild " - "the more detailed version if needed. " - "Default value of *compartmentLengthInLambdas* is 0. ", - &Neuron::setCompartmentLengthInLambdas, - &Neuron::getCompartmentLengthInLambdas - ); + "compartmentLengthInLambdas", + "Units: meters (SI). \n" + "Electrotonic length to use for the largest compartment in the " + "model. Used to define subdivision of branches into compartments. " + "For example, if we set *compartmentLengthInLambdas* to 0.1, " + "and *lambda* (electrotonic length) is 250 microns, then it " + "sets the compartment length to 25 microns. Thus a dendritic " + "branch of 500 microns is subdivided into 20 commpartments. " + "If the branch is shorter than *compartmentLengthInLambdas*, " + "then it is not subdivided. " + "If *compartmentLengthInLambdas* is set to 0 then the original " + "compartmental structure of the model is preserved. " + " Note that this routine does NOT merge branches, even if " + "*compartmentLengthInLambdas* is bigger than the branch. " + "While all this subdivision is being done, the Neuron class " + "preserves as detailed a geometry as it can, so it can rebuild " + "the more detailed version if needed. " + "Default value of *compartmentLengthInLambdas* is 0. ", + &Neuron::setCompartmentLengthInLambdas, + &Neuron::getCompartmentLengthInLambdas + ); static ElementValueFinfo< Neuron, vector< string > > - channelDistribution( - "channelDistribution", - "Specification for distribution of channels, CaConcens and " - "any other model components that are defined as prototypes and " - "have to be placed on the electrical compartments.\n" - "Arguments: proto path field expr [field expr]...\n" - " Each entry is terminated with an empty string. " - "The prototype is any object created in */library*, " - "If a channel matching the prototype name already exists, then " - "all subsequent operations are applied to the extant channel and " - "a new one is not created. " - "The paired arguments are as follows: \n" - "The *field* argument specifies the name of the parameter " - "that is to be assigned by the expression.\n" - "The *expression* argument is a mathematical expression in " - "the muparser framework, which permits most operations including " - "trig and transcendental ones. Of course it also handles simple " - "numerical values like 1.0, 1e-10 and so on. " - "Available arguments for muParser are:\n" - " p, g, L, len, dia, maxP, maxG, maxL \n" - " p: path distance from soma, measured along dendrite, in metres.\n" - " g: geometrical distance from soma, in metres.\n" - " L: electrotonic distance (# of lambdas) from soma, along dend. No units.\n" - " len: length of compartment, in metres.\n" - " dia: for diameter of compartment, in metres.\n" - " maxP: Maximum value of *p* for this neuron. \n" - " maxG: Maximum value of *g* for this neuron. \n" - " maxL: Maximum value of *L* for this neuron.\n" - "The expression for the first field must evaluate to > 0 " - "for the channel to be installed. For example, for " - "channels, if Field == Gbar, and func( r, L, len, dia) < 0, \n" - "then the channel is not installed. This feature is typically " - "used with the sign() or Heaviside H() function to limit range: " - "for example: H(1 - L) will only put channels closer than " - "one length constant from the soma, and zero elsewhere. \n" - "Available fields are: \n" - "Channels: Gbar (install), Ek \n" - "CaConcen: shellDia (install), shellFrac (install), tau, min\n" - "Unless otherwise noted, all fields are scaled appropriately by " - "the dimensions of their compartment. Thus the channel " - "maximal conductance Gbar is automatically scaled by the area " - "of the compartment, and the user does not need to insert this " - "scaling into the calculations.\n" - "All parameters are expressed in SI units. Conductance, for " - "example, is Siemens/sq metre. " - "\n\n" - "Some example function forms might be for a channel Gbar: \n" - " p < 10e-6 ? 400 : 0.0 \n" - " equivalently, \n" - " H(10e-6 - p) * 400 \n" - " equivalently, \n" - " ( sign(10e-6 - p) + 1) * 200 \n" - "Each of these forms instruct the function to " - "set channel Gbar to 400 S/m^2 only within 10 microns path " - "distance of soma\n" - "\n" - " L < 1.0 ? 100 * exp( -L ) : 0.0 \n" - " ->Set channel Gbar to an exponentially falling function of " - "electrotonic distance from soma, provided L is under " - "1.0 lambdas. \n", + channelDistribution( + "channelDistribution", + "Specification for distribution of channels, CaConcens and " + "any other model components that are defined as prototypes and " + "have to be placed on the electrical compartments.\n" + "Arguments: proto path field expr [field expr]...\n" + " Each entry is terminated with an empty string. " + "The prototype is any object created in */library*, " + "If a channel matching the prototype name already exists, then " + "all subsequent operations are applied to the extant channel and " + "a new one is not created. " + "The paired arguments are as follows: \n" + "The *field* argument specifies the name of the parameter " + "that is to be assigned by the expression.\n" + "The *expression* argument is a mathematical expression in " + "the muparser framework, which permits most operations including " + "trig and transcendental ones. Of course it also handles simple " + "numerical values like 1.0, 1e-10 and so on. " + "Available arguments for muParser are:\n" + " p, g, L, len, dia, maxP, maxG, maxL \n" + " p: path distance from soma, measured along dendrite, in metres.\n" + " g: geometrical distance from soma, in metres.\n" + " L: electrotonic distance (# of lambdas) from soma, along dend. No units.\n" + " len: length of compartment, in metres.\n" + " dia: for diameter of compartment, in metres.\n" + " maxP: Maximum value of *p* for this neuron. \n" + " maxG: Maximum value of *g* for this neuron. \n" + " maxL: Maximum value of *L* for this neuron.\n" + "The expression for the first field must evaluate to > 0 " + "for the channel to be installed. For example, for " + "channels, if Field == Gbar, and func( r, L, len, dia) < 0, \n" + "then the channel is not installed. This feature is typically " + "used with the sign() or Heaviside H() function to limit range: " + "for example: H(1 - L) will only put channels closer than " + "one length constant from the soma, and zero elsewhere. \n" + "Available fields are: \n" + "Channels: Gbar (install), Ek \n" + "CaConcen: shellDia (install), shellFrac (install), tau, min\n" + "Unless otherwise noted, all fields are scaled appropriately by " + "the dimensions of their compartment. Thus the channel " + "maximal conductance Gbar is automatically scaled by the area " + "of the compartment, and the user does not need to insert this " + "scaling into the calculations.\n" + "All parameters are expressed in SI units. Conductance, for " + "example, is Siemens/sq metre. " + "\n\n" + "Some example function forms might be for a channel Gbar: \n" + " p < 10e-6 ? 400 : 0.0 \n" + " equivalently, \n" + " H(10e-6 - p) * 400 \n" + " equivalently, \n" + " ( sign(10e-6 - p) + 1) * 200 \n" + "Each of these forms instruct the function to " + "set channel Gbar to 400 S/m^2 only within 10 microns path " + "distance of soma\n" + "\n" + " L < 1.0 ? 100 * exp( -L ) : 0.0 \n" + " ->Set channel Gbar to an exponentially falling function of " + "electrotonic distance from soma, provided L is under " + "1.0 lambdas. \n", &Neuron::setChannelDistribution, &Neuron::getChannelDistribution - ); + ); static ElementValueFinfo< Neuron, vector< string > > - passiveDistribution( - "passiveDistribution", - "Specification for distribution of passive properties of cell.\n" - "Arguments: . path field expr [field expr]...\n" - "Note that the arguments list starts with a period. " - " Each entry is terminated with an empty string. " - "The paired arguments are as follows: \n" - "The *field* argument specifies the name of the parameter " - "that is to be assigned by the expression.\n" - "The *expression* argument is a mathematical expression in " - "the muparser framework, which permits most operations including " - "trig and transcendental ones. Of course it also handles simple " - "numerical values like 1.0, 1e-10 and so on. " - "Available arguments for muParser are:\n" - " p, g, L, len, dia, maxP, maxG, maxL \n" - " p: path distance from soma, measured along dendrite, in metres.\n" - " g: geometrical distance from soma, in metres.\n" - " L: electrotonic distance (# of lambdas) from soma, along dend. No units.\n" - " len: length of compartment, in metres.\n" - " dia: for diameter of compartment, in metres.\n" - " maxP: Maximum value of *p* for this neuron. \n" - " maxG: Maximum value of *g* for this neuron. \n" - " maxL: Maximum value of *L* for this neuron.\n" - "Available fields are: \n" - "RM, RA, CM, Rm, Ra, Cm, Em, initVm \n" - "The first three fields are scaled appropriately by " - "the dimensions of their compartment. Thus the membrane " - "resistivity RM (ohms.m^2) is automatically scaled by the area " - "of the compartment, and the user does not need to insert this " - "scaling into the calculations to compute Rm." - "Using the Rm field lets the user directly assign the " - "membrane resistance (in ohms), presumably using len and dia.\n" - "Similarly, RA (ohms.m) and CM (Farads/m^2) are specific units " - "and the actual values for each compartment are assigned by " - "scaling by length and diameter. Ra (ohms) and Cm (Farads) " - "require explicit evaluation of the expression. " - "All parameters are expressed in SI units. Conductance, for " - "example, is Siemens/sq metre.\n" - "Note that time these calculations do NOT currently include spines\n", + passiveDistribution( + "passiveDistribution", + "Specification for distribution of passive properties of cell.\n" + "Arguments: . path field expr [field expr]...\n" + "Note that the arguments list starts with a period. " + " Each entry is terminated with an empty string. " + "The paired arguments are as follows: \n" + "The *field* argument specifies the name of the parameter " + "that is to be assigned by the expression.\n" + "The *expression* argument is a mathematical expression in " + "the muparser framework, which permits most operations including " + "trig and transcendental ones. Of course it also handles simple " + "numerical values like 1.0, 1e-10 and so on. " + "Available arguments for muParser are:\n" + " p, g, L, len, dia, maxP, maxG, maxL \n" + " p: path distance from soma, measured along dendrite, in metres.\n" + " g: geometrical distance from soma, in metres.\n" + " L: electrotonic distance (# of lambdas) from soma, along dend. No units.\n" + " len: length of compartment, in metres.\n" + " dia: for diameter of compartment, in metres.\n" + " maxP: Maximum value of *p* for this neuron. \n" + " maxG: Maximum value of *g* for this neuron. \n" + " maxL: Maximum value of *L* for this neuron.\n" + "Available fields are: \n" + "RM, RA, CM, Rm, Ra, Cm, Em, initVm \n" + "The first three fields are scaled appropriately by " + "the dimensions of their compartment. Thus the membrane " + "resistivity RM (ohms.m^2) is automatically scaled by the area " + "of the compartment, and the user does not need to insert this " + "scaling into the calculations to compute Rm." + "Using the Rm field lets the user directly assign the " + "membrane resistance (in ohms), presumably using len and dia.\n" + "Similarly, RA (ohms.m) and CM (Farads/m^2) are specific units " + "and the actual values for each compartment are assigned by " + "scaling by length and diameter. Ra (ohms) and Cm (Farads) " + "require explicit evaluation of the expression. " + "All parameters are expressed in SI units. Conductance, for " + "example, is Siemens/sq metre.\n" + "Note that time these calculations do NOT currently include spines\n", &Neuron::setPassiveDistribution, &Neuron::getPassiveDistribution - ); + ); static ElementValueFinfo< Neuron, vector< string > >spineDistribution( - "spineDistribution", - "Specification for distribution of spines on dendrite. \n" - "Arguments: proto path spacing expr [field expr]...\n" - " Each entry is terminated with an empty string. " - "The *prototype* is any spine object created in */library*, \n" - "The *path* is the wildcard path of compartments on which to " - "place the spine.\n" - "The *spacing* is the spacing of spines, in metres. \n" - "The *expression* argument is a mathematical expression in " - "the muparser framework, which permits most operations including " - "trig and transcendental ones. Of course it also handles simple " - "numerical values like 1.0, 1e-10 and so on. " - "The paired arguments are as follows: \n" - "The *field* argument specifies the name of the parameter " - "that is to be assigned by the expression.\n" - "The *expression* argument is a mathematical expression as above. " - "Available arguments for muParser are:\n" - " p, g, L, len, dia, maxP, maxG, maxL \n" - " p: path distance from soma, measured along dendrite, in metres.\n" - " g: geometrical distance from soma, in metres.\n" - " L: electrotonic distance (# of lambdas) from soma, along dend. No units.\n" - " len: length of compartment, in metres.\n" - " dia: for diameter of compartment, in metres.\n" - " maxP: Maximum value of *p* for this neuron. \n" - " maxG: Maximum value of *g* for this neuron. \n" - " maxL: Maximum value of *L* for this neuron.\n" - "The expression for the *spacing* field must evaluate to > 0 for " - "the spine to be installed. For example, if the expresssion is\n" - " H(1 - L) \n" - "then the system will only put spines closer than " - "one length constant from the soma, and zero elsewhere. \n" - "Available spine parameters are: \n" - "spacing, minSpacing, size, sizeDistrib " - "angle, angleDistrib \n" - "minSpacing sets the granularity of sampling (typically about 0.1*" - "spacing) for the usual case where spines are spaced randomly. " - "If minSpacing < 0 then the spines are spaced equally at " - "'spacing', unless the dendritic segment length is smaller than " - "'spacing'. In that case it falls back to the regular random " - "placement method.", + "spineDistribution", + "Specification for distribution of spines on dendrite. \n" + "Arguments: proto path spacing expr [field expr]...\n" + " Each entry is terminated with an empty string. " + "The *prototype* is any spine object created in */library*, \n" + "The *path* is the wildcard path of compartments on which to " + "place the spine.\n" + "The *spacing* is the spacing of spines, in metres. \n" + "The *expression* argument is a mathematical expression in " + "the muparser framework, which permits most operations including " + "trig and transcendental ones. Of course it also handles simple " + "numerical values like 1.0, 1e-10 and so on. " + "The paired arguments are as follows: \n" + "The *field* argument specifies the name of the parameter " + "that is to be assigned by the expression.\n" + "The *expression* argument is a mathematical expression as above. " + "Available arguments for muParser are:\n" + " p, g, L, len, dia, maxP, maxG, maxL \n" + " p: path distance from soma, measured along dendrite, in metres.\n" + " g: geometrical distance from soma, in metres.\n" + " L: electrotonic distance (# of lambdas) from soma, along dend. No units.\n" + " len: length of compartment, in metres.\n" + " dia: for diameter of compartment, in metres.\n" + " maxP: Maximum value of *p* for this neuron. \n" + " maxG: Maximum value of *g* for this neuron. \n" + " maxL: Maximum value of *L* for this neuron.\n" + "The expression for the *spacing* field must evaluate to > 0 for " + "the spine to be installed. For example, if the expresssion is\n" + " H(1 - L) \n" + "then the systemwill only put spines closer than " + "one length constant from the soma, and zero elsewhere. \n" + "Available spine parameters are: \n" + "spacing, minSpacing, size, sizeDistrib " + "angle, angleDistrib \n" + "minSpacing sets the granularity of sampling (typically about 0.1*" + "spacing) for the usual case where spines are spaced randomly. " + "If minSpacing < 0 then the spines are spaced equally at " + "'spacing', unless the dendritic segment length is smaller than " + "'spacing'. In that case it falls back to the regular random " + "placement method.", &Neuron::setSpineDistribution, &Neuron::getSpineDistribution - ); + ); static ReadOnlyValueFinfo< Neuron, unsigned int > numCompartments( - "numCompartments", - "Number of electrical compartments in model. ", - &Neuron::getNumCompartments - ); + "numCompartments", + "Number of electrical compartments in model. ", + &Neuron::getNumCompartments + ); static ReadOnlyValueFinfo< Neuron, unsigned int > numSpines( - "numSpines", - "Number of dendritic spines in model. ", - &Neuron::getNumSpines - ); + "numSpines", + "Number of dendritic spines in model. ", + &Neuron::getNumSpines + ); static ReadOnlyValueFinfo< Neuron, unsigned int > numBranches( - "numBranches", - "Number of branches in dendrites. ", - &Neuron::getNumBranches - ); + "numBranches", + "Number of branches in dendrites. ", + &Neuron::getNumBranches + ); static ReadOnlyValueFinfo< Neuron, vector< double > > pathDistFromSoma( - "pathDistanceFromSoma", - "geometrical path distance of each segment from soma, measured by " - "threading along the dendrite.", - &Neuron::getPathDistFromSoma - ); + "pathDistanceFromSoma", + "geometrical path distance of each segment from soma, measured by " + "threading along the dendrite.", + &Neuron::getPathDistFromSoma + ); static ReadOnlyValueFinfo< Neuron, vector< double > > geomDistFromSoma( - "geometricalDistanceFromSoma", - "geometrical distance of each segment from soma.", - &Neuron::getGeomDistFromSoma - ); + "geometricalDistanceFromSoma", + "geometrical distance of each segment from soma.", + &Neuron::getGeomDistFromSoma + ); static ReadOnlyValueFinfo< Neuron, vector< double > > elecDistFromSoma( - "electrotonicDistanceFromSoma", - "geometrical distance of each segment from soma, as measured along " - "the dendrite.", - &Neuron::getElecDistFromSoma - ); + "electrotonicDistanceFromSoma", + "geometrical distance of each segment from soma, as measured along " + "the dendrite.", + &Neuron::getElecDistFromSoma + ); static ReadOnlyValueFinfo< Neuron, vector< ObjId > > compartments( - "compartments", - "Vector of ObjIds of electrical compartments. Order matches order " - "of segments, and also matches the order of the electrotonic and " - "geometricalDistanceFromSoma vectors. ", - &Neuron::getCompartments - ); + "compartments", + "Vector of ObjIds of electrical compartments. Order matches order " + "of segments, and also matches the order of the electrotonic and " + "geometricalDistanceFromSoma vectors. ", + &Neuron::getCompartments + ); static ReadOnlyLookupElementValueFinfo< Neuron, string, vector< ObjId > > - compartmentsFromExpression( - "compartmentsFromExpression", - "Vector of ObjIds of electrical compartments that match the " - "'path expression' pair in the argument string.", - &Neuron::getExprElist - ); + compartmentsFromExpression( + "compartmentsFromExpression", + "Vector of ObjIds of electrical compartments that match the " + "'path expression' pair in the argument string.", + &Neuron::getExprElist + ); static ReadOnlyLookupElementValueFinfo< Neuron, string, vector< double > > - valuesFromExpression( - "valuesFromExpression", - "Vector of values computed for each electrical compartment that " - "matches the 'path expression' pair in the argument string." - "This has 13 times the number of entries as # of compartments." - "For each compartment the entries are: \n" - "val, p, g, L, len, dia, maxP, maxG, maxL, x, y, z, 0", - &Neuron::getExprVal - ); + valuesFromExpression( + "valuesFromExpression", + "Vector of values computed for each electrical compartment that " + "matches the 'path expression' pair in the argument string." + "This has 13 times the number of entries as # of compartments." + "For each compartment the entries are: \n" + "val, p, g, L, len, dia, maxP, maxG, maxL, x, y, z, 0", + &Neuron::getExprVal + ); static ReadOnlyLookupElementValueFinfo< Neuron, string, vector< ObjId > > - spinesFromExpression( - "spinesFromExpression", - //"Vector of ObjIds of spines/heads sitting on the electrical " - //"compartments that match the 'path expression' pair in the " - //"argument string.", - "Vector of ObjIds of compartments comprising spines/heads " - "that match the 'path expression' pair in the " - "argument string.", - &Neuron::getSpinesFromExpression - ); + spinesFromExpression( + "spinesFromExpression", + //"Vector of ObjIds of spines/heads sitting on the electrical " + //"compartments that match the 'path expression' pair in the " + //"argument string.", + "Vector of ObjIds of compartments comprising spines/heads " + "that match the 'path expression' pair in the " + "argument string.", + &Neuron::getSpinesFromExpression + ); static ReadOnlyLookupElementValueFinfo< Neuron, ObjId,vector< ObjId > > - spinesOnCompartment( - "spinesOnCompartment", - "Vector of ObjIds of spines shafts/heads sitting on the specified " - "electrical compartment. If each spine has a shaft and a head," - "and there are 10 spines on the compartment, there will be 20 " - "entries in the returned vector, ordered " - "shaft0, head0, shaft1, head1, ... ", - &Neuron::getSpinesOnCompartment - ); + spinesOnCompartment( + "spinesOnCompartment", + "Vector of ObjIds of spines shafts/heads sitting on the specified " + "electrical compartment. If each spine has a shaft and a head," + "and there are 10 spines on the compartment, there will be 20 " + "entries in the returned vector, ordered " + "shaft0, head0, shaft1, head1, ... ", + &Neuron::getSpinesOnCompartment + ); static ReadOnlyLookupElementValueFinfo< Neuron, ObjId, ObjId > - parentCompartmentOfSpine( - "parentCompartmentOfSpine", - "Returns parent compartment of specified spine compartment." - "Both the spine head or its shaft will return the same parent.", - &Neuron::getParentCompartmentOfSpine - ); + parentCompartmentOfSpine( + "parentCompartmentOfSpine", + "Returns parent compartment of specified spine compartment." + "Both the spine head or its shaft will return the same parent.", + &Neuron::getParentCompartmentOfSpine + ); static ReadOnlyLookupElementValueFinfo< Neuron, vector< ObjId >, vector< ObjId > > - spineIdsFromCompartmentIds( - "spineIdsFromCompartmentIds", - "Vector of ObjIds of spine entries (FieldElements on this Neuron, " - "used for scaling) that map to the the specified " - "electrical compartments. If a bad compartment Id is given, the" - "corresponding spine entry is the root Id.", - &Neuron::getSpineIdsFromCompartmentIds - ); + spineIdsFromCompartmentIds( + "spineIdsFromCompartmentIds", + "Vector of ObjIds of spine entries (FieldElements on this Neuron, " + "used for scaling) that map to the the specified " + "electrical compartments. If a bad compartment Id is given, the" + "corresponding spine entry is the root Id.", + &Neuron::getSpineIdsFromCompartmentIds + ); ///////////////////////////////////////////////////////////////////// // DestFinfos ///////////////////////////////////////////////////////////////////// static DestFinfo buildSegmentTree( "buildSegmentTree", - "Build the reference segment tree structure using the child " - "compartments of the current Neuron. Fills in all the coords and " - "length constant information into the segments, for later use " - "when we build reduced compartment trees and channel " - "distributions. Should only be called once, since subsequent use " - "on a reduced model will lose the original full cell geometry. ", - new EpFunc0< Neuron >( &Neuron::buildSegmentTree ) - ); + "Build the reference segment tree structure using the child " + "compartments of the current Neuron. Fills in all the coords and " + "length constant information into the segments, for later use " + "when we build reduced compartment trees and channel " + "distributions. Should only be called once, since subsequent use " + "on a reduced model will lose the original full cell geometry. ", + new EpFunc0< Neuron >( &Neuron::buildSegmentTree ) + ); static DestFinfo setSpineAndPsdMesh( "setSpineAndPsdMesh", - "Assigns the spine and psd mesh to the Neuron. This is used " - "to build up a mapping from Spine entries on the Neuron to " - "chem spines and PSDs, so that volume change operations from " - "the Spine can propagate to the chem systems.", - new OpFunc2< Neuron, Id, Id >( &Neuron::setSpineAndPsdMesh ) - ); + "Assigns the spine and psd mesh to the Neuron. This is used " + "to build up a mapping from Spine entries on the Neuron to " + "chem spines and PSDs, so that volume change operations from " + "the Spine can propagate to the chem systems.", + new OpFunc2< Neuron, Id, Id >( &Neuron::setSpineAndPsdMesh ) + ); static DestFinfo setSpineAndPsdDsolve( "setSpineAndPsdDsolve", - "Assigns the Dsolves used by spine and PSD to the Neuron. " - "This is used " - "to handle the rescaling of diffusion rates when spines are " - "resized. ", - new OpFunc2< Neuron, Id, Id >( &Neuron::setSpineAndPsdDsolve ) - ); + "Assigns the Dsolves used by spine and PSD to the Neuron. " + "This is used " + "to handle the rescaling of diffusion rates when spines are " + "resized. ", + new OpFunc2< Neuron, Id, Id >( &Neuron::setSpineAndPsdDsolve ) + ); /* static DestFinfo rotateInSpace( "rotateInSpace", @@ -781,7 +783,7 @@ static void setCompartmentParams( } } } - catch ( mu::Parser::exception_type& err ) + catch ( moose::Parser::exception_type& err ) { cout << err.GetMsg() << endl; } @@ -807,7 +809,7 @@ static void setMechParams( } } } - catch ( mu::Parser::exception_type& err ) + catch ( moose::Parser::exception_type& err ) { cout << err.GetMsg() << endl; } @@ -1551,7 +1553,7 @@ void Neuron::evalExprForElist( const vector< ObjId >& elist, valIndex += nuParser::numVal; } } - catch ( mu::Parser::exception_type& err ) + catch ( moose::Parser::exception_type& err ) { cout << err.GetMsg() << endl; } @@ -1910,9 +1912,9 @@ void Neuron::makeSpacingDistrib( const vector< ObjId >& elist, } } } - catch ( mu::Parser::exception_type& err ) + catch ( moose::Parser::exception_type& err ) { - cout << err.GetMsg() << endl; + cerr << err.GetMsg() << endl; } } @@ -1954,7 +1956,7 @@ static void makeAngleDistrib ( const vector< ObjId >& elist, theta[k] = angle; } } - catch ( mu::Parser::exception_type& err ) + catch ( moose::Parser::exception_type& err ) { cout << err.GetMsg() << endl; } @@ -1996,7 +1998,7 @@ static void makeSizeDistrib ( const vector< ObjId >& elist, size[k] = sz; } } - catch ( mu::Parser::exception_type& err ) + catch ( moose::Parser::exception_type& err ) { cout << err.GetMsg() << endl; } diff --git a/biophysics/ReadCell.cpp b/biophysics/ReadCell.cpp index 50f2ef08..06c0f246 100644 --- a/biophysics/ReadCell.cpp +++ b/biophysics/ReadCell.cpp @@ -10,7 +10,7 @@ #include "../basecode/header.h" #include "../shell/Shell.h" #include "ReadCell.h" -#include "../utility/utility.h" +#include "../utility/strutil.h" #include "CompartmentBase.h" #include "Compartment.h" #include "SymCompartment.h" diff --git a/biophysics/testBiophysics.cpp b/biophysics/testBiophysics.cpp index e46b3012..0dde4834 100644 --- a/biophysics/testBiophysics.cpp +++ b/biophysics/testBiophysics.cpp @@ -105,8 +105,8 @@ void testIntFireNetwork( unsigned int runsteps = 5 ) // by multiple threads if the above Set call is not complete. vector< double > origVm( size, 0.0 ); - - // NOTE: From + + // NOTE: From moose::mtseed( 5489UL ); for ( unsigned int i = 0; i < size; ++i ) origVm[i] = moose::mtrand() * Vmax; @@ -214,7 +214,7 @@ void testIntFireNetwork( unsigned int runsteps = 5 ) #if 0 cout << endl; - cout << std::setprecision(12) << retVm100 << endl; + cout << std::setprecision(12) << retVm100 << endl; cout << std::setprecision(12) << retVm101 << endl; cout << std::setprecision(12) << retVm102 << endl; cout << std::setprecision(11) << retVm99 << endl; @@ -746,26 +746,26 @@ void testHHChannel() //Sample current obtained from channel in Chapter 20, Sakmann & Neher, Pg. 603. //The current is sampled at intervals of 10 usec. static double sampleCurrent[] = {0.0, // This is to handle the value sent by ChanBase on reinit - 0.0000000e+00, 3.0005743e-26, 1.2004594e-25, 2.7015505e-25, 4.8036751e-25, 7.5071776e-25, - 1.0812402e-24, 1.4719693e-24, 1.9229394e-24, 2.4341850e-24, 3.0057404e-24, 3.6376401e-24, - 4.3299183e-24, 5.0826095e-24, 5.8957481e-24, 6.7693684e-24, 7.7035046e-24, 8.6981913e-24, - 9.7534627e-24, 1.0869353e-23, 1.2045897e-23, 1.3283128e-23, 1.4581082e-23, 1.5939791e-23, - 1.7359292e-23, 1.8839616e-23, 2.0380801e-23, 2.1982878e-23, 2.3645883e-23, 2.5369850e-23, - 2.7154813e-23, 2.9000806e-23, 3.0907863e-23, 3.2876020e-23, 3.4905309e-23, 3.6995766e-23, - 3.9147423e-23, 4.1360317e-23, 4.3634480e-23, 4.5969946e-23, 4.8366751e-23, 5.0824928e-23, - 5.3344511e-23, 5.5925535e-23, 5.8568033e-23, 6.1272040e-23, 6.4037589e-23, 6.6864716e-23, - 6.9753453e-23, 7.2703835e-23, 7.5715897e-23, 7.8789672e-23, 8.1925194e-23, 8.5122497e-23, - 8.8381616e-23, 9.1702584e-23, 9.5085435e-23, 9.8530204e-23, 1.0203692e-22, 1.0560563e-22, - 1.0923636e-22, 1.1292913e-22, 1.1668400e-22, 1.2050099e-22, 1.2438013e-22, 1.2832146e-22, - 1.3232502e-22, 1.3639083e-22, 1.4051894e-22, 1.4470937e-22, 1.4896215e-22, 1.5327733e-22, - 1.5765494e-22, 1.6209501e-22, 1.6659757e-22, 1.7116267e-22, 1.7579032e-22, 1.8048057e-22, - 1.8523345e-22, 1.9004900e-22, 1.9492724e-22, 1.9986821e-22, 2.0487195e-22, 2.0993849e-22, - 2.1506786e-22, 2.2026010e-22, 2.2551524e-22, 2.3083331e-22, 2.3621436e-22, 2.4165840e-22, - 2.4716548e-22, 2.5273563e-22, 2.5836888e-22, 2.6406527e-22, 2.6982483e-22, 2.7564760e-22, - 2.8153360e-22, 2.8748287e-22, 2.9349545e-22, 2.9957137e-22, 3.0571067e-22 - }; - -void testMarkovGslSolver() + 0.0000000e+00, 3.0005743e-26, 1.2004594e-25, 2.7015505e-25, 4.8036751e-25, 7.5071776e-25, + 1.0812402e-24, 1.4719693e-24, 1.9229394e-24, 2.4341850e-24, 3.0057404e-24, 3.6376401e-24, + 4.3299183e-24, 5.0826095e-24, 5.8957481e-24, 6.7693684e-24, 7.7035046e-24, 8.6981913e-24, + 9.7534627e-24, 1.0869353e-23, 1.2045897e-23, 1.3283128e-23, 1.4581082e-23, 1.5939791e-23, + 1.7359292e-23, 1.8839616e-23, 2.0380801e-23, 2.1982878e-23, 2.3645883e-23, 2.5369850e-23, + 2.7154813e-23, 2.9000806e-23, 3.0907863e-23, 3.2876020e-23, 3.4905309e-23, 3.6995766e-23, + 3.9147423e-23, 4.1360317e-23, 4.3634480e-23, 4.5969946e-23, 4.8366751e-23, 5.0824928e-23, + 5.3344511e-23, 5.5925535e-23, 5.8568033e-23, 6.1272040e-23, 6.4037589e-23, 6.6864716e-23, + 6.9753453e-23, 7.2703835e-23, 7.5715897e-23, 7.8789672e-23, 8.1925194e-23, 8.5122497e-23, + 8.8381616e-23, 9.1702584e-23, 9.5085435e-23, 9.8530204e-23, 1.0203692e-22, 1.0560563e-22, + 1.0923636e-22, 1.1292913e-22, 1.1668400e-22, 1.2050099e-22, 1.2438013e-22, 1.2832146e-22, + 1.3232502e-22, 1.3639083e-22, 1.4051894e-22, 1.4470937e-22, 1.4896215e-22, 1.5327733e-22, + 1.5765494e-22, 1.6209501e-22, 1.6659757e-22, 1.7116267e-22, 1.7579032e-22, 1.8048057e-22, + 1.8523345e-22, 1.9004900e-22, 1.9492724e-22, 1.9986821e-22, 2.0487195e-22, 2.0993849e-22, + 2.1506786e-22, 2.2026010e-22, 2.2551524e-22, 2.3083331e-22, 2.3621436e-22, 2.4165840e-22, + 2.4716548e-22, 2.5273563e-22, 2.5836888e-22, 2.6406527e-22, 2.6982483e-22, 2.7564760e-22, + 2.8153360e-22, 2.8748287e-22, 2.9349545e-22, 2.9957137e-22, 3.0571067e-22 + }; + +void testMarkovOdeSolver() { Shell* shell = reinterpret_cast< Shell* >( ObjId( Id(), 0 ).data() ); unsigned size = 1; @@ -774,7 +774,7 @@ void testMarkovGslSolver() Id comptId = shell->doCreate( "Compartment", nid, "compt", size ); Id rateTabId = shell->doCreate( "MarkovRateTable", comptId, "rateTab", size ); Id mChanId = shell->doCreate( "MarkovChannel", comptId, "mChan", size ); - Id gslSolverId = shell->doCreate( "MarkovGslSolver", comptId, "gslSolver", size ); + Id gslSolverId = shell->doCreate( "MarkovOdeSolver", comptId, "gslSolver", size ); Id tabId = shell->doCreate( "Table", nid, "tab", size ); @@ -902,9 +902,10 @@ void testMarkovGslSolver() { if (!doubleEq( sampleCurrent[i] * 1e25, vec[i] * 1e25 )) { - cout << "testMarkovGslSolver: sample=" << sampleCurrent[i]*1e25 << " calculated=" << vec[i]*1e25 << endl; + cout << "testMarkovOdeSolver: sample=" << sampleCurrent[i]*1e25 << " calculated=" << vec[i]*1e25 << endl; } ASSERT_DOUBLE_EQ("", sampleCurrent[i] * 1e25, vec[i] * 1e25 ); + // cout << sampleCurrent[i] << " " << vec[i] << endl; } //Currents involved here are incredibly small. Scaling them up is necessary //for the doubleEq function to do its job. @@ -914,16 +915,16 @@ void testMarkovGslSolver() } //////////////// -//The testMarkovGslSolver() function includes the MarkovChannel object, but +//The testMarkovOdeSolver() function includes the MarkovChannel object, but //is a rather trivial case, in that the rates are all constant. -//This test simultaneously tests the MarkovChannel, MarkovGslSolver, +//This test simultaneously tests the MarkovChannel, MarkovOdeSolver, //MarkovSolverBase and MarkovSolver classes. //This test involves simulating the 4-state NMDA channel model specified //in the following paper : //"Voltage Dependence of NMDA-Activated Macroscopic Conductances Predicted //by Single-Channel Kinetics", Craig E. Jahr and Charles F. Stevens, The Journal //of Neuroscience, 1990, 10(9), pp. 3178-3182. -//It is expected that the MarkovGslSolver and the MarkovSolver objects will +//It is expected that the MarkovOdeSolver and the MarkovSolver objects will //give the same answer. // //Note that this is different from the NMDAChan test which involves synapses. @@ -944,12 +945,12 @@ void testMarkovChannel() Id exptlRateTableId = shell->doCreate( "MarkovRateTable", exptlComptId, "exptlRateTable", size ); - Id mChanGslId = shell->doCreate( "MarkovChannel", gslComptId, - "mChanGsl", size ); + Id mChanOdeId = shell->doCreate( "MarkovChannel", gslComptId, + "mChanOde", size ); Id mChanExptlId = shell->doCreate( "MarkovChannel", exptlComptId, "mChanExptl", size ); - Id gslSolverId = shell->doCreate( "MarkovGslSolver", gslComptId, + Id gslSolverId = shell->doCreate( "MarkovOdeSolver", gslComptId, "gslSolver", size ); Id exptlSolverId = shell->doCreate( "MarkovSolver", exptlComptId, "exptlSolver", size ); @@ -972,7 +973,7 @@ void testMarkovChannel() //via its ChanBase base class, sends back the conductance and current through //it. ObjId mid = shell->doAddMsg( "Single", ObjId( gslComptId ), "channel", - ObjId( mChanGslId ), "channel" ); + ObjId( mChanOdeId ), "channel" ); assert( !mid.bad() ); mid = shell->doAddMsg( "Single", ObjId( exptlComptId ), "channel", @@ -980,7 +981,7 @@ void testMarkovChannel() assert( !mid.bad() ); //////// - //Connecting up the MarkovGslSolver. + //Connecting up the MarkovOdeSolver. /////// //Connecting Compartment and MarkovRateTable. @@ -996,20 +997,20 @@ void testMarkovChannel() ObjId( gslRateTableId ), "channel" ); assert( !mid.bad() ); - //Connecting the MarkovRateTable with the MarkovGslSolver object. + //Connecting the MarkovRateTable with the MarkovOdeSolver object. //As mentioned earlier, the MarkovRateTable object sends out information - //about Q to the MarkovGslSolver. The MarkovGslSolver then churns out + //about Q to the MarkovOdeSolver. The MarkovOdeSolver then churns out //the state of the system for the next time step. mid = shell->doAddMsg("Single", ObjId( gslRateTableId ), "instratesOut", ObjId( gslSolverId ), "handleQ" ); - //Connecting MarkovGslSolver with MarkovChannel. - //The MarkovGslSolver object, upon computing the state of the channel, + //Connecting MarkovOdeSolver with MarkovChannel. + //The MarkovOdeSolver object, upon computing the state of the channel, //sends this information to the MarkovChannel object. The MarkovChannel //object will compute the expected conductance of the channel and send //this information to the compartment. mid = shell->doAddMsg( "Single", ObjId( gslSolverId ), "stateOut", - ObjId( mChanGslId ), "handleState" ); + ObjId( mChanOdeId ), "handleState" ); assert( !mid.bad() ); ////////// @@ -1035,7 +1036,7 @@ void testMarkovChannel() //Get the current values from the GSL solver based channel. mid = shell->doAddMsg( "Single", ObjId( gslTableId ), "requestOut", - ObjId( mChanGslId ), "getIk" ); + ObjId( mChanOdeId ), "getIk" ); assert( !mid.bad() ); //Get the current values from the matrix exponential solver based channel. @@ -1069,10 +1070,10 @@ void testMarkovChannel() ///////////////// //Number of states and open states. - Field< unsigned int >::set( mChanGslId, "numStates", 4 ); + Field< unsigned int >::set( mChanOdeId, "numStates", 4 ); Field< unsigned int >::set( mChanExptlId, "numStates", 4 ); - Field< unsigned int >::set( mChanGslId, "numOpenStates", 1 ); + Field< unsigned int >::set( mChanOdeId, "numOpenStates", 1 ); Field< unsigned int >::set( mChanExptlId, "numOpenStates", 1 ); vector< string > stateLabels; @@ -1085,7 +1086,7 @@ void testMarkovChannel() stateLabels.push_back( "B2" ); //State 3. stateLabels.push_back( "C" ); //State 4. - Field< vector< string > >::set( mChanGslId, "labels", stateLabels ); + Field< vector< string > >::set( mChanOdeId, "labels", stateLabels ); Field< vector< string > >::set( mChanExptlId, "labels", stateLabels ); //Setting up conductance value for single open state. Value chosen @@ -1094,7 +1095,7 @@ void testMarkovChannel() gBar.push_back( 5.431553e-9 ); - Field< vector< double > >::set( mChanGslId, "gbar", gBar ); + Field< vector< double > >::set( mChanOdeId, "gbar", gBar ); Field< vector< double > >::set( mChanExptlId, "gbar", gBar ); //Initial state of the system. This is really an arbitrary choice. @@ -1105,7 +1106,7 @@ void testMarkovChannel() initState.push_back( 0.80 ); initState.push_back( 0.00 ); - Field< vector< double > >::set( mChanGslId, "initialState", initState ); + Field< vector< double > >::set( mChanOdeId, "initialState", initState ); Field< vector< double > >::set( mChanExptlId, "initialState", initState ); //This initializes the GSL solver object. @@ -1254,7 +1255,7 @@ void testMarkovChannel() "process", 2 ); shell->doUseClock( "/n/gslCompt/gslSolver,/n/exptlCompt/exptlSolver", "process", 3 ); - shell->doUseClock( "/n/gslCompt/mChanGsl,/n/gslTable","process", 4 ); + shell->doUseClock( "/n/gslCompt/mChanOde,/n/gslTable","process", 4 ); shell->doUseClock( "/n/exptlCompt/mChanExptl,/n/exptlTable", "process", 5 ); shell->doReinit(); @@ -1687,13 +1688,15 @@ void testBiophysicsProcess() testIntFireNetwork(); testCompartmentProcess(); // testMarkovGslSolver(); - // testMarkovChannel(); + testMarkovChannel(); #if 0 testHHChannel(); #endif } #else // ifdef DO_UNIT_TESTS + +// Dummy functions to avoid link error. void testBiophysics() { ; diff --git a/builtins/CMakeLists.txt b/builtins/CMakeLists.txt index 9b4e6399..aefa3964 100644 --- a/builtins/CMakeLists.txt +++ b/builtins/CMakeLists.txt @@ -44,6 +44,7 @@ if(WITH_NSDF) else(HDF5_FOUND) message(STATUS "HDF5 is not found. Disabling NSDF support." ) + add_definitions(-UUSE_HDF5 -UENABLE_NSDF) endif( HDF5_FOUND ) endif(WITH_NSDF) @@ -51,7 +52,6 @@ set(SRCS Arith.cpp Group.cpp Mstring.cpp - MooseParser.cpp Function.cpp Variable.cpp InputVariable.cpp @@ -65,17 +65,20 @@ set(SRCS Stats.cpp Interpol2D.cpp SpikeStats.cpp + MooseParser.cpp SocketStreamer.cpp testBuiltins.cpp ) if(WITH_NSDF AND HDF5_FOUND) list(APPEND SRCS - HDF5WriterBase.cpp - NSDFWriter.cpp - HDF5DataWriter.cpp - testNSDF.cpp - ) + HDF5WriterBase.cpp + NSDFWriter.cpp + HDF5DataWriter.cpp + SpikeStats.cpp + testBuiltins.cpp + testNSDF.cpp + ) endif() add_library(moose_builtins ${SRCS} ) diff --git a/builtins/Func.cpp b/builtins/Func.cpp deleted file mode 100644 index 7408ded3..00000000 --- a/builtins/Func.cpp +++ /dev/null @@ -1,696 +0,0 @@ -// Func.cpp --- -// -// Filename: Func.cpp -// Description: Implementation of a wrapper around GNU libmatheval to calculate arbitrary functions. -// Author: Subhasis Ray -// Maintainer: Subhasis Ray -// Created: Sat May 25 16:35:17 2013 (+0530) -// Version: -// Last-Updated: Tue Jun 11 16:49:01 2013 (+0530) -// By: subha -// Update #: 619 -// URL: -// Keywords: -// Compatibility: -// -// - -// Commentary: -// -// -// -// - -// Change log: -// -// -// -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; either version 3, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this program; see the file COPYING. If not, write to -// the Free Software Foundation, Inc., 51 Franklin Street, Fifth -// Floor, Boston, MA 02110-1301, USA. -// -// - -// Code: - -#include "../basecode/header.h" -#include "../utility/utility.h" -#include "../utility/numutil.h" -#include "Func.h" - -static SrcFinfo1 *valueOut() -{ - static SrcFinfo1 valueOut("valueOut", - "Evaluated value of the function for the current variable values."); - return &valueOut; -} - -static SrcFinfo1< double > *derivativeOut() -{ - static SrcFinfo1< double > derivativeOut("derivativeOut", - "Value of derivative of the function for the current variable values"); - return &derivativeOut; -} - -const Cinfo * Func::initCinfo() -{ - //////////////////////////////////////////////////////////// - // Value fields - //////////////////////////////////////////////////////////// - static ReadOnlyValueFinfo< Func, double > value("value", - "Result of the function evaluation with current variable values.", - &Func::getValue); - static ReadOnlyValueFinfo< Func, double > derivative("derivative", - "Derivative of the function at given variable values.", - &Func::getDerivative); - static ValueFinfo< Func, unsigned int > mode("mode", - "Mode of operation: \n" - " 1: only the function value will be calculated\n" - " 2: only the derivative will be calculated\n" - " 3: both function value and derivative at current variable values will be calculated.", - &Func::setMode, - &Func::getMode); - static ValueFinfo< Func, string > expr("expr", - "Mathematical expression defining the function. The underlying parser\n" - "is muParser. In addition to the available functions and operators from\n" - "muParser, some more functions are added.\n" - "\nFunctions\n" - "Name args explanation\n" - "sin 1 sine function\n" - "cos 1 cosine function\n" - "tan 1 tangens function\n" - "asin 1 arcus sine function\n" - "acos 1 arcus cosine function\n" - "atan 1 arcus tangens function\n" - "sinh 1 hyperbolic sine function\n" - "cosh 1 hyperbolic cosine\n" - "tanh 1 hyperbolic tangens function\n" - "asinh 1 hyperbolic arcus sine function\n" - "acosh 1 hyperbolic arcus tangens function\n" - "atanh 1 hyperbolic arcur tangens function\n" - "log2 1 logarithm to the base 2\n" - "log10 1 logarithm to the base 10\n" - "log 1 logarithm to the base 10\n" - "ln 1 logarithm to base e (2.71828...)\n" - "exp 1 e raised to the power of x\n" - "sqrt 1 square root of a value\n" - "sign 1 sign function -1 if x<0; 1 if x>0\n" - "rint 1 round to nearest integer\n" - "abs 1 absolute value\n" - "min var. min of all arguments\n" - "max var. max of all arguments\n" - "sum var. sum of all arguments\n" - "avg var. mean value of all arguments\n" - "rand 1 rand(seed), random float between 0 and 1, \n" - " if seed = -1, then a 'random' seed is created.\n" - "rand2 3 rand(a, b, seed), random float between a and b, \n" - " if seed = -1, a 'random' seed is created using either\n" - " by random_device or by reading system clock\n" - "\nOperators\n" - "Op meaning prioroty\n" - "= assignement -1\n" - "&& logical and 1\n" - "|| logical or 2\n" - "<= less or equal 4\n" - ">= greater or equal 4\n" - "!= not equal 4\n" - "== equal 4\n" - "> greater than 4\n" - "< less than 4\n" - "+ addition 5\n" - "- subtraction 5\n" - "* multiplication 6\n" - "/ division 6\n" - "^ raise x to the power of y 7\n" - "\n" - "?: if then else operator C++ style syntax\n", - &Func::setExpr, - &Func::getExpr); - static LookupValueFinfo < Func, string, double > var("var", - "Lookup table for variable values.", - &Func::setVar, - &Func::getVar); - static ReadOnlyValueFinfo< Func, vector > vars("vars", - "Variable names in the expression", - &Func::getVars); - static ValueFinfo< Func, double > x("x", - "Value for variable named x. This is a shorthand. If the\n" - "expression does not have any variable named x, this the first variable\n" - "in the sequence `vars`.", - &Func::setX, - &Func::getX); - static ValueFinfo< Func, double > y("y", - "Value for variable named y. This is a utility for two/three\n" - " variable functions where the y value comes from a source separate\n" - " from that of x. This is a shorthand. If the\n" - "expression does not have any variable named y, this the second\n" - "variable in the sequence `vars`.", - &Func::setY, - &Func::getY); - static ValueFinfo< Func, double > z("z", - "Value for variable named z. This is a utility for three\n" - " variable functions where the z value comes from a source separate\n" - " from that of x or z. This is a shorthand. If the expression does not\n" - " have any variable named z, this the third variable in the sequence `vars`.", - &Func::setZ, - &Func::getZ); - //////////////////////////////////////////////////////////// - // DestFinfos - //////////////////////////////////////////////////////////// - static DestFinfo varIn("varIn", - "Handle value for specified variable coming from other objects", - new OpFunc2< Func, string, double > (&Func::setVar)); - static DestFinfo xIn("xIn", - "Handle value for variable named x. This is a shorthand. If the\n" - "expression does not have any variable named x, this the first variable\n" - "in the sequence `vars`.", - new OpFunc1< Func, double > (&Func::setX)); - static DestFinfo yIn("yIn", - "Handle value for variable named y. This is a utility for two/three\n" - " variable functions where the y value comes from a source separate\n" - " from that of x. This is a shorthand. If the\n" - "expression does not have any variable named y, this the second\n" - "variable in the sequence `vars`.", - new OpFunc1< Func, double > (&Func::setY)); - static DestFinfo zIn("zIn", - "Handle value for variable named z. This is a utility for three\n" - " variable functions where the z value comes from a source separate\n" - " from that of x or y. This is a shorthand. If the expression does not\n" - " have any variable named y, this the second variable in the sequence `vars`.", - new OpFunc1< Func, double > (&Func::setZ)); - static DestFinfo xyIn("xyIn", - "Handle value for variables x and y for two-variable function", - new OpFunc2< Func, double, double > (&Func::setXY)); - static DestFinfo xyzIn("xyzIn", - "Handle value for variables x, y and z for three-variable function", - new OpFunc3< Func, double, double, double > (&Func::setXYZ)); - - static DestFinfo setVars("setVars", - "Utility function to assign the variable values of the function.\n" - "Takes a list of variable names and a list of corresponding values.", - new OpFunc2< Func, vector< string >, vector< double > > (&Func::setVarValues)); - - // TODO - a way to allow connect a source to a specific variable without the source knowing the variable name - // simple case of x, [y, [z]] variables - - /////////////////////////////////////////////////////////////////// - // Shared messages - /////////////////////////////////////////////////////////////////// - static DestFinfo process( "process", - "Handles process call, updates internal time stamp.", - new ProcOpFunc< Func >( &Func::process ) ); - static DestFinfo reinit( "reinit", - "Handles reinit call.", - new ProcOpFunc< Func >( &Func::reinit ) ); - static Finfo* processShared[] = - { - &process, &reinit - }; - - static SharedFinfo proc( "proc", - "This is a shared message to receive Process messages " - "from the scheduler objects." - "The first entry in the shared msg is a MsgDest " - "for the Process operation. It has a single argument, " - "ProcInfo, which holds lots of information about current " - "time, thread, dt and so on. The second entry is a MsgDest " - "for the Reinit operation. It also uses ProcInfo. ", - processShared, sizeof( processShared ) / sizeof( Finfo* ) - ); - - static Finfo *funcFinfos[] = - { - &value, - &derivative, - &mode, - &expr, - &var, - &vars, - &x, - &y, - &z, - &varIn, - &xIn, - &yIn, - &zIn, - &xyIn, - &xyzIn, - &proc, - valueOut(), - derivativeOut(), - }; - - static string doc[] = - { - "Name", "Func", - "Author", "Subhasis Ray", - "Description", - "Func: general purpose function calculator using real numbers. It can\n" - "parse mathematical expression defining a function and evaluate it\n" - "and/or its derivative for specified variable values.\n" - "The variables can be input from other moose objects. In case of\n" - "arbitrary variable names, the source message must have the variable\n" - "name as the first argument. For most common cases, input messages to\n" - "set x, y, z and xy, xyz are made available without such\n" - "requirement. This class handles only real numbers\n" - "(C-double). Predefined constants are: pi=3.141592...,\n" - "e=2.718281... \n" - }; - - static Dinfo< Func > dinfo; - static Cinfo funcCinfo("Func", - Neutral::initCinfo(), - funcFinfos, - sizeof(funcFinfos) / sizeof(Finfo*), - &dinfo, - doc, - sizeof(doc)/sizeof(string)); - return &funcCinfo; - -} - -static const Cinfo * funcCinfo = Func::initCinfo(); - -const int Func::VARMAX = 10; - -Func::Func():_x(NULL), _y(NULL), _z(NULL), _mode(1), _valid(false) -{ - _varbuf.reserve(VARMAX); - _parser.SetVarFactory(_addVar, this); - // Adding pi and e, the defaults are `_pi` and `_e` - _parser.DefineConst(_T("pi"), (mu::value_type)M_PI); - _parser.DefineConst(_T("e"), (mu::value_type)M_E); -} - -Func::Func(const Func& rhs): _mode(rhs._mode) -{ - _varbuf.reserve(VARMAX); - _parser.SetVarFactory(_addVar, this); - // Adding pi and e, the defaults are `_pi` and `_e` - _parser.DefineConst(_T("pi"), (mu::value_type)M_PI); - _parser.DefineConst(_T("e"), (mu::value_type)M_E); - setExpr(rhs.getExpr()); - vector vars = rhs.getVars(); - for (unsigned int ii = 0; ii < vars.size(); ++ii) - { - setVar(vars[ii], rhs.getVar(vars[ii])); - } -} - -Func& Func::operator=(const Func rhs) -{ - _clearBuffer(); - _mode = rhs._mode; - // Adding pi and e, the defaults are `_pi` and `_e` - _parser.DefineConst(_T("pi"), (mu::value_type)M_PI); - _parser.DefineConst(_T("e"), (mu::value_type)M_E); - setExpr(rhs.getExpr()); - vector vars = rhs.getVars(); - for (unsigned int ii = 0; ii < vars.size(); ++ii) - { - setVar(vars[ii], rhs.getVar(vars[ii])); - } - return *this; -} - -Func::~Func() -{ - - _clearBuffer(); -} - -void Func::_clearBuffer() -{ - _parser.ClearVar(); - for (unsigned int ii = 0; ii < _varbuf.size(); ++ii) - { - delete _varbuf[ii]; - } - _varbuf.clear(); -} - -void Func::_showError(mu::Parser::exception_type &e) const -{ - cout << "Error occurred in parser.\n" - << "Message: " << e.GetMsg() << "\n" - << "Formula: " << e.GetExpr() << "\n" - << "Token: " << e.GetToken() << "\n" - << "Position: " << e.GetPos() << "\n" - << "Error code: " << e.GetCode() << endl; -} -/** - Call-back to add variables to parser automatically. - */ -static double * _addVar(const char *name, void *data) -{ - Func* func = reinterpret_cast< Func * >(data); - double *ret = new double; - *ret = 0.0; - func->_varbuf.push_back(ret); - return ret; -} - -void Func::setExpr(string expr) -{ - _valid = false; - _x = NULL; - _y = NULL; - _z = NULL; - mu::varmap_type vars; - try - { - _parser.SetExpr(expr); - vars = _parser.GetUsedVar(); - } - catch (mu::Parser::exception_type &e) - { - _showError(e); - _clearBuffer(); - return; - } - mu::varmap_type::iterator v = vars.find("x"); - if (v != vars.end()) - { - _x = v->second; - } - else if (vars.size() >= 1) - { - v = vars.begin(); - _x = v->second; - } - v = vars.find("y"); - if (v != vars.end()) - { - _y = v->second; - } - else if (vars.size() >= 2) - { - v = vars.begin(); - ++v; - _y = v->second; - } - v = vars.find("z"); - if (v != vars.end()) - { - _z = v->second; - } - else if (vars.size() >= 3) - { - v = vars.begin(); - v++; - v++; - _z = v->second; - } - _valid = true; -} - -string Func::getExpr() const -{ - if (!_valid) - { - cout << "Error: Func::getExpr() - invalid parser state" << endl; - return ""; - } - return _parser.GetExpr(); -} - -/** - Set value of variable `name` -*/ -void Func::setVar(string name, double value) -{ - if (!_valid) - { - cout << "Error: Func::setVar() - invalid parser state" << endl; - return; - } - mu::varmap_type vars; - try - { - vars = _parser.GetVar(); - } - catch (mu::Parser::exception_type &e) - { - _valid = false; - _showError(e); - return; - } - mu::varmap_type::iterator v = vars.find(name); - if (v != vars.end()) - { - *v->second = value; - } - else - { - cout << "Error: no such variable " << name << endl; - } -} - -/** - Get value of variable `name` -*/ -double Func::getVar(string name) const -{ - if (!_valid) - { - cout << "Error: Func::getVar() - invalid parser state" << endl; - return 0.0; - } - try - { - const mu::varmap_type &vars = _parser.GetVar(); - mu::varmap_type::const_iterator v = vars.find(name); - if (v != vars.end()) - { - return *v->second; - } - else - { - cout << "Error: no such variable " << name << endl; - return 0.0; - } - } - catch (mu::Parser::exception_type &e) - { - _showError(e); - return 0.0; - } -} - -void Func::setX(double x) -{ - if (_x != NULL) - { - *_x = x; - } -} - -double Func::getX() const -{ - if (_x != NULL) - { - return *_x; - } - return 0.0; -} - -void Func::setY(double y) -{ - if (_y != NULL) - { - *_y = y; - } -} - -double Func::getY() const -{ - if (_y != NULL) - { - return *_y; - } - return 0.0; -} -void Func::setZ(double z) -{ - if (_z != NULL) - { - *_z = z; - } -} - -double Func::getZ() const -{ - if (_z != NULL) - { - return *_z; - } - return 0.0; -} - -void Func::setXY(double x, double y) -{ - if (_x != NULL) - { - *_x = x; - } - if (_y != NULL) - { - *_y = y; - } -} - -void Func::setXYZ(double x, double y, double z) -{ - if (_x != NULL) - { - *_x = x; - } - if (_y != NULL) - { - *_y = y; - } - if (_z != NULL) - { - *_z = z; - } -} - -void Func::setMode(unsigned int mode) -{ - _mode = mode; -} - -unsigned int Func::getMode() const -{ - return _mode; -} - -double Func::getValue() const -{ - double value = 0.0; - if (!_valid) - { - cout << "Error: Func::getValue() - invalid state" << endl; - return value; - } - try - { - value = _parser.Eval(); - } - catch (mu::Parser::exception_type &e) - { - _showError(e); - } - return value; -} - -double Func::getDerivative() const -{ - double value = 0.0; - if (!_valid) - { - cout << "Error: Func::getDerivative() - invalid state" << endl; - return value; - } - if (_x != NULL) - { - try - { - value = _parser.Diff(_x, *_x); - } - catch (mu::Parser::exception_type &e) - { - _showError(e); - } - } - return value; -} - - -vector Func::getVars() const -{ - vector< string > ret; - if (!_valid) - { - cout << "Error: Func::getVars() - invalid parser state" << endl; - return ret; - } - mu::varmap_type vars; - try - { - vars = _parser.GetVar(); - for (mu::varmap_type::iterator ii = vars.begin(); - ii != vars.end(); ++ii) - { - ret.push_back(ii->first); - } - } - catch (mu::Parser::exception_type &e) - { - _showError(e); - } - return ret; -} - -void Func::setVarValues(vector vars, vector vals) -{ - - if (vars.size() > vals.size() || !_valid) - { - return; - } - mu::varmap_type varmap = _parser.GetVar(); - for (unsigned int ii = 0; ii < vars.size(); ++ii) - { - mu::varmap_type::iterator v = varmap.find(vars[ii]); - if ( v != varmap.end()) - { - *v->second = vals[ii]; - } - } -} - -void Func::process(const Eref &e, ProcPtr p) -{ - if (!_valid) - { - return; - } - if (_mode & 1) - { - valueOut()->send(e, getValue()); - } - if (_mode & 2) - { - derivativeOut()->send(e, getDerivative()); - } -} - -void Func::reinit(const Eref &e, ProcPtr p) -{ - if (!_valid) - { - cout << "Error: Func::reinit() - invalid parser state. Will do nothing." << endl; - return; - } - if (moose::trim(_parser.GetExpr(), " \t\n\r").length() == 0) - { - cout << "Error: no expression set. Will do nothing." << endl; - setExpr("0.0"); - _valid = false; - } -} -// -// Func.cpp ends here diff --git a/builtins/Func.h b/builtins/Func.h deleted file mode 100644 index 4ca6d097..00000000 --- a/builtins/Func.h +++ /dev/null @@ -1,121 +0,0 @@ -/* Func.h --- - * - * Filename: Func.h - * Description: A simple function parser and evaluator class for MOOSE. - * Author: Subhasis Ray - * Maintainer: - * Created: Sat May 25 16:14:13 2013 (+0530) - * Version: - * Last-Updated: Sat Jun 1 19:04:31 2013 (+0530) - * By: subha - * Update #: 117 - * URL: - * Keywords: - * Compatibility: - * - */ - -/* Commentary: - * - * - * - */ - -/* Change log: - * - * - */ - -/* This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 3, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth - * Floor, Boston, MA 02110-1301, USA. - */ - -/* Code: */ - -#ifndef _FUNC_H -#define _FUNC_H - -#include "../external/muparser/include/muParser.h" -/** - Simple function parser and evaluator for MOOSE. This can take a mathematical - expression in standard C form and a list of variables values and - evaluate the results. - */ -static double *_addVar(const char *name, void *data); - -class Func -{ - public: - static const int VARMAX; - Func(); - Func(const Func& rhs); - ~Func(); - void setExpr(string expr); - string getExpr() const; - - - // get a list of variable identifiers. - // this is created by the parser - vector getVars() const; - void setVarValues(vector< string > vars, vector < double > vals); - - - // get/set the value of variable `name` - void setVar(string name, double value); - double getVar(string name) const; - - // get function eval result - double getValue() const; - - // get/set operation mode - void setMode(unsigned int mode); - unsigned int getMode() const; - - void setX(double value); - double getX() const; - - void setY(double value); - double getY() const; - - void setZ(double value); - double getZ() const; - - void setXY(double x, double y); - void setXYZ(double x, double y, double z); - - double getDerivative() const; - - Func& operator=(const Func rhs); - - void process(const Eref& e, ProcPtr p); - void reinit(const Eref& e, ProcPtr p); - - static const Cinfo * initCinfo(); - -protected: - friend double * _addVar(const char * name, void *data); - vector< double *> _varbuf; - mu::Parser _parser; - double *_x, *_y, *_z; - unsigned int _mode; - mutable bool _valid; - void _clearBuffer(); - void _showError(mu::Parser::exception_type &e) const; -}; -#endif - - - -/* Func.h ends here */ diff --git a/builtins/Function.cpp b/builtins/Function.cpp index 16ee175e..ca581a25 100644 --- a/builtins/Function.cpp +++ b/builtins/Function.cpp @@ -1,17 +1,25 @@ -// Description: Implementation of a wrapper around muParser. -// Author: Subhasis Ray -// Maintainer: Subhasis Ray +/*** + * Description: Wrapper around MooseParser. + * Author: Dilawar Singh , Subhasis Ray + * Maintainer: Dilawar Singh + */ + +#include #include "../basecode/header.h" -#include "../utility/utility.h" +#include "../basecode/global.h" +#include "../basecode/ElementValueFinfo.h" +#include "../basecode/LookupElementValueFinfo.h" + +#include "../utility/strutil.h" #include "../utility/numutil.h" -#include "../utility/print_function.hpp" +#include "../utility/testing_macros.hpp" + #include "../builtins/MooseParser.h" #include "Variable.h" #include "Function.h" -#include "../basecode/ElementValueFinfo.h" static const double TriggerThreshold = 0.0; @@ -33,28 +41,29 @@ static SrcFinfo1< double > *derivativeOut() static SrcFinfo1< double > *rateOut() { static SrcFinfo1< double > rateOut("rateOut", - "Value of time-derivative of the function for the current variable values"); + "Value of time-derivative of the function for the current variable values" + ); return &rateOut; } static SrcFinfo1< vector < double > *> *requestOut() { static SrcFinfo1< vector < double > * > requestOut( - "requestOut", - "Sends request for input variable from a field on target object"); + "requestOut", + "Sends request for input variable from a field on target object"); return &requestOut; } const Cinfo * Function::initCinfo() { - //////////////////////////////////////////////////////////// // Value fields - //////////////////////////////////////////////////////////// static ReadOnlyValueFinfo< Function, double > value( "value", "Result of the function evaluation with current variable values.", - &Function::getValue); + &Function::getValue + ); + static ReadOnlyValueFinfo< Function, double > derivative( "derivative", "Derivative of the function at given variable values. This is calulated" @@ -62,13 +71,17 @@ const Cinfo * Function::initCinfo() " at current value of" " independent variable. Note that unlike hand-calculated derivatives," " numerical derivatives are not exact.", - &Function::getDerivative); + &Function::getDerivative + ); + static ReadOnlyValueFinfo< Function, double > rate( "rate", "Derivative of the function at given variable values. This is computed" " as the difference of the current and previous value of the function" " divided by the time step.", - &Function::getRate); + &Function::getRate + ); + static ValueFinfo< Function, unsigned int > mode( "mode", "Mode of operation: \n" @@ -77,7 +90,9 @@ const Cinfo * Function::initCinfo() " 3: only rate (time derivative) will be sent out.\n" " anything else: all three, value, derivative and rate will be sent out.\n", &Function::setMode, - &Function::getMode); + &Function::getMode + ); + static ValueFinfo< Function, bool > useTrigger( "useTrigger", "When *false*, disables event-driven calculation and turns on " @@ -86,7 +101,9 @@ const Cinfo * Function::initCinfo() "Process-driven calculations. \n" "Defaults to *false*. \n", &Function::setUseTrigger, - &Function::getUseTrigger); + &Function::getUseTrigger + ); + static ValueFinfo< Function, bool > doEvalAtReinit( "doEvalAtReinit", "When *false*, disables function evaluation at reinit, and " @@ -95,13 +112,24 @@ const Cinfo * Function::initCinfo() "the computed value to any message targets. \n" "Defaults to *false*. \n", &Function::setDoEvalAtReinit, - &Function::getDoEvalAtReinit); + &Function::getDoEvalAtReinit + ); + + static ValueFinfo< Function, bool > allowUnknownVariable( + "allowUnknownVariable", + "When *false*, expression can only have ci, xi, yi and t." + "When set to *true*, expression can have arbitrary names." + "Defaults to *true*. \n", + &Function::setAllowUnknownVariable, + &Function::getAllowUnknowVariable + ); + static ElementValueFinfo< Function, string > expr( "expr", "Mathematical expression defining the function. The underlying parser\n" - "is muParser. In addition to the available functions and operators from\n" - "muParser, some more functions are added.\n" - "\nFunctions\n" + "is exprtk (https://archive.codeplex.com/?p=exprtk) . In addition to the\n" + "available functions and operators from exprtk, a few functions are added.\n" + "\nMajor Functions\n" "Name args explanation\n" "sin 1 sine function\n" "cos 1 cosine function\n" @@ -118,11 +146,10 @@ const Cinfo * Function::initCinfo() "log2 1 logarithm to the base 2\n" "log10 1 logarithm to the base 10\n" "log 1 logarithm to the base 10\n" - "ln 1 logarithm to base e (2.71828...)\n" + "ln 1 logarithm to base e (2.71828...)\n" "exp 1 e raised to the power of x\n" "sqrt 1 square root of a value\n" "sign 1 sign function -1 if x<0; 1 if x>0\n" - "rint 1 round to nearest integer\n" "abs 1 absolute value\n" "min var. min of all arguments\n" "max var. max of all arguments\n" @@ -135,24 +162,26 @@ const Cinfo * Function::initCinfo() " if seed = -1, a 'random' seed is created using either\n" " by random_device or by reading system clock\n" "\nOperators\n" - "Op meaning priority\n" - "= assignment -1\n" - "&& logical and 1\n" - "|| logical or 2\n" - "<= less or equal 4\n" - ">= greater or equal 4\n" - "!= not equal 4\n" - "== equal 4\n" - "> greater than 4\n" - "< less than 4\n" - "+ addition 5\n" - "- subtraction 5\n" - "* multiplication 6\n" - "/ division 6\n" - "^ raise x to the power of y 7\n" - "% floating point modulo 7\n" + "Op meaning priority\n" + "= assignment -1\n" + "&&,and logical and 1\n" + "||,or logical or 2\n" + "<= less or equal 4\n" + ">= greater or equal 4\n" + "!=,not not equal 4\n" + "== equal 4\n" + "> greater than 4\n" + "< less than 4\n" + "+ addition 5\n" + "- subtraction 5\n" + "* multiplication 6\n" + "/ division 6\n" + "^ raise x to the power of y 7\n" + "% floating point modulo 7\n" "\n" - "?: if then else operator C++ style syntax\n", + "?: if then else operator C++ style syntax\n" + "\n\n" + "For more information see https://archive.codeplex.com/?p=exprtk \n", &Function::setExpr, &Function::getExpr ); @@ -166,59 +195,69 @@ const Cinfo * Function::initCinfo() static FieldElementFinfo< Function, Variable > inputs( "x", - "Input variables to the function. These can be passed via messages.", + "Input variables (indexed) to the function. These can be passed via messages.", Variable::initCinfo(), &Function::getVar, &Function::setNumVar, &Function::getNumVar ); + static LookupValueFinfo < Function, string, double > constants( "c", "Constants used in the function. These must be assigned before" " specifying the function expression.", &Function::setConst, - &Function::getConst); + &Function::getConst + ); + + static LookupValueFinfo< Function, string, unsigned int > xindex( + "xindex", + "Return the index of given variable. It can be used with field `x`", + &Function::setVarIndex, + &Function::getVarIndex + ); static ReadOnlyValueFinfo< Function, vector < double > > y( "y", "Variable values received from target fields by requestOut", - &Function::getY); + &Function::getY + ); static ValueFinfo< Function, string > independent( "independent", "Index of independent variable. Differentiation is done based on this. Defaults" " to the first assigned variable.", &Function::setIndependent, - &Function::getIndependent); + &Function::getIndependent + ); /////////////////////////////////////////////////////////////////// // Shared messages /////////////////////////////////////////////////////////////////// static DestFinfo process( "process", - "Handles process call, updates internal time stamp.", - new ProcOpFunc< Function >( &Function::process ) ); + "Handles process call, updates internal time stamp.", + new ProcOpFunc< Function >( &Function::process ) + ); + static DestFinfo reinit( "reinit", - "Handles reinit call.", - new ProcOpFunc< Function >( &Function::reinit ) ); + "Handles reinit call.", + new ProcOpFunc< Function >( &Function::reinit ) + ); + static Finfo* processShared[] = { &process, &reinit }; static SharedFinfo proc( "proc", - "This is a shared message to receive Process messages " - "from the scheduler objects." - "The first entry in the shared msg is a MsgDest " - "for the Process operation. It has a single argument, " - "ProcInfo, which holds lots of information about current " - "time, thread, dt and so on. The second entry is a MsgDest " - "for the Reinit operation. It also uses ProcInfo. ", - processShared, sizeof( processShared ) / sizeof( Finfo* ) - ); - /* - static DestFinfo trigger( "trigger", - "Handles trigger input. Argument is timestamp of event. This is " - "compatible with spike events as well as chemical ones. ", - new OpFunc1< Function, double >( &Function::trigger ) ); - */ + "This is a shared message to receive Process messages " + "from the scheduler objects." + "The first entry in the shared msg is a MsgDest " + "for the Process operation. It has a single argument, " + "ProcInfo, which holds lots of information about current " + "time, thread, dt and so on. The second entry is a MsgDest " + "for the Reinit operation. It also uses ProcInfo. ", + processShared, sizeof( processShared ) / sizeof( Finfo* ) + ); + static Finfo *functionFinfos[] = { @@ -228,9 +267,11 @@ const Cinfo * Function::initCinfo() &mode, &useTrigger, &doEvalAtReinit, + &allowUnknownVariable, &expr, &numVars, &inputs, + &xindex, &constants, &independent, &proc, @@ -243,185 +284,161 @@ const Cinfo * Function::initCinfo() static string doc[] = { "Name", "Function", - "Author", "Subhasis Ray", + "Author", "Subhasis Ray/Dilawar Singh", "Description", - "General purpose function calculator using real numbers.\n" - "It can parse mathematical expression defining a function and evaluate" - " it and/or its derivative for specified variable values." - "You can assign expressions of the form::\n" - "\n" - "f(c0, c1, ..., cM, x0, x1, ..., xN, y0,..., yP ) \n" - "\n" - " where `ci`'s are constants and `xi`'s and `yi`'s are variables." - - "The constants must be defined before setting the expression and" - " variables are connected via messages. The constants can have any" - " name, but the variable names must be of the form x{i} or y{i}" - " where i is increasing integer starting from 0.\n" - " The variables can be input from other moose objects." - " Such variables must be named `x{i}` in the expression and the source" - " field is connected to Function.x[i]'s `input` destination field.\n" - " In case the input variable is not available as a source field, but is" - " a value field, then the value can be requested by connecting the" - " `requestOut` message to the `get{Field}` destination on the target" - " object. Such variables must be specified in the expression as y{i}" - " and connecting the messages should happen in the same order as the" - " y indices.\n" - " This class handles only real numbers (C-double). Predefined constants" - " are: pi=3.141592..., e=2.718281..." - }; - - static Dinfo< Function > dinfo; - static Cinfo functionCinfo("Function", - Neutral::initCinfo(), - functionFinfos, - sizeof(functionFinfos) / sizeof(Finfo*), - &dinfo, - doc, - sizeof(doc)/sizeof(string)); - return &functionCinfo; + R""""(General purpose function calculator using real numbers. -} - -static const Cinfo * functionCinfo = Function::initCinfo(); +It can parse mathematical expression defining a function and evaluate it and/or +its derivative for specified variable values. You can assign expressions of +the form:: -Function::Function(): _t(0.0), _valid(false), _numVar(0), _lastValue(0.0), - _value(0.0), _rate(0.0), _mode(1), - _useTrigger( false ), _doEvalAtReinit( false ), _stoich(0) -{ - _parser.SetVarFactory(_functionAddVar, this); - _independent = "x0"; - //extendMuParser( ); + f(t, x, y, z, var, p, q, Ca, CaMKII) - // Adding this default expression by default to avoid complains from GUI - try - { - _parser.SetExpr("0"); - } - catch (moose::Parser::exception_type &e) - { - _showError(e); - _clearBuffer(); - return; - } - _valid = true; -} +NOTE: `t` represents time. You CAN NOT use to for any other purpose. -Function::Function(const Function& rhs): - _numVar(rhs._numVar), - _lastValue(rhs._lastValue), - _value(rhs._value), _rate(rhs._rate), - _mode(rhs._mode), - _useTrigger( rhs._useTrigger), - _stoich(nullptr) -{ - static Eref er; - _independent = rhs._independent; +The constants must be defined before setting the expression and variables are +connected via messages. The variables can be input from other moose objects. +Connected variables named `xyz` in the expression and the source field is +connected to Function[xyz]'s `input` destination field. - _parser.SetVarFactory(_functionAddVar, this); - //extendMuParser( ); +In case the input variable is not available as a source field, but is a value +field, then the value can be requested by connecting the `requestOut` message +to the `get{Field}` destination on the target object. Such variables must be +specified in the expression as y{i} and connecting the messages should happen +in the same order as the y indices. - // Copy the constants - moose::Parser::valmap_type cmap = rhs._parser.GetConst(); - if (cmap.size()) - { - moose::Parser::valmap_type::const_iterator item = cmap.begin(); - for (; item!=cmap.end(); ++item) - { - _parser.DefineConst(item->first, item->second); - } - } + This class handles only real numbers (C-double). Predefined constants + are: pi=3.141592..., e=2.718281...)"""" + }; + static Dinfo< Function > dinfo; + static Cinfo functionCinfo("Function", + Neutral::initCinfo(), + functionFinfos, + sizeof(functionFinfos) / sizeof(Finfo*), + &dinfo, + doc, + sizeof(doc)/sizeof(string)); + return &functionCinfo; - setExpr(er, rhs.getExpr( er )); - // Copy the values from the var pointers in rhs - assert(_varbuf.size() == rhs._varbuf.size()); - for (unsigned int ii = 0; ii < rhs._varbuf.size(); ++ii) - { - _varbuf[ii]->value = rhs._varbuf[ii]->value; - } - assert(_pullbuf.size() == rhs._pullbuf.size()); - for (unsigned int ii = 0; ii < rhs._pullbuf.size(); ++ii) - { - *_pullbuf[ii] = *(rhs._pullbuf[ii]); - } } -Function& Function::operator=(const Function rhs) -{ - static Eref er; - _clearBuffer(); - _mode = rhs._mode; - _lastValue = rhs._lastValue; - _value = rhs._value; - _rate = rhs._rate; - _independent = rhs._independent; - // Adding pi and e, the defaults are `_pi` and `_e` - _parser.DefineConst(_T("pi"), (moose::Parser::value_type)M_PI); - _parser.DefineConst(_T("e"), (moose::Parser::value_type)M_E); - // Copy the constants - moose::Parser::valmap_type cmap = rhs._parser.GetConst(); - if (cmap.size()) - { - moose::Parser::valmap_type::const_iterator item = cmap.begin(); - for (; item!=cmap.end(); ++item) +static const Cinfo * functionCinfo = Function::initCinfo(); + +Function::Function(): + valid_(false) + , numVar_(0) + , lastValue_(0.0) + , value_(0.0) + , rate_(0.0) + , mode_(1) + , useTrigger_(false) + , doEvalAtReinit_(false) + , allowUnknownVar_(true) + , t_(0.0) + , independent_("t") + , stoich_(nullptr) + , parser_(shared_ptr(new moose::MooseParser())) +{ +} + +// Careful: This is a critical function. Also since during zombiefication, deep +// copy is expected. Merely copying the parser won't work. +Function& Function::operator=(const Function& rhs) +{ + // protect from self-assignment. + if( this == &rhs) + return *this; + + valid_ = rhs.valid_; + numVar_ = rhs.numVar_; + lastValue_ = rhs.lastValue_; + value_ = rhs.value_; + mode_ = rhs.mode_; + useTrigger_ = rhs.useTrigger_; + doEvalAtReinit_ = rhs.doEvalAtReinit_; + allowUnknownVar_ = rhs.allowUnknownVar_; + t_ = rhs.t_; + rate_ = rhs.rate_; + + // Deep copy; create new Variable and constant to link with new parser. + // Zombification requires it. DO NOT just copy the object/pointer of + // MooseParser. + xs_.clear(); + ys_.clear(); + varIndex_.clear(); + parser_->ClearAll(); + if(rhs.parser_->GetExpr().size() > 0) + { + // These are alreay indexed. So its OK to add them by name. + for(auto x: rhs.xs_) { - _parser.DefineConst(item->first, item->second); + xs_.push_back(shared_ptr(new Variable(x->getName()))); + varIndex_[x->getName()] = xs_.size()-1; } - } - // Copy the values from the var pointers in rhs - setExpr(er, rhs.getExpr( er )); - assert(_varbuf.size() == rhs._varbuf.size()); - for (unsigned int ii = 0; ii < rhs._varbuf.size(); ++ii) - { - _varbuf[ii]->value = rhs._varbuf[ii]->value; - } - assert(_pullbuf.size() == rhs._pullbuf.size()); - for (unsigned int ii = 0; ii < rhs._pullbuf.size(); ++ii) - { - *_pullbuf[ii] = *(rhs._pullbuf[ii]); + // Add all the Ys now. + for(size_t i=0; i < rhs.ys_.size(); i++) + ys_.push_back(shared_ptr(new double(0.0))); + parser_->LinkVariables(xs_, ys_, &t_); + parser_->SetExpr(rhs.parser_->GetExpr()); } return *this; } Function::~Function() { - _clearBuffer(); } -// do not know what to do about Variables that have already been -// connected by message. -void Function::_clearBuffer() +/* --------------------------------------------------------------------------*/ +/** + * @Synopsis Add a xn (index n). Make sure to add all missing i's such at we have all + * xi s from x0 to xn. + * + * FIXME: DO NOT CALL THIS FUNCTION if there are non xi in the xs_. + * + * @Param index + */ +/* ----------------------------------------------------------------------------*/ +void Function::addXByIndex(const unsigned int index) { - _numVar = 0; - _parser.ClearVar(); - for (unsigned int ii = 0; ii < _varbuf.size(); ++ii) - { - if ( _varbuf[ii] ) - { - delete _varbuf[ii]; - } - } - _varbuf.clear(); - for (unsigned int ii = 0; ii < _pullbuf.size(); ++ii) + // We have only xi's in xs_. + string name = 'x'+to_string(index); + if(symbolExists(name)) + return; + + if(index >= xs_.size()) { - if ( _pullbuf[ii] ) + for(size_t i = xs_.size(); i <= index; i++) { - delete _pullbuf[ii]; + xs_.push_back(shared_ptr(new Variable('x'+to_string(i)))); + varIndex_[name] = xs_.size()-1; } } - _pullbuf.clear(); + parser_->DefineVar(name, xs_[index]->ref()); + varIndex_[name] = xs_.size()-1; + numVar_ = varIndex_.size(); +} + +void Function::addXByName(const string& name) +{ + if(symbolExists(name)) + return; + xs_.push_back(shared_ptr(new Variable(name))); + parser_->DefineVar(name, xs_.back()->ref()); + varIndex_[name] = xs_.size()-1; + numVar_ = varIndex_.size(); } -void Function::_showError(moose::Parser::exception_type &e) const +void Function::addY(const unsigned int index) { - cerr << "Error occurred in parser.\n" - << "Message: " << e.GetMsg() << endl; + string name = 'y'+to_string(index); + if(index >= ys_.size()) + ys_.resize(index+1); + ys_[index].reset(new double(0.0)); + parser_->DefineVar(name, ys_[index].get()); } /** - Call-back to add variables to parser automatically. - We use different storage for constants and variables. Variables are stored in a vector of Variable object pointers. They must have the name x{index} where index is any non-negative integer. Note that @@ -433,389 +450,418 @@ void Function::_showError(moose::Parser::exception_type &e) const If the name starts with anything other than `x` or `y`, then it is taken to be a named constant, which must be set before any expression or variables and error is thrown. - - NOTE: this is called not on setting expression but on first attempt - at evaluation of the same, i.e. when you access `value` of the - Function object. */ -double * _functionAddVar(const char *name, void *data) +void Function::addVariable(const string& name) { - Function* function = reinterpret_cast< Function * >(data); - double * ret = NULL; - string strname(name); - // Names starting with x are variables, everything else is constant. - if (name[0] == 'x') + VarType vtype = getVarType(name); + + if(XVAR_INDEX == vtype) { - int index = atoi(strname.substr(1).c_str()); - if ((unsigned)index >= function->_varbuf.size()) - { - function->_varbuf.resize(index+1, 0); - for (int ii = 0; ii <= index; ++ii) - { - if (function->_varbuf[ii] == 0) - { - function->_varbuf[ii] = new Variable(); - } - } - function->_numVar = function->_varbuf.size(); - } - ret = &(function->_varbuf[index]->value); + addXByIndex(stoul(name.substr(1))); + return; } - else if (name[0] == 'y') + if(XVAR_NAMED == vtype) { - int index = atoi(strname.substr(1).c_str()); - if ((unsigned)index >= function->_pullbuf.size()) - { - function->_pullbuf.resize(index+1, 0 ); - for (int ii = 0; ii <= index; ++ii) - { - if (function->_pullbuf[ii] == 0) - { - function->_pullbuf[ii] = new double(); - } - } - } - ret = function->_pullbuf[index]; + addXByName(name); + return; } - else if (strname == "t") + + if(YVAR == vtype) { - ret = &function->_t; + addY(stoul(name.substr(1))); + return; } - else + + if (TVAR == vtype) + { + parser_->DefineVar("t", &t_); + return; + } + + if(CONSTVAR == vtype) { - MOOSE_WARN( "Got an undefined symbol: " << strname << ".\n" - << "Variables must be named xi, yi, where i is integer index." - << " You must define the constants beforehand using LookupField c: c[name]" - " = value" - ); - throw moose::Parser::exception_type("Undefined constant."); + // These are constants. Don't add them. We don't know there value just + // yet. + return; } - return ret; + throw runtime_error(name + " is not supported or invalid name."); } -/** - This function is for automatically adding variables when setVar - messages are connected. - - There are two ways new variables can be created : - - (1) When the user sets the expression, muParser calls _functionAddVar to - get the address of the storage for each variable name in the - expression. - - (2) When the user connects a setVar message to a Variable. ?? - - This is called by Variable::addMsgCallback - which is unused. - */ -unsigned int Function::addVar() +void Function::callbackAddSymbol(const string& name) { - return 0; + // Add only if doesn't exist. + if(varIndex_.find(name) == varIndex_.end()) + addXByName(name); } - -void Function::setExpr(const Eref& eref, string expr) + +/* --------------------------------------------------------------------------*/ +/** + * @Synopsis Return the type of Variable. + * + * @Param name + * + * @Returns + */ +/* ----------------------------------------------------------------------------*/ +VarType Function::getVarType(const string& name) const { - this->innerSetExpr( eref, expr ); // Refer to the virtual function here. + if(regex_match(name, regex("x\\d+"))) + return XVAR_INDEX; + if(regex_match(name, regex("y\\d+"))) + return YVAR; + if(regex_match(name, regex("c\\d+"))) + return CONSTVAR; + if(name == "t") + return TVAR; + return XVAR_NAMED; } -// Virtual function, this does the work. -void Function::innerSetExpr(const Eref& eref, string expr) +/* --------------------------------------------------------------------------*/ +/** + * @Synopsis Assign an expression to the parser. Calls innerSetExpr to do the + * task. + * + * @Param eref + * @Param expression + */ +/* ----------------------------------------------------------------------------*/ +void Function::setExpr(const Eref& eref, const string expression) { - _valid = false; - _clearBuffer(); - _varbuf.resize(_numVar); - // _pullbuf.resize(_num - moose::Parser::varmap_type vars; - try + string expr = moose::trim(expression); + if(expr.empty()) { - _parser.SetExpr(expr); + // MOOSE_WARN("Empty expression."); + return; } - catch (moose::Parser::exception_type &e) + + if(valid_ && expr == parser_->GetExpr()) { - cerr << "Error setting expression on: " << eref.objId().path() << endl; - _showError(e); - _clearBuffer(); + MOOSE_WARN( "No changes in the expression."); return; } - // Force variable creation right away. Otherwise numVar does not - // get set properly + try { - _parser.Eval(); - _valid = true; + valid_ = innerSetExpr(eref, expr); } - catch (moose::Parser::exception_type &e) + catch(moose::Parser::ParserException& e) { - _showError(e); + valid_ = false; + cerr << "Error setting expression on: " << eref.objId().path() << endl; + cerr << "\tExpression: '" << expr << "'" << endl; + cerr << e.GetMsg() << endl; } } +/* --------------------------------------------------------------------------*/ +/** + * @Synopsis Set expression in the parser. This function support two mode: + * with dynamic lookup and without it. When `dynamicLookup_` is set to true, + * unknown variables are created at the compile time. Otherwise, an error is + * raised. + * + * @Param eref + * @Param expr Expression to set. + * @Param dynamicLookup Weather to allow unknown variables in the expression. + * (default to true in moose>=4.0.0) + * + * @Returns True if compilation was successful. + */ +/* ----------------------------------------------------------------------------*/ +bool Function::innerSetExpr(const Eref& eref, const string expr) +{ + ASSERT_FALSE(expr.empty(), "Empty expression not allowed here."); + + // NOTE: Don't clear the expression here. Sometime the user extend the + // expression by calling this function agian. For example: + // + // >>> f.expr = 'x0+x2' + // >>> # connect x0 and x2 + // >>> f.expr += '+ 100+y0' + // >>> # connect more etc. + + // First, set the xi, yi and t to the symbol table. + set xs; + set ys; + moose::MooseParser::findXsYs(expr, xs, ys); + for(auto &x : xs) addXByIndex(std::stoul(x.substr(1))); + for(auto &y : ys) addY(std::stoul(y.substr(1))); + addVariable("t"); + + if(allowUnknownVar_) + return parser_->SetExprWithUnknown(expr, this); + + // If we are here that mean we have only xi, yi and t in the expression. + // Find all variables x\d+ or y\d+ etc, and add them. + return parser_->SetExpr(expr); +} + string Function::getExpr( const Eref& e ) const { - if (!_valid) + if (!valid_) { cout << "Error: " << e.objId().path() << "::getExpr() - invalid parser state" << endl; + cout << "\tExpression was : " << parser_->GetExpr() << endl; return ""; } - return _parser.GetExpr(); + return parser_->GetExpr(); } void Function::setMode(unsigned int mode) { - _mode = mode; + mode_ = mode; } unsigned int Function::getMode() const { - return _mode; + return mode_; } void Function::setUseTrigger(bool useTrigger ) { - _useTrigger = useTrigger; + useTrigger_ = useTrigger; } bool Function::getUseTrigger() const { - return _useTrigger; + return useTrigger_; } void Function::setDoEvalAtReinit(bool doEvalAtReinit ) { - _doEvalAtReinit = doEvalAtReinit; + doEvalAtReinit_ = doEvalAtReinit; } bool Function::getDoEvalAtReinit() const { - return _doEvalAtReinit; + return doEvalAtReinit_; +} + +void Function::setAllowUnknownVariable(bool value ) +{ + allowUnknownVar_ = value; +} + +bool Function::getAllowUnknowVariable() const +{ + return allowUnknownVar_; } + double Function::getValue() const { - double value = 0.0; - if (!_valid) - { - cout << "Error: Function::getValue() - invalid state" << endl; - return value; - } - try - { - value = _parser.Eval(); - } - catch (moose::Parser::exception_type &e) - { - _showError(e); - } - return value; + return parser_->Eval( ); } + double Function::getRate() const { - if (!_valid) + if (!valid_) { cout << "Error: Function::getValue() - invalid state" << endl; } - return _rate; + return rate_; } void Function::setIndependent(string var) { - _independent = var; + independent_ = var; } string Function::getIndependent() const { - return _independent; + return independent_; } vector< double > Function::getY() const { - vector < double > ret(_pullbuf.size()); + vector < double > ret(ys_.size()); for (unsigned int ii = 0; ii < ret.size(); ++ii) - { - ret[ii] = *_pullbuf[ii]; - } + ret[ii] = *ys_[ii]; return ret; } double Function::getDerivative() const { double value = 0.0; - if (!_valid) + if (!valid_) { cout << "Error: Function::getDerivative() - invalid state" << endl; return value; } - moose::Parser::varmap_type variables = _parser.GetVar(); - moose::Parser::varmap_type::const_iterator item = variables.find(_independent); - if (item != variables.end()) - { - try - { - value = _parser.Diff(item->second, *(item->second)); - } - catch (moose::Parser::exception_type &e) - { - _showError(e); - } - } - return value; + return parser_->Derivative(independent_); } void Function::setNumVar(const unsigned int num) { - _clearBuffer(); - for (unsigned int ii = 0; ii < num; ++ii) - _functionAddVar( ("x"+std::to_string(ii)).c_str(), this); + // Deprecated: numVar has no effect. MOOSE can infer number of variables + // from the expression. + numVar_ = num; } unsigned int Function::getNumVar() const { - return _numVar; + return numVar_; } void Function::setVar(unsigned int index, double value) { - cout << "varbuf[" << index << "]->setValue(" << value << ")\n"; - if (index < _varbuf.size()) - { - _varbuf[index]->setValue(value); - } - else + if(index < xs_.size()) { - cerr << "Function: index " << index << " out of bounds." << endl; + xs_[index]->setValue(value); + return; } + MOOSE_WARN("Function: index " << index << " out of bounds."); } -Variable * Function::getVar(unsigned int ii) +Variable* Function::getVar(unsigned int ii) { - static Variable dummy; - if ( ii < _varbuf.size()) + static Variable dummy("DUMMY"); + if(ii >= xs_.size()) { - return _varbuf[ii]; + MOOSE_WARN("No active variable for index " << ii); + return &dummy; } - cout << "Warning: Function::getVar: index: " - << ii << " is out of range: " - << _varbuf.size() << endl; - return &dummy; + return xs_[ii].get(); } void Function::setConst(string name, double value) { - _parser.DefineConst(name, value); + parser_->DefineConst(name.c_str(), value); } double Function::getConst(string name) const { - auto cmap = _parser.GetConst(); - if (cmap.size()) + moose::Parser::varmap_type cmap = parser_->GetConst(); + if (! cmap.empty() ) { - auto it = cmap.find(name); + moose::Parser::varmap_type::const_iterator it = cmap.find(name); if (it != cmap.end()) + { return it->second; + } } return 0; } +void Function::setVarIndex(string name, unsigned int val) +{ + cerr << "This should not be used." << endl; +} + +unsigned int Function::getVarIndex(string name) const +{ + if(varIndex_.find(name) == varIndex_.end()) + return numeric_limits::max(); + return varIndex_.at(name); +} + +bool Function::symbolExists(const string& name) const +{ + return varIndex_.find(name) != varIndex_.end(); +} + void Function::process(const Eref &e, ProcPtr p) { - if (!_valid) + if(! valid_) { + cerr << "Warn: Invalid parser state. " << endl; return; } - vector < double > databuf; + + // Update values of incoming variables. + vector databuf; requestOut()->send(e, &databuf); - for (unsigned int ii = 0; - (ii < databuf.size()) && (ii < _pullbuf.size()); - ++ii) - { - *_pullbuf[ii] = databuf[ii]; - } - _t = p->currTime; - _value = getValue(); - _rate = (_value - _lastValue) / p->dt; - if ( _useTrigger && _value < TriggerThreshold ) + + t_ = p->currTime; + value_ = getValue(); + rate_ = (value_ - lastValue_) / p->dt; + + for (size_t ii = 0; (ii < databuf.size()) && (ii < ys_.size()); ++ii) + *ys_[ii] = databuf[ii]; + + if ( useTrigger_ && value_ < TriggerThreshold ) { - _lastValue = _value; + lastValue_ = value_; return; } - switch (_mode) - { - case 1: + + if( 1 == mode_ ) { - valueOut()->send(e, _value); + valueOut()->send(e, value_); + lastValue_ = value_; return; } - case 2: + if( 2 == mode_ ) { derivativeOut()->send(e, getDerivative()); + lastValue_ = value_; return; } - case 3: + if( 3 == mode_ ) { - rateOut()->send(e, _rate); + rateOut()->send(e, rate_); + lastValue_ = value_; return; } - default: + else { - valueOut()->send(e, _value); + valueOut()->send(e, value_); derivativeOut()->send(e, getDerivative()); - rateOut()->send(e, _rate); + rateOut()->send(e, rate_); + lastValue_ = value_; return; } - } - _lastValue = _value; } void Function::reinit(const Eref &e, ProcPtr p) { - if (!_valid) + if (! (valid_ || parser_->GetExpr().empty())) { - cout << "Error: Function::reinit() - invalid parser state. Will do nothing." << endl; + cout << "Error: " << e.objId().path() << "::reinit() - invalid parser state" << endl; + cout << " Expr: '" << parser_->GetExpr() << "'" << endl; return; } - if (moose::trim(_parser.GetExpr(), " \t\n\r").length() == 0) - { - cout << "Error: no expression set. Will do nothing." << endl; - setExpr(e, "0.0"); - _valid = false; - } - _t = p->currTime; - if (_doEvalAtReinit) - { - _lastValue = _value = getValue(); - } + + t_ = p->currTime; + + if (doEvalAtReinit_) + lastValue_ = value_ = getValue(); else + lastValue_ = value_ = 0.0; + + rate_ = 0.0; + + if (1 == mode_) { - _lastValue = _value = 0.0; - } - _rate = 0.0; - switch (_mode) - { - case 1: - { - valueOut()->send(e, _value); - break; + valueOut()->send(e, value_); + return; } - case 2: + if( 2 == mode_ ) { derivativeOut()->send(e, 0.0); - break; + return; } - case 3: + if( 3 == mode_ ) { - rateOut()->send(e, _rate); - break; + rateOut()->send(e, rate_); + return; } - default: + else { - valueOut()->send(e, _value); + valueOut()->send(e, value_); derivativeOut()->send(e, 0.0); - rateOut()->send(e, _rate); - break; - } + rateOut()->send(e, rate_); + return; } } -// Function.cpp ends here + +void Function::clearAll() +{ + xs_.clear(); + ys_.clear(); + varIndex_.clear(); +} diff --git a/builtins/Function.h b/builtins/Function.h index 8834b51c..1d88f65c 100644 --- a/builtins/Function.h +++ b/builtins/Function.h @@ -1,41 +1,55 @@ -// Description: +// Function.h --- +// Description: moose.Function class. // Author: Subhasis Ray +// Maintainer: Dilawar Singh +// Version: See git logs. -#ifndef _MOOSE_FUNCTION_H_ -#define _MOOSE_FUNCTION_H_ +#ifndef FUNCTIONH_ +#define FUNCTIONH_ +#include +class Variable; +class Eref; +class Cinfo; + +namespace moose { + class MooseParser; +}; -/** - Simple function parser and evaluator for MOOSE. This can take a mathematical - expression in standard C form and a list of variables values and - evaluate the results. - */ -double *_functionAddVar(const char *name, void *data); -class Function +// Symbol types. +enum VarType {XVAR_INDEX, XVAR_NAMED, YVAR, TVAR, CONSTVAR}; + +class Function { public: static const int VARMAX; Function(); - Function(const Function& rhs); + + // Destructor. ~Function(); - virtual void innerSetExpr( const Eref& e, string expr); - void setExpr( const Eref& e, string expr); - string getExpr( const Eref& e ) const; + + // copy operator. + Function& operator=(const Function& rhs); + + static const Cinfo * initCinfo(); + + void setExpr(const Eref& e, const string expr); + bool innerSetExpr(const Eref& e, const string expr); + + string getExpr(const Eref& e) const; // get a list of variable identifiers. - // this is created by the parser vector getVars() const; - void setVarValues(vector< string > vars, vector < double > vals); - + void setVarValues(vector vars, vector vals); // get/set the value of variable `name` void setVar(unsigned int index, double value); - Variable * getVar(unsigned int ii); + + Variable* getVar(unsigned int ii); // get function eval result double getValue() const; - double getRate() const; // get/set operation mode @@ -50,20 +64,26 @@ class Function void setDoEvalAtReinit(bool doEvalAtReinit); bool getDoEvalAtReinit() const; + void setAllowUnknownVariable(bool value); + bool getAllowUnknowVariable() const; + void setNumVar(unsigned int num); unsigned int getNumVar() const; void setConst(string name, double value); double getConst(string name) const; + void setVarIndex(string name, unsigned int val); + unsigned int getVarIndex(string name) const; + void setIndependent(string index); string getIndependent() const; - vector < double > getY() const; + vector getY() const; double getDerivative() const; - Function& operator=(const Function rhs); + void findXsYs( const string& expr, vector& vars ); unsigned int addVar(); /* void dropVar(unsigned int msgLookup); */ @@ -71,37 +91,56 @@ class Function void process(const Eref& e, ProcPtr p); void reinit(const Eref& e, ProcPtr p); - static const Cinfo * initCinfo(); + // This is also used as callback. + void addVariable(const string& name); + + // Add unknown variable. + void callbackAddSymbol(const string& name); + + bool symbolExists(const string& name) const; + + void addXByIndex(const unsigned int index); + void addXByName(const string& name); + + void addY(const unsigned int index); + + VarType getVarType(const string& name) const; + + void clearAll(); protected: - friend double * _functionAddVar(const char * name, void *data); - double _t; // local storage for current time - mutable bool _valid; - unsigned int _numVar; - double _lastValue; - double _value; - double _rate; - unsigned int _mode; - bool _useTrigger; - bool _doEvalAtReinit; + + bool valid_; + unsigned int numVar_; + double lastValue_; + double value_; + double rate_; + unsigned int mode_; + bool useTrigger_; + bool doEvalAtReinit_; + bool allowUnknownVar_; + + double t_; // local storage for current time + string independent_; // To take derivative. // this stores variables received via incoming messages, identifiers of // the form x{i} are included in this - vector _varbuf; + vector> xs_; + + // Keep the index of x's. + map varIndex_; // this stores variable values pulled by sending request. identifiers of // the form y{i} are included in this - vector< double * > _pullbuf; - map< string, double *> _constbuf; // for constants - string _independent; // index of independent variable + vector> ys_; + map> consts_; - MooseParser _parser; + // Used by kinetic solvers when this is zombified. + void* stoich_; - void _clearBuffer(); - void _showError(moose::Parser::exception_type &e) const; + // pointer to the MooseParser + shared_ptr parser_; - // Used by kinetic solvers when this is zombified. - char* _stoich; }; -#endif +#endif /* end of include guard: FUNCTIONH_ */ diff --git a/builtins/InputVariable.cpp b/builtins/InputVariable.cpp index ac018da2..3e4c9a8e 100644 --- a/builtins/InputVariable.cpp +++ b/builtins/InputVariable.cpp @@ -98,7 +98,8 @@ void InputVariable::setOwner( NSDFWriter * owner) void InputVariable::epSetValue( const Eref& eref, double value) { - if (owner_){ + if (owner_) + { owner_->setInput(eref.fieldIndex(), value); } } diff --git a/builtins/MooseParser.cpp b/builtins/MooseParser.cpp index b8cdcb74..0e73ee34 100644 --- a/builtins/MooseParser.cpp +++ b/builtins/MooseParser.cpp @@ -1,18 +1,419 @@ /*** - * Description: Class MooseParser. + * Description: Moose Parser class, wraps exprtk. * - * Created: 2019-05-30 + * Created: 2018-08-25 * Author: Dilawar Singh * Organization: NCBS Bangalore - * License: MIT License */ +#include +#include +#include +#include + +#include "../basecode/global.h" +#include "../basecode/header.h" + +#include "../utility/testing_macros.hpp" +#include "../utility/print_function.hpp" +#include "../utility/strutil.h" + +#include "../builtins/Variable.h" +#include "../builtins/Function.h" #include "MooseParser.h" -MooseParser::MooseParser() -{} +using namespace std; + +namespace moose +{ + +MooseParser::MooseParser(): valid_(true) +{ + Parser::symbol_table_t symbolTable; + symbolTable.add_function("ln", MooseParser::Ln); + symbolTable.add_function("rand", MooseParser::Rand); // between 0 and 1 + symbolTable.add_function("rnd", MooseParser::Rand); // between 0 and 1 + symbolTable.add_function("srand", MooseParser::SRand); + symbolTable.add_function("rand2", MooseParser::Rand2); + symbolTable.add_function("srand2", MooseParser::SRand2); + symbolTable.add_function("fmod", MooseParser::Fmod); + expression_.register_symbol_table(symbolTable); +} MooseParser::~MooseParser() -{} +{ +} + +/*----------------------------------------------------------------------------- + * User defined function here. + *-----------------------------------------------------------------------------*/ +double MooseParser::Ln( double v ) +{ + return std::log(v); +} + +double MooseParser::Rand( ) +{ + return moose::mtrand(); +} + +double MooseParser::SRand( double seed = -1 ) +{ + if( seed >= 0 ) + moose::mtseed( (size_t) seed ); + return moose::mtrand(); +} + +double MooseParser::Rand2( double a, double b ) +{ + return moose::mtrand( a, b ); +} + +double MooseParser::SRand2( double a, double b, double seed = -1 ) +{ + if( seed >= 0 ) + moose::mtseed( (size_t) seed ); + return moose::mtrand( a, b ); +} + +double MooseParser::Fmod( double a, double b ) +{ + return fmod(a, b); +} + + +/*----------------------------------------------------------------------------- + * Get/Set + *-----------------------------------------------------------------------------*/ +Parser::symbol_table_t& MooseParser::GetSymbolTable(const size_t nth) +{ + return expression_.get_symbol_table(nth); +} + +const Parser::symbol_table_t& MooseParser::GetSymbolTable(const size_t nth) const +{ + return expression_.get_symbol_table(nth); +} + +double MooseParser::GetVarValue(const string& name) const +{ + return GetSymbolTable().get_variable(name)->value(); +} + +void MooseParser::PrintSymbolTable(void) const +{ + stringstream ss; + auto symbTable = GetSymbolTable(); + vector> vars; + auto n = symbTable.get_variable_list(vars); + ss << "More Information:\nTotal variables " << n << "."; + for (auto i : vars) + ss << "\t" << i.first << "=" << i.second << " " << symbTable.get_variable(i.first)->ref(); + cerr << ss.str() << endl; +} + +void MooseParser::findAllVars( const string& expr, set& vars, const string& pattern) +{ + const regex pat(pattern); + smatch sm; + string temp(expr); + while(regex_search(temp, sm, pat)) + { + vars.insert(sm.str()); + temp = sm.suffix(); + } +} + +/*----------------------------------------------------------------------------- + * Other function. + *-----------------------------------------------------------------------------*/ +bool MooseParser::DefineVar( const string varName, double* const val) +{ + // Use in copy assignment. + if( GetSymbolTable().is_variable(varName)) + GetSymbolTable().remove_variable(varName); + return GetSymbolTable().add_variable(varName, *val); +} + +void MooseParser::DefineConst( const string& constName, const double value ) +{ + const_map_[constName] = value; + GetSymbolTable().add_constant(constName, value); +} + +void MooseParser::DefineFun1( const string& funcName, double (&func)(double) ) +{ + // Add a function. This function currently handles only one argument + // function. + num_user_defined_funcs_ += 1; + GetSymbolTable().add_function( funcName, func ); +} + + +/* --------------------------------------------------------------------------*/ +/** + * @Synopsis EXPRTK does not have && and || but have 'and' and 'or' symbol. + * Replace && with 'and' and '||' with 'or'. + * + * @Param user_expr + * + * @Returns + */ +/* ----------------------------------------------------------------------------*/ +string MooseParser::Reformat( const string user_expr ) +{ + string expr( user_expr ); + + // Replate || with 'or' + moose::str_replace_all( expr, "||", " or " ); + // Replace && with 'and' + moose::str_replace_all( expr, "&&", " and " ); + + // Trickt business: Replace ! with not but do not change != + moose::str_replace_all( expr, "!=", "@@@" ); // placeholder + moose::str_replace_all( expr, "!", " not " ); + moose::str_replace_all( expr, "@@@", "!=" ); // change back @@@ to != + + return expr; +} + + +/* --------------------------------------------------------------------------*/ +/** + * @Synopsis Find all x\d+ and y\d+ in the experssion. + * + * @Param expr + * @Param vars + */ +/* ----------------------------------------------------------------------------*/ +void MooseParser::findXsYs( const string& expr, set& xs, set& ys ) +{ + findAllVars( expr, xs, "x\\d+"); + findAllVars( expr, ys, "y\\d+" ); +} + +/* --------------------------------------------------------------------------*/ +/** + * @Synopsis Set expression on parser. + * + * @Param user_expr + * + * @Returns + */ +/* ----------------------------------------------------------------------------*/ +bool MooseParser::SetExpr( const string& user_expr) +{ + ASSERT_FALSE( user_expr.empty(), "Empty expression" ); + expr_ = Reformat(user_expr); + return CompileExpr(); +} + +bool MooseParser::SetExprWithUnknown(const string& user_expr, Function* func) +{ + ASSERT_FALSE( user_expr.empty(), "Empty expression" ); + expr_ = Reformat(user_expr); + return CompileExprWithUnknown(func); +} + +/* --------------------------------------------------------------------------*/ +/** + * @Synopsis Compile a given expression. + * + * @Returns Return true if successful, throws exception if compilation fails. + * Exception includes a detailed diagnostic. + */ +/* ----------------------------------------------------------------------------*/ +bool MooseParser::CompileExpr() +{ + // User should make sure that symbol table has been setup. Do not raise + // exception here. User can set expression again. + // GCC specific + ASSERT_FALSE(expr_.empty(), __func__ << ": Empty expression not allowed here"); + + Parser::parser_t parser; + + // This option is very useful when setting expression which don't have + // standard naming of variables. For example, A + B etc. + bool res = parser.compile(expr_, expression_); + if(! res) + { + std::stringstream ss; + ss << "Failed to parse '" << expr_ << "' :" << endl; + for (std::size_t i = 0; i < parser.error_count(); ++i) + { + Parser::error_t error = parser.get_error(i); + ss << "Error[" << i << "] Position: " << error.token.position + << " Type: [" << exprtk::parser_error::to_str(error.mode) + << "] Msg: " << error.diagnostic << endl; + + // map is + auto symbTable = GetSymbolTable(); + vector> vars; + auto n = symbTable.get_variable_list(vars); + ss << "More Information:\nTotal variables " << n << "."; + for (auto i : vars) + ss << "\t" << i.first << "=" << i.second << " " << symbTable.get_variable(i.first)->ref(); + ss << endl; + } + // Throw the error, this is handled in callee. + throw moose::Parser::exception_type(ss.str()); + } + return res; +} + +bool MooseParser::CompileExprWithUnknown(Function* func) +{ + ASSERT_FALSE(expr_.empty(), __func__ << ": Empty expression not allowed here"); + + // User should make sure that symbol table has been setup. + Parser::parser_t parser; + parser.enable_unknown_symbol_resolver(); + + // This option is very useful when setting expression which don't have + // standard naming of variables. For example, A + B etc. This call to parse + // will collect all variables in a symbol table. + bool res = parser.compile(expr_, expression_); + + // Get all symbols and create Variable() for them. Note that now the + // previos symbol table and compiled expressions are invalid. + auto symbTable = GetSymbolTable(); + vector> vars; + symbTable.get_variable_list(vars); + + // note: Don't clear the symbol table. Constants will also get cleared + // which we don't want. + // We want continuity in xi's to make sure the OLD api still works. For + // example, if x5+x1 is the expression, we have to make sure that x0, x1, + // ..., x5 are present in symbol table. + for(auto& v: vars) + { + // We have already made sure, before calling this function that xi, yi + // ci, and t are set up. Only XVAR_NAMED variables need to be added. + if(func->getVarType(v.first) == XVAR_NAMED) + { + GetSymbolTable().remove_variable(v.first, true); + func->callbackAddSymbol(v.first); + } + } + + // Compile again with updated symbol table. + // parser.disable_unknown_symbol_resolver(); + res = parser.compile(expr_, expression_); + if(! res) + { + std::stringstream ss; + ss << "Failed to parse '" << expr_ << "' :" << endl; + for (std::size_t i = 0; i < parser.error_count(); ++i) + { + Parser::error_t error = parser.get_error(i); + ss << "Error[" << i << "] Position: " << error.token.position + << " Type: [" << exprtk::parser_error::to_str(error.mode) + << "] Msg: " << error.diagnostic << endl; + + // map is + auto symbTable = GetSymbolTable(); + vector> vars; + auto n = symbTable.get_variable_list(vars); + ss << "More Information:\nTotal variables " << n << "."; + for (auto i : vars) + ss << "\t" << i.first << "=" << i.second << " " << symbTable.get_variable(i.first)->ref(); + ss << endl; + } + // Throw the error, this is handled in callee. + throw moose::Parser::exception_type(ss.str()); + } + return res; +} + + +double MooseParser::Derivative(const string& name, size_t nth) const +{ + if(nth > 3) + { + cout << "Error: " << nth << "th derivative is not supported." << endl; + return 0.0; + } + if(nth == 3) + return exprtk::third_derivative(expression_, name); + if(nth == 2) + return exprtk::second_derivative(expression_, name); + return exprtk::derivative(expression_, name); +} + +double MooseParser::Eval(bool check) const +{ + if(! valid_) + { + cout << "Warn: Invalid parser state." << endl; + return 0.0; + } + + if(expr_.empty()) + { + cout << "warn: Expr is empty " << endl; + return 0.0; + } + + // PrintSymbolTable(); + // Make sure that no symbol is unknown at this point. Else emit error. The + // Function::reinit must take of it. + return expression_.value(); +} + + +double MooseParser::Diff( const double a, const double b ) const +{ + return a-b; +} + +Parser::varmap_type MooseParser::GetConst( ) const +{ + return const_map_; +} + +void MooseParser::ClearVariables( ) +{ + GetSymbolTable().clear_variables(); +} + +void MooseParser::ClearAll( ) +{ + ClearVariables(); +} + +void MooseParser::Reset( ) +{ + expression_.release(); +} + +const string MooseParser::GetExpr( ) const +{ + return expr_; +} + +void MooseParser::LinkVariables(vector& xs, vector& ys, double* t) +{ + for(size_t i = 0; i < xs.size(); i++) + DefineVar('x'+to_string(i), xs[i]->ref()); + + for (size_t i = 0; i < ys.size(); i++) + DefineVar('y'+to_string(i), ys[i]); + + DefineVar("t", t); +} + +void MooseParser::LinkVariables(vector>& xs, vector>& ys, double* t) +{ + for(size_t i = 0; i < xs.size(); i++) + DefineVar('x'+to_string(i), xs[i]->ref()); + + for (size_t i = 0; i < ys.size(); i++) + DefineVar('y'+to_string(i), ys[i].get()); + + DefineVar("t", t); +} + + +} // namespace moose. diff --git a/builtins/MooseParser.h b/builtins/MooseParser.h index cea2c0ae..9b8d2220 100644 --- a/builtins/MooseParser.h +++ b/builtins/MooseParser.h @@ -1,56 +1,138 @@ /*** - * Description: MooseParser class. + * Description: Parser class. Similar API as muParser. * - * Created: 2019-05-30 - * Author: Dilawar Singh * Organization: NCBS Bangalore - * License: MIT License + * + * License: See the LICENSE.md file. */ -#ifndef MOOSEPARSER_H -#define MOOSEPARSER_H +#ifndef PARSER_H +#define PARSER_H +#include +#include +#include +#include #include +#include + +#define exprtk_enabled_debugging 0 +#define exprtk_disable_comments 1 +#include "../external/exprtk/exprtk.hpp" + using namespace std; -#include "../external/muparser/include/muParser.h" +class Variable; +class Function; + +namespace moose +{ +namespace Parser +{ + +// ExprTk types. +typedef exprtk::symbol_table symbol_table_t; +typedef exprtk::expression expression_t; +typedef exprtk::parser parser_t; +typedef exprtk::parser_error::type error_t; -namespace moose { - namespace Parser { +struct ParserException : public std::exception +{ + ParserException( const string msg ) : msg_(msg) { ; } - struct ParserException : public std::exception - { - ParserException( const std::string msg ) : msg_(msg) { ; } + string GetMsg() + { + return msg_; + } - string GetMsg() - { - return msg_; - } + string msg_; +}; - string msg_; - }; +typedef ParserException exception_type; +typedef map varmap_type; +} // namespace Parser - typedef ParserException exception_type; +class MooseParser +{ +public: + MooseParser(); + ~MooseParser(); + void PrintSymbolTable() const; - // These should be same for both muparser and EXPRTK parser. - typedef std::map valmap_type; - typedef std::map varmap_type; - typedef double value_type; + /*----------------------------------------------------------------------------- + * Set/Get + *-----------------------------------------------------------------------------*/ + Parser::symbol_table_t& GetSymbolTable(const size_t nth=0); + const Parser::symbol_table_t& GetSymbolTable(const size_t nth=0) const; - } // namespace Parser + /*----------------------------------------------------------------------------- + * User interface. + *-----------------------------------------------------------------------------*/ + bool DefineVar( const string varName, double* const v ); -} // namespace moose + void DefineConst( const string& cname, const double val ); -class MooseParser : public mu::Parser -{ - public: - MooseParser(); - ~MooseParser(); + void DefineFun1( const string& funcName, double (&func)(double) ); + + bool SetExpr( const string& expr); + bool SetExprWithUnknown( const string& expr, Function* func); + + bool CompileExpr(); + bool CompileExprWithUnknown(Function* func); + + // Reformat the expression to meet TkExpr. + string Reformat( const string user_expr ); + + static void findAllVars( const string& expr, set& vars, const string& start ); + static void findXsYs(const string& expr, set& xs, set& ys); + + void LinkVariables(vector& xs_, vector& ys_, double* t); + void LinkVariables(vector>& xs_, vector>& ys_, double* t); + + double Eval(bool check=false) const; + + double Derivative(const string& name, size_t nth=1) const; + + double Diff( const double a, const double b) const; + + Parser::varmap_type GetConst( ) const; + double GetVarValue(const string& name) const; + + + void ClearVariables( ); + void ClearAll( ); + void Reset( ); + + const string GetExpr( ) const; + + /*----------------------------------------------------------------------------- + * User defined function of parser. + *-----------------------------------------------------------------------------*/ + static double Ln(double v); + static double Rand( ); + static double SRand( double seed ); + static double Rand2( double a, double b ); + static double SRand2( double a, double b, double seed ); + static double Fmod( double a, double b ); + +private: + + /* data */ + string expr_; + double value=0.0; + + Parser::varmap_type const_map_; + + Parser::expression_t expression_; /* expression type */ + + size_t num_user_defined_funcs_ = 0; + + bool valid_; - private: - /* data */ }; -#endif /* end of include guard: MOOSEPARSER_H */ +} // namespace moose. + +#endif /* end of include guard: PARSER_H */ diff --git a/builtins/Table.h b/builtins/Table.h index 2d59f67d..22b55a3f 100644 --- a/builtins/Table.h +++ b/builtins/Table.h @@ -10,6 +10,10 @@ #ifndef _TABLE_H #define _TABLE_H + +#if USE_BOOST_FILESYSTEM +#include +#endif /* ----- USE_BOOST_FILESYSTEM ----- */ #include /** diff --git a/builtins/Variable.cpp b/builtins/Variable.cpp index e68e08ed..3c11570d 100644 --- a/builtins/Variable.cpp +++ b/builtins/Variable.cpp @@ -1,6 +1,6 @@ // Description: // Author: Subhasis Ray -// Maintainer: +// Maintainer: Dilawar Singh // Created: Fri May 30 19:56:06 2014 (+0530) #include "../basecode/header.h" @@ -14,20 +14,22 @@ const Cinfo * Variable::initCinfo() "value", "Variable value", &Variable::setValue, - &Variable::getValue); + &Variable::getValue + ); static DestFinfo input( "input", "Handles incoming variable value.", - new EpFunc1< Variable, double >( &Variable::epSetValue )); + new EpFunc1< Variable, double >( &Variable::setValue ) + ); static Finfo * variableFinfos[] = { &value, &input }; - static string doc[] = - { + + static string doc[] = { "Name", "Variable", "Author", "Subhasis Ray", "Description", "Variable for storing double values. This is used in Function class." @@ -36,17 +38,16 @@ const Cinfo * Variable::initCinfo() static Dinfo< Variable > dinfo; static Cinfo variableCinfo("Variable", - Neutral::initCinfo(), - variableFinfos, - sizeof(variableFinfos) / sizeof(Finfo*), - &dinfo, - doc, - sizeof(doc) / sizeof(string), - true // is FieldElement, not to be created directly - ); + Neutral::initCinfo(), + variableFinfos, + sizeof(variableFinfos) / sizeof(Finfo*), + &dinfo, + doc, + sizeof(doc) / sizeof(string), + true // is FieldElement, not to be created directly + ); return & variableCinfo; } static const Cinfo * variableCinfo = Variable::initCinfo(); - diff --git a/builtins/Variable.h b/builtins/Variable.h index 99cb05d0..0ad03c10 100644 --- a/builtins/Variable.h +++ b/builtins/Variable.h @@ -1,93 +1,70 @@ // Variable.h --- -// // Filename: Variable.h // Description: // Author: Subhasis Ray -// Maintainer: +// Maintainer: Dilawar Singh // Created: Fri May 30 19:37:24 2014 (+0530) -// Version: -// Last-Updated: -// By: -// Update #: 0 -// URL: -// Keywords: -// Compatibility: -// -// - -// Commentary: -// -// Field element for variables in Function class. -// -// - -// Change log: -// -// -// -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; see the file COPYING. If not, write to -// the Free Software Foundation, Inc., 51 Franklin Street, Fifth -// Floor, Boston, MA 02110-1301, USA. -// -// - -// Code: + #ifndef _VARIABLE_H #define _VARIABLE_H -/** - This class is used as FieldElement in Function. It is used as named + +#include + +class ObjId; +class Eref; +class Cinfo; + +using namespace std; + +/** This class is used as FieldElement in Function. It is used as named variable of type double. */ class Variable { + public: - Variable():value(0.0) - { - }; - Variable(const Variable& rhs): value(rhs.value) + + Variable(string name=""): name_(name), value_(0.0) + {}; + + Variable(const Variable& rhs): name_(rhs.name_), value_(rhs.value_) { ; } - virtual ~Variable(){}; + ~Variable() {}; void setValue(double v) { - value = v; + value_ = v; } - virtual void epSetValue(const Eref & e, double v) + void setValue(const Eref & e, double v) { - value = v; + value_ = v; } double getValue() const { - return value; + return value_; + } + + string getName() const + { + return name_; } - void addMsgCallback(const Eref& e, const string& finfoName, ObjId msg, unsigned int msgLookup); + double* ref() + { + return &value_; + } static const Cinfo * initCinfo(); - double value; +private: + string name_{"NONAME"}; + double value_{0.0}; }; -#endif - - +#endif // include guard. -// -// Variable.h ends here diff --git a/cmake_modules/FindGSL.cmake b/cmake/FindGSL.cmake similarity index 97% rename from cmake_modules/FindGSL.cmake rename to cmake/FindGSL.cmake index b45aca3a..e07c063b 100644 --- a/cmake_modules/FindGSL.cmake +++ b/cmake/FindGSL.cmake @@ -55,13 +55,13 @@ IF(WIN32) ELSE(WIN32) # UNIX - IF(GSL_USE_STATIC_LIBRARIES) + if((GSL_USE_STATIC_LIBRARIES) OR ($ENV{GSL_USE_STATIC_LIBRARIES})) SET(GSL_LIB_NAMES libgsl.a) SET(GSL_CBLAS_LIB_NAMES libgslcblas.a) - ELSE(GSL_USE_STATIC_LIBRARIES) + else() SET(GSL_LIB_NAMES gsl) SET(GSL_CBLAS_LIB_NAMES gslcblas) - ENDIF( ) + endif( ) if(GSL_ROOT_DIR) FIND_LIBRARY(GSL_LIB diff --git a/cmake_modules/FindLIBSBML.cmake b/cmake/FindLIBSBML.cmake similarity index 100% rename from cmake_modules/FindLIBSBML.cmake rename to cmake/FindLIBSBML.cmake diff --git a/cmake_modules/FindLibXML2.cmake b/cmake/FindLibXML2.cmake similarity index 100% rename from cmake_modules/FindLibXML2.cmake rename to cmake/FindLibXML2.cmake diff --git a/cmake_modules/FindPyQt.py b/cmake/FindPyQt.py similarity index 100% rename from cmake_modules/FindPyQt.py rename to cmake/FindPyQt.py diff --git a/cmake_modules/FindPyQt4.cmake b/cmake/FindPyQt4.cmake similarity index 100% rename from cmake_modules/FindPyQt4.cmake rename to cmake/FindPyQt4.cmake diff --git a/cmake_modules/FindReadline.cmake b/cmake/FindReadline.cmake similarity index 100% rename from cmake_modules/FindReadline.cmake rename to cmake/FindReadline.cmake diff --git a/cmake_modules/FindSIP.cmake b/cmake/FindSIP.cmake similarity index 100% rename from cmake_modules/FindSIP.cmake rename to cmake/FindSIP.cmake diff --git a/cmake_modules/FindSIP.py b/cmake/FindSIP.py similarity index 100% rename from cmake_modules/FindSIP.py rename to cmake/FindSIP.py diff --git a/cmake_modules/FindSphinx.cmake b/cmake/FindSphinx.cmake similarity index 100% rename from cmake_modules/FindSphinx.cmake rename to cmake/FindSphinx.cmake diff --git a/cmake_modules/FindTermcap.cmake b/cmake/FindTermcap.cmake similarity index 100% rename from cmake_modules/FindTermcap.cmake rename to cmake/FindTermcap.cmake diff --git a/cmake_modules/GetGitRevisionDescription.cmake b/cmake/GetGitRevisionDescription.cmake similarity index 100% rename from cmake_modules/GetGitRevisionDescription.cmake rename to cmake/GetGitRevisionDescription.cmake diff --git a/cmake_modules/GetGitRevisionDescription.cmake.in b/cmake/GetGitRevisionDescription.cmake.in similarity index 100% rename from cmake_modules/GetGitRevisionDescription.cmake.in rename to cmake/GetGitRevisionDescription.cmake.in diff --git a/cmake_modules/GetRevision.cmake b/cmake/GetRevision.cmake similarity index 100% rename from cmake_modules/GetRevision.cmake rename to cmake/GetRevision.cmake diff --git a/cmake_modules/Pinfo.plist b/cmake/Pinfo.plist similarity index 100% rename from cmake_modules/Pinfo.plist rename to cmake/Pinfo.plist diff --git a/cmake_modules/SIPMacros.cmake b/cmake/SIPMacros.cmake similarity index 100% rename from cmake_modules/SIPMacros.cmake rename to cmake/SIPMacros.cmake diff --git a/cmake_modules/FindNumPy.cmake b/cmake_modules/FindNumPy.cmake deleted file mode 100644 index 285b4730..00000000 --- a/cmake_modules/FindNumPy.cmake +++ /dev/null @@ -1,94 +0,0 @@ -# - Find the NumPy libraries -# This module finds if NumPy is installed, and sets the following variables -# indicating where it is. -# -# TODO: Update to provide the libraries and paths for linking npymath lib. -# -# NUMPY_FOUND - was NumPy found -# NUMPY_VERSION - the version of NumPy found as a string -# NUMPY_VERSION_MAJOR - the major version number of NumPy -# NUMPY_VERSION_MINOR - the minor version number of NumPy -# NUMPY_VERSION_PATCH - the patch version number of NumPy -# NUMPY_VERSION_DECIMAL - e.g. version 1.6.1 is 10601 -# NUMPY_INCLUDE_DIRS - path to the NumPy include files - -#============================================================================ -# Copyright 2012 Continuum Analytics, Inc. -# -# MIT License -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files -# (the "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -# OTHER DEALINGS IN THE SOFTWARE. -# -#============================================================================ - -# Finding NumPy involves calling the Python interpreter - -message( STATUS "Using ${PYTHON_EXECUTABLE} to locate numpy" ) -execute_process(COMMAND ${PYTHON_EXECUTABLE} -c - "import numpy as n; print(n.__version__); print(n.get_include());" - RESULT_VARIABLE _NUMPY_SEARCH_SUCCESS - OUTPUT_VARIABLE _NUMPY_VALUES_OUTPUT - ERROR_VARIABLE _NUMPY_ERROR_VALUE - OUTPUT_STRIP_TRAILING_WHITESPACE -) - -if(NOT _NUMPY_SEARCH_SUCCESS MATCHES 0) - if(NumPy_FIND_REQUIRED) - message(FATAL_ERROR - "NumPy import failure:\n${_NUMPY_ERROR_VALUE}") - endif() - set(NUMPY_FOUND FALSE) - return() -endif() - -# Convert the process output into a list -string(REGEX REPLACE ";" "\\\\;" _NUMPY_VALUES ${_NUMPY_VALUES_OUTPUT}) -string(REGEX REPLACE "\n" ";" _NUMPY_VALUES ${_NUMPY_VALUES}) -# Just in case there is unexpected output from the Python command. -list(GET _NUMPY_VALUES -2 NUMPY_VERSION) -list(GET _NUMPY_VALUES -1 NUMPY_INCLUDE_DIRS) - -string(REGEX MATCH "^[0-9]+\\.[0-9]+\\.[0-9]+" _VER_CHECK "${NUMPY_VERSION}") -if("${_VER_CHECK}" STREQUAL "") - # The output from Python was unexpected. Raise an error always - # here, because we found NumPy, but it appears to be corrupted somehow. - message(FATAL_ERROR - "Requested version and include path from NumPy, got instead:\n${_NUMPY_VALUES_OUTPUT}\n") - return() -endif() - -# Make sure all directory separators are '/' -string(REGEX REPLACE "\\\\" "/" NUMPY_INCLUDE_DIRS ${NUMPY_INCLUDE_DIRS}) - -# Get the major and minor version numbers -string(REGEX REPLACE "\\." ";" _NUMPY_VERSION_LIST ${NUMPY_VERSION}) -list(GET _NUMPY_VERSION_LIST 0 NUMPY_VERSION_MAJOR) -list(GET _NUMPY_VERSION_LIST 1 NUMPY_VERSION_MINOR) -list(GET _NUMPY_VERSION_LIST 2 NUMPY_VERSION_PATCH) -string(REGEX MATCH "[0-9]*" NUMPY_VERSION_PATCH ${NUMPY_VERSION_PATCH}) -math(EXPR NUMPY_VERSION_DECIMAL - "(${NUMPY_VERSION_MAJOR} * 10000) + (${NUMPY_VERSION_MINOR} * 100) + ${NUMPY_VERSION_PATCH}") - -find_package_message(NUMPY - "Found NumPy: version \"${NUMPY_VERSION}\" ${NUMPY_INCLUDE_DIRS}" - "${NUMPY_INCLUDE_DIRS}${NUMPY_VERSION}") - -set(NUMPY_FOUND TRUE) - diff --git a/devel/CMakeLists.txt b/devel/CMakeLists.txt new file mode 100644 index 00000000..4ea7b7fa --- /dev/null +++ b/devel/CMakeLists.txt @@ -0,0 +1,14 @@ +# Replicate Travis-CI building using docker +add_custom_target(travis + COMMAND docker build -t bhallalab/travis:latest + -f ${CMAKE_CURRENT_SOURCE_DIR}/docker/travis/Dockerfile . + COMMENT "Replicating Travis-CI building using Docker." + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + VERBATIM) + +add_custom_target(centos + COMMAND docker build -t bhallalab/centos:latest + -f ${CMAKE_CURRENT_SOURCE_DIR}/docker/centos/Dockerfile . + COMMENT "Building moose on centos" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + VERBATIM) diff --git a/devel/_conftest.py b/devel/_conftest.py new file mode 100644 index 00000000..a7fb4021 --- /dev/null +++ b/devel/_conftest.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +# Top level file to run and generate report. + +__author__ = "Dilawar Singh" +__copyright__ = "Copyright 2019-, Dilawar Singh" +__maintainer__ = "Dilawar Singh" +__email__ = "dilawars@ncbs.res.in" + +import pytest +try: + import reload +except ImportError: + from importlib import reload + +@pytest.fixture(scope="module", autouse=True) +def reload_moose(): + import moose + print('reloading moose') + for p in ['/model', '/library']: + if moose.exists(p): + moose.delete(p) + # If someone has changed the clock-ticks then we need to reset them. + # And relaod just to make sure and other values are initialized. + reload(moose) diff --git a/devel/docker/centos/Dockerfile b/devel/docker/centos/Dockerfile new file mode 100644 index 00000000..5e019d67 --- /dev/null +++ b/devel/docker/centos/Dockerfile @@ -0,0 +1,26 @@ +FROM centos:7 +MAINTAINER Dilawar Singh + +# Install dependencies. +RUN yum -y update && yum -y install epel-release && yum -y update \ + && yum -y clean all +RUN yum install -y git cmake3 gcc gcc-c++ make \ + python3 python3-devel python3-setuptools python3-numpy \ + && yum -y clean all +RUN yum install -y gsl-devel && yum -y clean all +# These are required to run tests. +RUN yum install -y python3-matplotlib python3-scipy python3-numpy && yum -y clean all +RUN yum install -y centos-release-scl && yum -y clean all +RUN yum install -y devtoolset-8 && yum -y clean all +RUN ln -s /usr/bin/cmake3 /usr/bin/cmake +RUN ln -s /usr/bin/ctest3 /usr/bin/ctest +WORKDIR /root + +# Run docker build from project ROOT. +COPY . moose-core +RUN python3 -m pip install matplotlib scipy sympy --user + +# enable devtoolset before building. +SHELL [ "/usr/bin/scl", "enable", "devtoolset-8" ] +RUN cd moose-core && python3 setup.py build test install +CMD ["/usr/bin/python3", "-c", "'import moose;moose.test()'"] diff --git a/devel/docker/centos/Makefile b/devel/docker/centos/Makefile new file mode 100644 index 00000000..63af01a5 --- /dev/null +++ b/devel/docker/centos/Makefile @@ -0,0 +1,18 @@ +NAME:=dilawars/centos-moose +VERSION:=$(shell date +%Y.%m.%d) + +PROJECT_ROOT_DIR:=(PWD)/../.. + +all : build + +build : Dockerfile + cd ../../ && docker build -t $(NAME):$(VERSION) -f $(PWD)/Dockerfile . + cd ../../ && docker build -t $(NAME):latest -f $(PWD)/Dockerfile . + +upload : + docker push $(NAME):$(VERSION) + docker push $(NAME):latest + +run : + docker run -ti $(NAME):$(VERSION) bash + diff --git a/devel/docker/opensuse/Dockerfile b/devel/docker/opensuse/Dockerfile new file mode 100644 index 00000000..ce2b68c9 --- /dev/null +++ b/devel/docker/opensuse/Dockerfile @@ -0,0 +1,18 @@ +FROM opensuse/leap +MAINTAINER Dilawar Singh + +# Install dependencies. +RUN zypper install -y git cmake gcc gcc-c++ make \ + python3 python3-devel python3-setuptools python3-numpy-devel \ + && rm -rf /var/cache/zypp/packages/* +RUN zypper install -y gsl-devel \ + && rm -rf /var/cache/zypp/packages/* +# These are required to run tests. +RUN zypper install -y python3-matplotlib python3-networkx graphviz python3-scipy \ + && rm -rf /var/cache/zypp/packages/* +WORKDIR /home/root +# RUN git clone https://github.com/dilawar/moose-core -b devel +# Run docker build from outside +COPY . moose-core +RUN cd moose-core && python3 setup.py build test install +CMD ["/usr/bin/python3", "-c", "'import moose;moose.test()'"] diff --git a/devel/docker/opensuse/Makefile b/devel/docker/opensuse/Makefile new file mode 100644 index 00000000..ab068eb7 --- /dev/null +++ b/devel/docker/opensuse/Makefile @@ -0,0 +1,18 @@ +NAME:=dilawars/centos-moose +VERSION:=$(shell date +%Y.%m.%d) + +PROJECT_ROOT_DIR:=(PWD)/../.. + +all : build + +build : Dockerfile + cd ../../ && docker build -t $(NAME):$(VERSION) -f $(PWD)/Dockerfile . + cd ../../ && docker build -t $(NAME):latest -f $(PWD)/Dockerfile . + +upload : + docker push $(NAME):$(VERSION) + docker push $(NAME):latest + +run : + docker run $(NAME):$(VERSION) /bin/bash -c "python3 -c 'import moose; moose.test()'" + diff --git a/devel/docker/travis/Dockerfile b/devel/docker/travis/Dockerfile new file mode 100644 index 00000000..acd4d351 --- /dev/null +++ b/devel/docker/travis/Dockerfile @@ -0,0 +1,22 @@ +FROM ubuntu:18.04 +MAINTAINER Dilawar Singh + +ENV DEBIAN_FRONTEND=noninteractive + +# Install dependencies. +RUN apt update && apt install -y cmake gcc g++ make valgrind \ + libboost-all-dev libgsl-dev libblas-dev liblapack-dev \ + python3-pip python-pip \ + python3-numpy python-numpy python3-matplotlib python-matplotlib \ + python-tk python3-tk \ + python-setuptools python3-setuptools \ + python-dev python3-dev \ + && rm -rf /var/lib/apt/lists/* + +RUN python2 -m pip --no-cache-dir install pyneuroml python-libsbml +RUN python3 -m pip --no-cache-dir install pyneuroml python-libsbml +WORKDIR /root +RUN ls -ltrah +COPY . moose-core/ +RUN ls -ltarh +RUN cd moose-core && rm -rf .git && ./.ci/travis_build_linux.sh diff --git a/devel/docker/travis/Makefile b/devel/docker/travis/Makefile new file mode 100644 index 00000000..8447a2bd --- /dev/null +++ b/devel/docker/travis/Makefile @@ -0,0 +1,20 @@ +NAME:=dilawars/moose-travis +VERSION:=$(shell date +"%Y%m%d") + +PWD:=$(shell pwd) +PROJECT_ROOT_DIR:=$(PWD)/../../.. +DOCKERFILE:=$(PWD)/Dockerfile + +all : build + +build : Dockerfile + cd $(PROJECT_ROOT_DIR) && docker build -t $(NAME):$(VERSION) -f $(DOCKERFILE) . + cd $(PROJECT_ROOT_DIR) && docker build -t $(NAME):latest -f $(DOCKERFILE) . + +upload : + docker push $(NAME):$(VERSION) + docker push $(NAME):latest + +run : + docker run -it $(NAME):latest bash + diff --git a/devel/docker/wheel/Dockerfile b/devel/docker/wheel/Dockerfile new file mode 100644 index 00000000..6d8401ea --- /dev/null +++ b/devel/docker/wheel/Dockerfile @@ -0,0 +1,23 @@ +FROM quay.io/pypa/manylinux2010_x86_64 + +ARG PYPI_PASSWORD + +MAINTAINER Dilawar Singh +ENV PATH=/usr/local/bin:$PATH +RUN yum update -y +RUN yum install -y cmake3 wget curl && yum clean all +RUN ln -s /usr/bin/cmake3 /usr/local/bin/cmake +RUN ln -s /usr/bin/ctest3 /usr/local/bin/ctest +RUN curl -O https://ftp.gnu.org/gnu/gsl/gsl-2.4.tar.gz \ + && tar xvf gsl-2.4.tar.gz \ + && cd gsl-2.4 \ + && CFLAGS=-fPIC ./configure --enable-static && make $MAKEOPTS \ + && make install \ + && cd .. +RUN yum install -y git vim && yum clean all +RUN git config --global user.name 'Dilawar Singh' \ + && git config --global user.email 'dilawar.s.rajput@gmail.com' \ + && git clone https://github.com/dilawar/vim ~/.vim -b minimal +WORKDIR /root +COPY ./build_wheels.sh /root +COPY ./test_and_upload.sh /root diff --git a/devel/docker/wheel/Makefile b/devel/docker/wheel/Makefile new file mode 100644 index 00000000..8644fa88 --- /dev/null +++ b/devel/docker/wheel/Makefile @@ -0,0 +1,16 @@ +VERSION := 3.2.dev$(shell date +"%Y%m%d") + +all : wheels + +DOCKERFILE:="bhallalab/python-wheels" + +wheels : ./Dockerfile + docker build -t $(DOCKERFILE):$(VERSION) . + docker build -t $(DOCKERFILE):latest . + +upload: + docker push $(DOCKERFILE):$(VERSION) + docker push $(DOCKERFILE):latest + +run: + docker run -it $(DOCKERFILE):latest bash diff --git a/devel/docker/wheel/README.md b/devel/docker/wheel/README.md new file mode 100644 index 00000000..d34861f9 --- /dev/null +++ b/devel/docker/wheel/README.md @@ -0,0 +1,3 @@ +This docker image can be used to build pymoose wheels. + +This image is based on manylinux_2010 https://www.python.org/dev/peps/pep-0571/. diff --git a/devel/docker/wheel/build_wheels.sh b/devel/docker/wheel/build_wheels.sh new file mode 100755 index 00000000..25656905 --- /dev/null +++ b/devel/docker/wheel/build_wheels.sh @@ -0,0 +1,67 @@ +#!/bin/sh + +set -e + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +NPROC=$(cat /proc/cpuinfo | awk '/^processor/{print $3}' | wc -l) +NUM_WORKERS=$((NPROC-1)) + +if [ "$TRAVIS" == "true" ]; then + NUM_WORKERS=2 +fi +MAKEOPTS="-j$NUM_WORKERS" + +# Place to store wheels. +WHEELHOUSE=${1-$HOME/wheelhouse} +echo "Path to store wheels : $WHEELHOUSE" +mkdir -p $WHEELHOUSE + +# Usually docker file copies the source code into the image. +MOOSE_SOURCE_DIR=$(pwd)/moose-core +if [ ! -d $MOOSE_SOURCE_DIR ]; then + git clone https://github.com/BhallaLab/moose-core --depth 10 +fi + +# Try to link statically. +GSL_STATIC_LIBS="/usr/local/lib/libgsl.a;/usr/local/lib/libgslcblas.a" +CMAKE=/usr/bin/cmake3 + +# Build wheels here. +for PYV in 38 37 36 27; do + PYDIR=/opt/python/cp${PYV}-cp${PYV}m + cd $MOOSE_SOURCE_DIR + echo "Building using $PYDIR in $PYVER" + PYTHON=$(ls $PYDIR/bin/python?.?) + if [ "$PYV" -eq 27 ]; then + $PYTHON -m pip install numpy==1.16 + $PYTHON -m pip install matplotlib==2.2.3 + else + $PYTHON -m pip install numpy + $PYTHON -m pip install matplotlib + fi + $PYTHON -m pip install wheel + # $PYTHON setup.py build_ext --with-gsl-static + # $PYTHON setup.py bdist_wheel + # Don't build numpy. Use wheel. + export GSL_USE_STATIC_LIBRARIES=1 + $PYTHON -m pip wheel --verbose --no-deps . -w $WHEELHOUSE + echo "Content of WHEELHOUSE" + ls -lh $WHEELHOUSE/*.whl +done + +# List all wheels. +ls -lh $WHEELHOUSE/*.whl + +# now check the wheels. +for whl in $WHEELHOUSE/pymoose*.whl; do + auditwheel show "$whl" +done + +echo "Installing before testing ... " +/opt/python/cp27-cp27m/bin/pip install $WHEELHOUSE/pymoose-$VERSION-py2-none-any.whl +/opt/python/cp36-cp36m/bin/pip install $WHEELHOUSE/pymoose-$VERSION-py3-none-any.whl +for PYV in 36 27; do + PYDIR=/opt/python/cp${PYV}-cp${PYV}m + PYTHON=$(ls $PYDIR/bin/python?.?) + $PYTHON -c 'import moose; print( moose.__version__ )' +done diff --git a/devel/docker/wheel/test_and_upload.sh b/devel/docker/wheel/test_and_upload.sh new file mode 100755 index 00000000..0968f2b0 --- /dev/null +++ b/devel/docker/wheel/test_and_upload.sh @@ -0,0 +1,67 @@ +#!/bin/bash - +#=============================================================================== +# +# FILE: test_and_upload.sh +# +# USAGE: ./test_and_upload.sh +# +# DESCRIPTION: Test each wheels and upload. +# +# OPTIONS: --- +# REQUIREMENTS: --- +# BUGS: --- +# NOTES: --- +# AUTHOR: Dilawar Singh (), bhallalabs@ncbs.res.in +# ORGANIZATION: NCBS Bangalore +# CREATED: Saturday 03 March 2018 09:56:20 IST +# REVISION: --- +#=============================================================================== + +set -e +set -x +set -o nounset # Treat unset variables as an error +GLOBAL_PIP=/opt/python/cp27-cp27m/bin/pip +GLOBAL_PY=/opt/python/cp27-cp27m/bin/python +$GLOBAL_PIP install twine +TWINE=/opt/python/cp27-cp27m/bin/twine + +cat </tmp/test.py +import moose +import moose.utils as mu +print( moose.__version__ ) +moose.reinit() +moose.start( 1 ) +EOF + +for whl in `find $HOME/wheelhouse -name "pymoose*.whl"`; do + echo "Wheel $whl" + if [[ $whl = *"-py2-"* ]]; then + echo "++ Python2 wheel $whl"; + PYTHON=/opt/python/cp27-cp27m/bin/python + PIP=/opt/python/cp27-cp27m/bin/pip + set -e + $PIP install $whl + $PYTHON /tmp/test.py + else + echo "++ Python3 wheel $whl"; + PYTHON=/opt/python/cp36-cp36m/bin/python + PIP=/opt/python/cp36-cp36m/bin/pip + set -e + $PIP install $whl + $PYTHON /tmp/test.py + fi +done + +PYPI_PASSWORD="$1" +# upload to PYPI. +for whl in `find $HOME/wheelhouse -name "pymoose*.whl"`; do + mkdir -p /tmp/wheelhouse + # If successful, upload using twine. + if [ -n "$PYPI_PASSWORD" ]; then + $TWINE upload $whl --user bhallalab --password $PYPI_PASSWORD --skip-existing + else + echo "PYPI password is not set" + echo "Copying to /tmp/wheelhouse" + cp $whl /tmp/wheelhouse/ + fi +done diff --git a/tests/python/testDisabled_socket_streamer_tcp.py b/devel/fixme/testDisabled_socket_streamer_tcp.py similarity index 100% rename from tests/python/testDisabled_socket_streamer_tcp.py rename to devel/fixme/testDisabled_socket_streamer_tcp.py diff --git a/devel/fixme/test_81_synTrigCICR.py b/devel/fixme/test_81_synTrigCICR.py new file mode 100644 index 00000000..bc96d4ec --- /dev/null +++ b/devel/fixme/test_81_synTrigCICR.py @@ -0,0 +1,97 @@ +# This example demonstrates synaptic triggering of a wave of calcium +# release (CICR) from the endoplasmic reticulum. The wave is confined to +# a subset of a dendrite where there is elevated IP3 present. +# +# Copyright (C) Upinder S. Bhalla NCBS 2018 +# Released under the terms of the GNU Public License V3. +# Converted to doctest by Dilawar Singh + +import os +import moose +import numpy as np + +import rdesigneur as rd + +sdir_ = os.path.dirname(os.path.realpath(__file__)) + +expected = np.array([1.340e-05, 1.123e-16, 8.595e-09, 4.092e-01, 8.740e-05, 8.000e-05, + 3.007e-05, 3.007e-05, 3.007e-05, 3.007e-05, 3.007e-05, 3.007e-05, + 3.007e-05, 3.008e-05, 3.011e-05, 3.026e-05, 3.091e-05, 3.106e-05, + 3.110e-05, 3.111e-05, 3.113e-05, 3.118e-05, 3.135e-05, 3.118e-05, + 3.113e-05, 3.112e-05, 3.111e-05, 3.111e-05, 3.111e-05, 3.111e-05, + 3.111e-05, 3.111e-05, 3.111e-05, 3.110e-05, 3.106e-05, 3.091e-05, + 3.026e-05, 3.011e-05, 3.008e-05, 3.007e-05, 3.007e-05, 3.007e-05, + 3.007e-05, 3.007e-05, 3.007e-05, 3.007e-05, 3.007e-05, 3.007e-05, + 3.007e-05, 3.007e-05, 3.007e-05, 3.007e-05, 3.007e-05, 3.008e-05, + 3.011e-05, 3.026e-05, 3.091e-05, 3.106e-05, 3.110e-05, 3.111e-05, + 3.113e-05, 3.118e-05, 3.135e-05, 3.118e-05, 3.113e-05, 3.112e-05, + 3.111e-05, 3.111e-05, 3.111e-05, 3.111e-05, 3.111e-05, 3.111e-05, + 3.111e-05, 3.110e-05, 3.106e-05, 3.091e-05, 3.026e-05, 3.011e-05, + 3.008e-05, 3.007e-05, 3.007e-05, 3.007e-05, 3.007e-05, 3.007e-05, + 3.007e-05, 3.007e-05, 4.090e-01, 4.090e-01, 4.090e-01, 4.090e-01, + 4.090e-01, 4.090e-01, 4.090e-01, 4.090e-01, 4.090e-01, 4.091e-01, + 4.089e-01, 4.089e-01, 4.089e-01, 4.090e-01, 4.090e-01, 4.090e-01, + 4.093e-01, 4.090e-01, 4.090e-01, 4.090e-01, 4.090e-01, 4.090e-01, + 4.090e-01, 4.090e-01, 4.090e-01, 4.090e-01, 4.090e-01, 4.089e-01, + 4.089e-01, 4.089e-01, 4.091e-01, 4.090e-01, 4.090e-01, 4.090e-01, + 4.090e-01, 4.090e-01, 4.090e-01, 4.090e-01, 4.090e-01, 4.090e-01]) + +def test(): + """ + Test CICR. + + >>> test() # doctest: +NORMALIZE_WHITESPACE + Rdesigneur: Elec model has 5 compartments and 2 spines on 4 compartments. + Chem part of model has the following compartments: + | In dend, 40 voxels X 19 pools + | In spine, 2 voxels X 1 pools + | In psd, 2 voxels X 1 pools + | In dend_endo, 40 voxels X 2 pools + True + """ + rdes = rd.rdesigneur( + turnOffElec = False, + chemDt = 0.002, + chemPlotDt = 0.02, + diffusionLength = 1e-6, + numWaveFrames = 50, + useGssa = False, + addSomaChemCompt = False, + addEndoChemCompt = True, + # cellProto syntax: ['ballAndStick', 'name', somaDia, somaLength, dendDia, dendLength, numDendSeg] + cellProto = [['ballAndStick', 'soma', 10e-6, 10e-6, 2e-6, 40e-6, 4]], + spineProto = [['makeActiveSpine()', 'spine']], + chemProto = [[os.path.join(sdir_,'../py_rdesigneur/chem/CICRspineDend.g'), 'chem']], + spineDistrib = [['spine', '#dend#', '10e-6', '0.1e-6']], + chemDistrib = [['chem', 'dend#,spine#,head#', 'install', '1' ]], + adaptorList = [ + [ 'Ca_conc', 'Ca', 'spine/Ca', 'conc', 0.00008, 8 ] + ], + stimList = [ + ['head0', '0.5', 'glu', 'periodicsyn', '1 + 40*(t>5 && t<6)'], + ['head0', '0.5', 'NMDA', 'periodicsyn', '1 + 40*(t>5 && t<6)'], + ['dend#', 'g>10e-6 && g<=31e-6', 'dend/IP3', 'conc', '0.0006' ], + ], + plotList = [ + ['head#', '1', 'spine/Ca', 'conc', 'Spine Ca conc'], + ['dend#', '1', 'dend/Ca', 'conc', 'Dend Ca conc'], + ['dend#', '1', 'dend/Ca', 'conc', 'Dend Ca conc', 'wave'], + ['dend#', '1', 'dend_endo/CaER', 'conc', 'ER Ca conc', 'wave'], + ['soma', '1', '.', 'Vm', 'Memb potl'], + ], + ) + moose.seed( 1234 ) + rdes.buildModel() + moose.reinit() + moose.start(2) + data = [] + for t in moose.wildcardFind('/##[TYPE=Table2]'): + data.append(t.vector[::20]) + res = np.mean(data, axis=1) + assert np.allclose(res, expected, rtol=1e-4, atol=1e-4), \ + "Total error %s" % np.sum(res - expected) + return True + +if __name__ == '__main__': + test() + print('All done') diff --git a/devel/fixme/test_82_multiscale_gluR_phosph_3compt.py b/devel/fixme/test_82_multiscale_gluR_phosph_3compt.py new file mode 100644 index 00000000..0cd4797f --- /dev/null +++ b/devel/fixme/test_82_multiscale_gluR_phosph_3compt.py @@ -0,0 +1,111 @@ +# This example demonstrates a multiscale model with synaptic input, Ca +# entry to the spine, receptor modulation following phosphorylation and +# Ca diffusion from spine to the dendrite. Lots going on. +# System switches to a potentiated state after a 1s strong synaptic input. +# +# Ca+CaM <===> Ca_CaM; Ca_CaM + CaMKII <===> Ca_CaM_CaMKII (all in +# spine head, except that the Ca_CaM_CaMKII translocates to the PSD) +# chan ------Ca_CaM_CaMKII-----> chan_p; chan_p ------> chan (all in PSD) +# +# Copyright (C) Upinder S. Bhalla NCBS 2018 +# Released under the terms of the GNU Public License V3. +# Convered to doctest by Dilawar Singh + +import os +import moose +import numpy as np +import rdesigneur as rd + +sdir_ = os.path.dirname(os.path.realpath(__file__)) + +A = np.array([3.522e-05, 3.298e-04, 1.752e-05, 1.879e-02, 1.629e-02, 1.533e-04, + 1.538e-04, 1.546e-04, 1.559e-04, 1.576e-04, 1.597e-04, 1.623e-04, + 1.655e-04, 1.693e-04, 1.738e-04, 1.791e-04, 1.852e-04, 1.922e-04, + 2.002e-04, 2.094e-04, 2.197e-04, 2.314e-04, 2.446e-04, 2.596e-04, + 2.765e-04, 2.955e-04, 3.171e-04, 3.415e-04, 3.693e-04, 4.008e-04, + 4.369e-04, 4.783e-04, 5.259e-04, 5.811e-04, 6.455e-04, 7.212e-04, + 8.076e-04, 8.993e-04, 9.039e-04, 9.105e-04, 9.189e-04, 9.293e-04, + 9.417e-04, 9.562e-04, 9.729e-04, 9.918e-04, 1.013e-03, 1.037e-03, + 1.063e-03, 1.092e-03, 1.123e-03, 1.157e-03, 1.193e-03, 1.233e-03, + 1.275e-03, 1.320e-03, 1.305e-03, 1.293e-03, 1.285e-03, 1.279e-03, + 1.276e-03, 1.029e-03, 1.035e-03, 3.114e-02, 2.892e-02, 4.087e-03, + 3.402e-03]) + +B = np.array([6.761e-06, 1.049e-04, 4.196e-06, 7.230e-02, 6.142e-02, 8.928e-05, + 8.956e-05, 9.012e-05, 9.096e-05, 9.209e-05, 9.350e-05, 9.524e-05, + 9.735e-05, 9.990e-05, 1.029e-04, 1.065e-04, 1.106e-04, 1.154e-04, + 1.208e-04, 1.271e-04, 1.342e-04, 1.422e-04, 1.514e-04, 1.618e-04, + 1.735e-04, 1.869e-04, 2.021e-04, 2.195e-04, 2.394e-04, 2.625e-04, + 2.894e-04, 3.210e-04, 3.586e-04, 4.041e-04, 4.601e-04, 5.305e-04, + 6.183e-04, 7.234e-04, 6.871e-04, 6.725e-04, 6.715e-04, 6.796e-04, + 6.937e-04, 7.114e-04, 7.310e-04, 7.515e-04, 7.720e-04, 7.922e-04, + 8.118e-04, 8.311e-04, 8.504e-04, 8.702e-04, 8.913e-04, 9.150e-04, + 9.429e-04, 9.780e-04, 9.673e-04, 9.636e-04, 9.632e-04, 9.640e-04, + 9.647e-04, 2.049e-03, 1.984e-03, 1.499e-02, 1.382e-02, 2.415e-03, + 1.918e-03]) +def test(): + """Test + """ + rdes = rd.rdesigneur( + elecDt = 50e-6, + chemDt = 0.002, + diffDt = 0.002, + chemPlotDt = 0.02, + useGssa = False, + # cellProto syntax: ['ballAndStick', 'name', somaDia, somaLength, dendDia, dendLength, numDendSegments ] + cellProto = [['ballAndStick', 'soma', 12e-6, 12e-6, 4e-6, 100e-6, 2 ]], + chemProto = [[os.path.join(sdir_, + '../py_rdesigneur/chem/chanPhosph3compt.g'), 'chem']], + spineProto = [['makeActiveSpine()', 'spine']], + chanProto = [ + ['make_Na()', 'Na'], + ['make_K_DR()', 'K_DR'], + ['make_K_A()', 'K_A' ], + ['make_Ca()', 'Ca' ], + ['make_Ca_conc()', 'Ca_conc' ] + ], + passiveDistrib = [['soma', 'CM', '0.01', 'Em', '-0.06']], + spineDistrib = [['spine', '#dend#', '50e-6', '1e-6']], + chemDistrib = [['chem', '#', 'install', '1' ]], + chanDistrib = [ + ['Na', 'soma', 'Gbar', '300' ], + ['K_DR', 'soma', 'Gbar', '250' ], + ['K_A', 'soma', 'Gbar', '200' ], + ['Ca_conc', 'soma', 'tau', '0.0333' ], + ['Ca', 'soma', 'Gbar', '40' ] + ], + adaptorList = [ + [ 'psd/chan_p', 'n', 'glu', 'modulation', 0.1, 1.0 ], + [ 'Ca_conc', 'Ca', 'spine/Ca', 'conc', 0.00008, 8 ] + ], + # Syn input basline 1 Hz, and 40Hz burst for 1 sec at t=20. Syn weight + # is 0.5, specified in 2nd argument as a special case stimLists. + stimList = [['head#', '0.5','glu', 'periodicsyn', '1 + 40*(t>10 && t<11)']], + plotList = [ + ['soma', '1', '.', 'Vm', 'Membrane potential'], + ['#', '1', 'spine/Ca', 'conc', 'Ca in Spine'], + ['#', '1', 'dend/DEND/Ca', 'conc', 'Ca in Dend'], + ['#', '1', 'spine/Ca_CaM', 'conc', 'Ca_CaM'], + ['head#', '1', 'psd/chan_p', 'conc', 'Phosph gluR'], + ['head#', '1', 'psd/Ca_CaM_CaMKII', 'conc', 'Active CaMKII'], + ] + ) + moose.seed(123) + rdes.buildModel() + moose.reinit() + moose.start(25) + data = [] + v = moose.wildcardFind('/##[TYPE=Table]')[0].vector + assert np.allclose( (v.mean(), v.std()), (-0.06777396715033643, + 0.008550767915889)), (v.mean(), v.std()) + for t in moose.wildcardFind('/##[TYPE=Table2]'): + data.append(t.vector) + + m = np.mean(data, axis=1) + u = np.std(data, axis=1) + assert m.shape[0] == 67 + assert np.allclose(m, A, atol=1e-5), m - A + assert np.allclose(u, B, atol=1e-5), u - B + +if __name__ == '__main__': + test() diff --git a/devel/fixme/test_long_sbml+exp+parser+multithreaded.py b/devel/fixme/test_long_sbml+exp+parser+multithreaded.py new file mode 100644 index 00000000..e458fca5 --- /dev/null +++ b/devel/fixme/test_long_sbml+exp+parser+multithreaded.py @@ -0,0 +1,580 @@ +# -*- coding: utf-8 -*- +from __future__ import print_function, division + +################################################################ +# This program is part of 'MOOSE', the +# Messaging Object Oriented Simulation Environment. +# Copyright (C) 2015 Upinder S. Bhalla. and NCBS +# It is made available under the terms of the +# GNU Lesser General Public License version 2.1 +# See the file COPYING.LIB for the full notice. +# +# rxdSpineSize.py: Builds a cell with spines and a propagating reaction +# wave. Products diffuse into the spine and cause it to get bigger. +################################################################# + +# Cdc42 activation profile (spatial and time) has to be accounted, +# Tension modification +# Modification logs: +# Model is developed by Vinu Verghese. +# Modified by Dilawar Singh for testing. + +import os +import numpy as np +import moose +print("[INFO] MOOSE: %s, version:%s" % (moose.__file__, moose.__version__)) +import sys +import rdesigneur as rd +import time +import xml.etree.ElementTree as ET + + +if sys.version_info.major == 2: + print("[INFO ] this test works with python3 only.") + quit(0) + +try: + import moose.SBML +except Exception as e: + print(e) + print("libsbml-python is not found. Disabling tests.") + quit(0) + +sdir_ = os.path.dirname(os.path.realpath(__file__)) +args_ = [ + '', 1e-6, 0.018, 1, 20e-12, 1e-12, 100, 102, 105, 4, 20, 10, 1.0, 0.5, + 0.05, 0.0, 0.0055, 0.1e-14 +] + +PI = 3.141592653 +scaling_ = 10.0 +RM = 1.0 / scaling_ +RA = 1.0 * scaling_ +CM = 0.01 * scaling_ +loc1 = str(args_[6]) +loc2 = str(args_[7]) +loc3 = str(args_[8]) +frameruntime = 1.0 +diffConst = 5e-10 +dendLen = 0.25e-6 +comptLen = 1e-6 +diffLen = 2.0e-6 +dendDia = 1e-6 +somaDia = 1e-6 +concInit = 0.1 # 10 micromolar +spineSpacing = float(args_[1]) +spineSpacingDistrib = 1e-6 +spineSize = 1.0 +spineSizeDistrib = 0.5 +spineAngle = np.pi / 2.0 +spineAngleDistrib = 0.0 +numDendSegments = 100 + + +def computeTP(t, distS, SourceC): + print("[INFO ] Calling computeTP", end=' ....') + sys.stdout.flush() + conv = moose.element('/model/chem/dend/conv') + w = len(conv.vec.n) + h = w + v2d = [[0.0 for x in range(w)] for y in range(h)] + mm = moose.vec('/model/chem/dend/mesh') + diffL = moose.element('/model/chem/dend').diffLength + print(conv.name, conv.vec[0].nInit, 'diff lenght %s' % diffL) + listL = [[distS, t]] + SourceC = SourceC + extraDiff = 0.05e-12 + for j in listL: + for i in range(len(conv.vec.n)): + for k in range(len(conv.vec.conc)): + v2d[i][k] = diffL**2.0 * ( + SourceC / + (4.0 * np.pi * j[1] * np.sqrt(extraDiff * extraDiff)) + ) * np.exp(-(mm[i].Coordinates[0]**2.0) / + (4 * extraDiff * j[1]) - (mm[k].Coordinates[0]**2) / + (4 * extraDiff * j[1])) + tempRec = [] + if True: + for i in range(len(conv.vec.n)): + tempRec.append(v2d[i][distS]) + print(" .... done") + sys.stdout.flush() + return tempRec + + +def pert_int(posPer, SourceC): + print('In pert_int') + timePer = int(args_[9]) + distS = int(args_[10]) + Ca = moose.element('/model/chem/dend/Ca') + conv = moose.element('/model/chem/dend/conv') + rec = moose.element('/model/chem/dend/IRSpGr/rec') + Ca_vec = moose.vec('/model/chem/dend/Ca').conc + tempRec = computeTP(timePer, distS, SourceC) + print(len(tempRec)) + sys.stdout.flush() + moose.element('/model/chem/dend/IRSpGr/rec').vec[posPer].conc += tempRec[0] + for j in range(posPer + 1, len(Ca_vec)): + print(j, end=' ') + sys.stdout.flush() + #rec.vec[j].conc=tempRec[j-posPer] + moose.element('/model/chem/dend/IRSpGr/rec').vec[j].conc += tempRec[ + j - posPer] + if int(posPer * 2 - j) >= 0: + #rec.vec[posPer*2-j].conc=tempRec[j-posPer] + moose.element('/model/chem/dend/IRSpGr/rec').vec[ + posPer * 2 - j].conc += tempRec[j - posPer] + moose.element('/model/chem/dend/IRSpGr/rec').conc = moose.element( + '/model/chem/dend/IRSpGr/rec').conc / 2 + + print('PERTURBED') + + return distS, timePer + + +def makeCellProto(name): + elec = moose.Neuron('/library/' + name) + ecompt = [] + #soma = rd.buildCompt( elec, 'soma', dx=somaDia, dia=somaDia, x=-somaDia, RM=RM, RA=RA, CM=CM ) + dend = rd.buildCompt(elec, + 'dend', + dx=dendLen, + dia=dendDia, + x=0, + RM=RM, + RA=RA, + CM=CM) + #moose.connect( soma, 'axial', dend, 'raxial' ) + prev = dend + x = dendLen + for i in range(numDendSegments): + compt = rd.buildCompt(elec, + 'dend' + str(i), + dx=dendLen, + dia=dendDia, + x=x, + RM=RM, + RA=RA, + CM=CM) + moose.connect(prev, 'axial', compt, 'raxial') + prev = compt + x = x + dendLen + elec.buildSegmentTree() + + +def makeDendProto(name): + dend = moose.Neuron('/library/dend') + prev = rd.buildCompt(dend, + 'soma', + RM=RM, + RA=RA, + CM=CM, + dia=2.0e-06, + x=0, + dx=comptLen) + x = comptLen + y = 0.0 + comptDia = 1e-06 + + for i in range(numDendSegments): + dx = comptLen + dy = 0 + compt = rd.buildCompt(dend, + 'dend' + str(i), + RM=RM, + RA=RA, + CM=CM, + x=x, + y=y, + dx=dx, + dy=dy, + dia=comptDia) + moose.connect(prev, 'axial', compt, 'raxial') + prev = compt + x += dx + y += dy + + +def makeChemProto(name='hydra'): + moose.Neutral('/library/') + meshName = '/library/' + name + moose.SBML.mooseReadSBML(os.path.join(sdir_, '..', 'data', 'c_m.xml'), + meshName) + Rad = moose.element('/library/hydra/dend/IRSpGr/Rad') + + I_C = moose.element(meshName + '/dend/IRSpGr/IRSp53') + Ca = moose.element(meshName + '/dend/Ca') + rec = moose.Pool(meshName + '/dend/IRSpGr/rec') + conv = moose.Pool(meshName + '/dend/conv') + Cdc42 = moose.element(meshName + '/dend/IRSpGr/Cdc42') + Cdc42_m = moose.element(meshName + '/dend/IRSpGr/Cdc42_m') + Cdc42_GDP = moose.element(meshName + '/dend/Cdc42_GDP') + Rac_GTP = moose.element(meshName + '/dend/Rac_GTP') + Rac_m = moose.element(meshName + '/dend/IRSpGr/Rac_m') + Rac_GDP = moose.element(meshName + '/dend/Rac_GDP') + Eps8 = moose.element(meshName + '/dend/IRSpGr/Eps8') + I_Cact = moose.element(meshName + '/dend/IRSpGr/IRSp53_a') + I_M = moose.element(meshName + '/dend/IRSpGr/IRSp53_m') + Idimer = moose.element(meshName + '/dend/IRSpGr/IRSp53_dimer') + recBAR = moose.Function(meshName + '/dend/IRSpGr/recBAR') + gradBAR = moose.Function(meshName + '/dend/IRSpGr/gradBAR') + Radfun = moose.Function(meshName + '/dend/IRSpGr/Radfun') + Ipool = moose.element(meshName + '/dend/IRSpGr/Ipool') + sort = moose.element(meshName + '/dend/IRSpGr/sort') + detach = moose.element(meshName + '/dend/IRSpGr/detach') + curv_IRSp53 = moose.element(meshName + '/dend/IRSpGr/curv_IRSp53') + tube_IRSp53 = moose.element(meshName + '/dend/IRSpGr/tube_IRSp53') + to_tube_Reac = moose.element(meshName + '/dend/IRSpGr/to_tube_Reac') + Cdc42_breac = moose.element(meshName + '/dend/Cdc42_GTP_GDP_Reac') + Tiam_breac = moose.element(meshName + '/dend/Tiam_Rev_Reac') + store_tube = moose.Pool(meshName + '/dend/IRSpGr/store_tube') + IRSp53_temp = moose.element(meshName + '/dend/IRSpGr/IRSp53_temp') + sigma = moose.Pool(meshName + '/dend/IRSpGr/sigma') + Kv = moose.Pool(meshName + '/dend/IRSpGr/Kv') + + dend_vasp = moose.element(meshName + '/dend/IRSpGr/VASP') + + dend_gactin = moose.element(meshName + '/dend/IRSpGr/Gactin') + dend_factin = moose.element(meshName + '/dend/IRSpGr/Factin') + GF_Reac = moose.element(meshName + '/dend/IRSpGr/GF_Reac') + sort_func = moose.element(meshName + '/dend/IRSpGr/sort_func') + breacT_fun = moose.Function(meshName + '/dend/breacT_fun') + breacC_fun = moose.Function(meshName + '/dend/breacC_fun') + simpleFun = moose.Function(meshName + '/dend/IRSpGr/simpleFun') + simpleFun1 = moose.Function(meshName + '/dend/IRSpGr/simpleFun1') + simpleFun2 = moose.Function(meshName + '/dend/IRSpGr/simpleFun2') + Kvfun = moose.Function(meshName + '/dend/IRSpGr/Kvfun') + recFun = moose.Function(meshName + '/dend/IRSpGr/recFun') + simpleFun2 = moose.Function(meshName + '/dend/IRSpGr/simpleFun2') + simpleFun3 = moose.Function(meshName + '/dend/IRSpGr/simpleFun3') + mod_sort = moose.element(meshName + '/dend/IRSpGr/mod_sort') + mod_detach = moose.element(meshName + '/dend/IRSpGr/mod_detach') + to_tube_Reac = moose.element(meshName + '/dend/IRSpGr/to_tube_Reac') + + conv_fun = moose.Function(meshName + '/dend/IRSpGr/conv_fun') + conv_fun.expr = "1*x0*(x1-1.89191155)+1.89191155" + Kvfun.expr = "1.0" + moose.connect(Kvfun, 'valueOut', Kv, 'setN') + + simpleFun.expr = "1.0*x0" + simpleFun1.expr = "1.0*x0" + simpleFun2.expr = "0.1*x0" + simpleFun3.expr = "1.0*x0" + breacT_fun.expr = "5*x0" + breacC_fun.expr = "5*x0" + + moose.connect(curv_IRSp53, 'nOut', simpleFun2.x[0], 'input') + moose.connect(simpleFun2, 'valueOut', GF_Reac, 'setNumKf') + + moose.connect(sort_func, 'nOut', simpleFun.x[0], 'input') + moose.connect(detach, 'nOut', simpleFun1.x[0], 'input') + moose.connect(store_tube, 'nOut', simpleFun3.x[0], 'input') + + recFun.expr = "0.0*x0+(exp(45*54*((" + str( + args_[14]) + "/(x0*1e9))-(1/(2.0*(x0*1e9)*(x0*1e9))))))" + + Radfun.expr = "sqrt(((45+12)*4*1e-18)/(2*(x2-0.08*(ln((((1.0*x0+1.0*x1)/(2*3.14*(0.45*0.05)))*1e-6*54))))))*((3*" + str( + float(args_[2])) + "*x3*(x0+1.0*x1)^2)/(1.+3*" + str(float( + args_[2])) + "*x3*(x0+1.0*x1)^2))" + + mod_sort.Kf = 0. + mod_sort.Kb = 0. + mod_detach.Kf = 0. + mod_detach.Kb = 0. + + moose.connect(curv_IRSp53, 'nOut', Radfun.x[0], 'input') + moose.connect(I_M, 'nOut', Radfun.x[1], 'input') + #moose.connect(tube_IRSp53,'nOut',Radfun.x[2],'input') + moose.connect(sigma, 'nOut', Radfun.x[2], 'input') + moose.connect(Kv, 'nOut', Radfun.x[3], 'input') + moose.connect(Radfun, 'valueOut', Rad, 'setN') + + moose.connect(rec, 'nOut', conv_fun.x[0], 'input') + moose.connect(conv, 'nOut', conv_fun.x[1], 'input') + moose.connect(conv_fun, 'valueOut', Ca, 'setN') + + moose.connect(simpleFun, 'valueOut', mod_sort, 'setNumKf') + moose.connect(simpleFun1, 'valueOut', mod_detach, 'setNumKf') + + moose.connect(Rad, 'nOut', recFun.x[0], 'input') + moose.connect(recFun, 'valueOut', Ipool, 'setN') + + ### Ipool is further copied to sort to participate in the reaction tube_reac or enz (model version 2.5.3) + + I_C.concInit = 0.0012 + file_molWt = os.path.join(sdir_, '..', 'data', 'prot_wt.xml') + den = 6.0 * 3.14 * np.cbrt(3.0 / (4.0 * 3.14 * 0.73 * 6.02 * 1e23)) + num = 1e3 * 1e6 * 1.38 * 1e-23 + co = num / den + + # Diffconsts are set here + if int(args_[3]) == 1: + for prot in moose.wildcardFind(meshName + '/dend/#[ISA=Pool]'): + mol_name = ET.parse(file_molWt).find(str(prot.name)) + print('Name is %s' % mol_name, end='. ') + molWt = mol_name.text.split() + if float(molWt[1]) <= 0.0: + continue + moose.element(prot).diffConst = co * ( + 300 / (200.0 * np.cbrt(float(molWt[1]) * 1e3))) * 1e-4 + print('-- D', prot.name, moose.element(prot).diffConst) + + for prot in moose.wildcardFind(meshName + + '/dend/CaMKII_gr/#[ISA=Pool]'): + mol_name = ET.parse(file_molWt).find(str(prot.name)) + print('Name is %s' % mol_name, end='. ') + molWt = mol_name.text.split() + if float(molWt[1]) <= 0.0: + continue + moose.element(prot).diffConst = co * ( + 300 / (200.0 * np.cbrt(float(molWt[1]) * 1e3))) * 1e-4 + print('-- D', prot.name, moose.element(prot).diffConst) + for prot in moose.wildcardFind(meshName + '/dend/Ras_gr/#[ISA=Pool]'): + mol_name = ET.parse(file_molWt).find(str(prot.name)) + print('Name is %s' % mol_name, end='. ') + molWt = mol_name.text.split() + if float(molWt[1]) <= 0.0: + continue + moose.element(prot).diffConst = co * ( + 300 / (200.0 * np.cbrt(float(molWt[1]) * 1e3))) * 1e-4 + print('-- D', prot.name, moose.element(prot).diffConst) + + Ca.diffConst = float(args_[4]) + print('-- D', Ca.name, Ca.diffConst) + print('\t==================== diffConst updated') + + print('DIFFUSION FOR IRSp53 GROUP') + I_C.diffConst = co * (300 / (8.0 * np.cbrt(120.0 * 1e3))) * 1e-4 + print(I_C.diffConst, end=' + ') + I_Cact.diffConst = co * (300 / (8.0 * np.cbrt(208.0 * 1e3))) * 1e-4 + print(I_Cact.diffConst) + Eps8.diffConst = co * (300 / (200.0 * np.cbrt(92.0 * 1e3))) * 1e-4 + print(Eps8.diffConst, end=' + ') + Cdc42.diffConst = co * (300 / (8.0 * np.cbrt(22.0 * 1e3))) * 1e-4 + Cdc42_m.diffConst = co * (300 / (200.0 * np.cbrt(22.0 * 1e3))) * 1e-4 + Cdc42_GDP.diffConst = co * (300 / (8.0 * np.cbrt(22.0 * 1e3))) * 1e-4 + print(Cdc42.diffConst, end=' + ') + Rac_GTP.diffConst = co * (300 / (8.0 * np.cbrt(22.0 * 1e3))) * 1e-4 + Rac_m.diffConst = co * (300 / (200.0 * np.cbrt(22.0 * 1e3))) * 1e-4 + Rac_GDP.diffConst = co * (300 / (8.0 * np.cbrt(22.0 * 1e3))) * 1e-4 + + I_M.diffConst = 1.0 * co * (300 / (200.0 * np.cbrt(392.0 * 1e3))) * 1e-4 + print(I_M.diffConst, end=' + ') + Idimer.diffConst = co * (300 / (8.0 * np.cbrt(120.0 * 1e3))) * 1e-4 + print(Idimer.diffConst) + curv_IRSp53.diffConst = float(args_[17]) + + conv.diffConst = 0.0 + rec.diffConst = 0.0 + + dend_gactin.diffConst = 1e-13 + dend_vasp.diffConst = 1e-13 + + return meshName + + +def makeModel(): + moose.Neutral('/library') + makeCellProto('cellProto') + makeChemProto() + rdes = rd.rdesigneur( + useGssa=False, + turnOffElec=False, + chemDt=0.0025, + diffDt=0.0025, + chemPlotDt=0.1, + combineSegments=False, + stealCellFromLibrary=True, + diffusionLength=50e-9, + cellProto=[['cellProto', 'elec']], + chanProto=[ + ['make_NMDA()', 'NMDA'], + ['make_Ca_conc()', 'Ca_conc'], + ], + chemProto=[['hydra', 'chem']], + chemDistrib=[["chem", "#", "install", "1"]], + chanDistrib=[ + ['NMDA', 'dend#', 'Gbar', '1'], + ['Ca_conc', 'dend#', 'tau', '0.033'], + ], + stimList=[ + [ + 'dend#', '1.', 'NMDA', 'periodicsyn', + str(args_[13]) + '*(t>0 && t<60)+' + str(args_[13]) + '*(t>' + + str(args_[15]) + ' && t<(' + str(args_[15]) + '+60))' + ], + ], + adaptorList=[['Ca_conc', 'Ca', 'dend/conv', 'conc', 0.00008, 20]], + benchmark=True) + moose.seed(100) + print("[INFO ] rdes is building model ...") + rdes.buildModel('/model') + print("[INFO ] Model is built...") + moose.element('/model/chem/dend/IRSpGr/Rad').nInit = 30e-9 + + +def makePlot(name, srcVec, field): + tab = moose.Table2('/graphs/' + name + 'Tab', len(srcVec)).vec + for i in zip(srcVec, tab): + moose.connect(i[1], 'requestOut', i[0], field) + return tab + + +def main(): + """ + This illustrates the use of rdesigneur to build a simple dendrite with + spines, and then to resize them using spine fields. These are the + fields that would be changed dynamically in a simulation with reactions + that affect spine geometry. + In this simulation there is a propagating reaction wave using a + highly abstracted equation, whose product diffuses into the spines and + makes them bigger. + """ + t0 = time.time() + makeModel() + print("[INFO ] Took %f sec." % (time.time() - t0)) + sys.stdout.flush() + for i in range(11, 18): + moose.setClock(i, 0.0025) + moose.setClock(18, 0.0025) + moose.element('/model/elec') + moose.Neutral('/graphs') + Cdcinit = moose.vec('/model/chem/dend/IRSpGr/Cdc42') + Tiaminit = moose.vec('/model/chem/dend/Tiam1') + Cdcinit.concInit = 0.0 + Tiaminit.concInit = 0.0 + + makePlot('dend_curv_IRSp53', + moose.vec('/model/chem/dend/IRSpGr/curv_IRSp53'), 'getN') + makePlot('sorting', moose.vec('/model/chem/dend/IRSpGr/sort'), 'getN') + makePlot('Ca', moose.vec('/model/chem/dend/Ca'), 'getN') + makePlot('CaM', moose.vec('/model/chem/dend/CaM'), 'getConc') + makePlot('CaM_GEF', moose.vec('/model/chem/dend/Ras_gr/CaM_GEF'), + 'getConc') + makePlot('Ca4CaM', moose.vec('/model/chem/dend/CaM_Ca4'), 'getConc') + makePlot('Cdc42', moose.vec('/model/chem/dend/IRSpGr/Cdc42'), 'getN') + makePlot('RacGTP', moose.vec('/model/chem/dend/Rac_GTP'), 'getN') + makePlot('Tiam', moose.vec('/model/chem/dend/Tiam1'), 'getN') + mypyrun = moose.PyRun('/model/mypyrun') + mypyrun.initString = """count=0""" + mypyrun.runString = """count=count+1 +radv=moose.vec('/model/chem/dend/IRSpGr/Rad').n +radm=radv[10] +output=radm +IRvec=moose.vec( '/model/chem/dend/IRSpGr/IRSp53' ).n +curv_IRSp53=moose.element( '/model/chem/dend/IRSpGr/curv_IRSp53') +Cdcvec=moose.vec( '/model/chem/dend/IRSpGr/Cdc42' ).n +if count==1: + Cdcinit=moose.vec( '/model/chem/dend/IRSpGr/Cdc42' ).nInit + pos=np.unravel_index(np.argmax(Cdcinit), Cdcinit.shape) + pos=pos[0] +curv_IRSp53vec=moose.vec('/model/chem/dend/IRSpGr/curv_IRSp53').n +sigmaVec=moose.vec('/model/chem/dend/IRSpGr/sigma').n +IRSp53_mvec=moose.vec('/model/chem/dend/IRSpGr/IRSp53_m').n +Ipoolvec=moose.vec('/model/chem/dend/IRSpGr/Ipool').n +Kv=moose.vec('/model/chem/dend/IRSpGr/Kv').n +sort_func=moose.vec('/model/chem/dend/IRSpGr/sort').n +for gri in range(0,len(Cdcvec)): + sort_func[gri]=1.0*((3*float(args_[2])*Kv[gri]*(1.0*curv_IRSp53vec[gri]+1.0*IRSp53_mvec[gri])**2)/(1.0+3.0*float(args_[2])*Kv[gri]*(1.0*curv_IRSp53vec[gri]+1.0*IRSp53_mvec[gri])**2))*sort_func[gri] +if count==1: + maxCIR=[] + maxIR=[] + max_curv=[] +for gri in range(0,len(Cdcvec)): + sigmaVec[gri]=(0.3-0.25*np.exp(-0.015*count*0.0025))*((float(args_[2])*3*curv_IRSp53vec[gri]**2)/(1+float(args_[2])*3*curv_IRSp53vec[gri]**2))+0.0055 + s_m=1-np.exp(-sigmaVec[gri]/0.3) + sort_func[gri]=sort_func[gri]-1.6*s_m*sort_func[gri] +det_vec=moose.vec('/model/chem/dend/IRSpGr/detach').n +for gri in range(0,len(Cdcvec)): + s_m=1-np.exp(-sigmaVec[gri]/0.3) + det_vec[gri]=det_vec[gri]+1.6*s_m*det_vec[gri] +moose.vec('/model/chem/dend/IRSpGr/detach').n=det_vec +temp_sort=moose.vec('/model/chem/dend/IRSpGr/sort_func').n +pref_curv=0.055 +radmax=max(radv) +if count%100==0: + print("Sum of IRSp53s") + print(sum(moose.vec('/model/chem/dend/IRSpGr/IRSp53_dimer').n)+sum(moose.vec('/model/chem/dend/IRSpGr/IRSp53_a').n)+sum(moose.vec('/model/chem/dend/IRSpGr/IRSp53_m').n)+sum(moose.vec('/model/chem/dend/IRSpGr/curv_IRSp53').n),sum(moose.vec('/model/chem/dend/IRSpGr/IRSp53_m').n),sum(moose.vec('/model/chem/dend/IRSpGr/IRSp53_a').n),sum(moose.vec('/model/chem/dend/IRSpGr/IRSp53_dimer').n),sum(moose.vec('/model/chem/dend/IRSpGr/curv_IRSp53').n)) + sys.stdout.flush() +""" + outputTab = moose.Table('/model/output') + moose.connect(mypyrun, 'output', outputTab, 'input') + moose.setClock(30, 0.0025) + moose.setClock(10, 0.0025) + moose.setClock(15, 0.0025) + moose.setClock(16, 0.0025) + mypyrun.mode = 1 + + k = moose.wildcardFind('/##[TYPE=Ksolve]')[0] + k.numThreads = 4 + print(' .... done making plots.') + print("[INFO ] Doing moose.reinit ...") + sys.stdout.flush() + moose.reinit() + print(" ... DONE REINIT") + sys.stdout.flush() + print('\n TEST PROPAGATING WAVES \n') + recavec = [] + loc1_vox = (int(loc1) * dendLen) / 50e-9 + loc2_vox = (int(loc2) * dendLen) / 50e-9 + loc3_vox = (int(loc3) * dendLen) / 50e-9 + + pert_int(int(loc1_vox), int(args_[11])) + + temp = moose.vec('/model/chem/dend/IRSpGr/rec').n + recavec.append(moose.vec('/model/chem/dend/IRSpGr/rec').n) + gap = int(loc2_vox) - int(loc1_vox) + gap_p = int(loc3_vox) - int(loc1_vox) + recavec.append([ + 0.0 + float(args_[12]) * temp[i - gap_p] + for i in range(0, len(moose.vec('/model/chem/dend/IRSpGr/rec').n)) + ]) + moose.vec('/model/chem/dend/IRSpGr/rec').n = [ + temp[i - gap] + for i in range(0, len(moose.vec('/model/chem/dend/IRSpGr/rec').n)) + ] + recavec.append(moose.vec('/model/chem/dend/IRSpGr/rec').n) + moose.vec('/model/chem/dend/IRSpGr/rec').n = [ + temp[i - gap] + for i in range(0, len(moose.vec('/model/chem/dend/IRSpGr/rec').n)) + ] + moose.vec('/model/chem/dend/IRSpGr/rec' + ).n = moose.vec('/model/chem/dend/IRSpGr/rec').n + temp + recavec.append(moose.vec('/model/chem/dend/IRSpGr/rec').n) + if float(args_[15]) == 0.0: + moose.vec('/model/chem/dend/IRSpGr/rec').n = recavec[3] + else: + moose.vec('/model/chem/dend/IRSpGr/rec').n = recavec[0] + + allres = [] + t0 = time.time() + for i in range(3): + print("[INFO ] Simulation step %d/3" % (1 + i)) + moose.start(0.5) + res = sum(moose.vec('/model/chem/dend/IRSpGr/IRSp53_dimer').n) + sum( + moose.vec('/model/chem/dend/IRSpGr/IRSp53_a').n + ) + sum(moose.vec('/model/chem/dend/IRSpGr/IRSp53_m').n) + sum( + moose.vec('/model/chem/dend/IRSpGr/curv_IRSp53').n), sum( + moose.vec('/model/chem/dend/IRSpGr/IRSp53_m').n + ), sum(moose.vec('/model/chem/dend/IRSpGr/IRSp53_a').n), sum( + moose.vec('/model/chem/dend/IRSpGr/IRSp53_dimer').n), sum( + moose.vec('/model/chem/dend/IRSpGr/curv_IRSp53').n) + allres.append(res) + + print("== Time taken %g s" % (time.time() - t0)) + + # These values are created by GSL based solver. Boost solvers generates + # slightly different values. + gslExpected = [[1.43312300e+04, 3.59179272e-10, 7.90030831e-09, 1.43312300e+04, 0.00000000e+00], + [1.43312300e+04, 5.85016305e-08, 6.01850896e-07, 1.43312300e+04, 0.00000000e+00], + [1.43312300e+04, 1.88782106e-01, 1.78215231e+00, 1.43292591e+04, 0.00000000e+00]] + gslExpected = np.array(gslExpected) + + allres = np.array(allres) + # Compare the last value. When using Boost based solvers these numbers can + # differ a bit but not more than 1%ii. + assert np.allclose(gslExpected, allres, rtol=1e-2, atol=1e-3), (allres, gslExpected) + print('done') + +if __name__ == '__main__': + main() diff --git a/tests/alpha/test_socket_streamer_multitab.py b/devel/fixme/test_socket_streamer_multitab.py similarity index 100% rename from tests/alpha/test_socket_streamer_multitab.py rename to devel/fixme/test_socket_streamer_multitab.py diff --git a/tests/alpha/test_socket_streamer_uds.py b/devel/fixme/test_socket_streamer_uds.py similarity index 100% rename from tests/alpha/test_socket_streamer_uds.py rename to devel/fixme/test_socket_streamer_uds.py diff --git a/tests/issues/hsolve/README b/devel/issues/hsolve/README similarity index 100% rename from tests/issues/hsolve/README rename to devel/issues/hsolve/README diff --git a/tests/issues/hsolve/compare_moose_nrn.py b/devel/issues/hsolve/compare_moose_nrn.py similarity index 100% rename from tests/issues/hsolve/compare_moose_nrn.py rename to devel/issues/hsolve/compare_moose_nrn.py diff --git a/tests/issues/hsolve/h10.CNG.hoc b/devel/issues/hsolve/h10.CNG.hoc similarity index 100% rename from tests/issues/hsolve/h10.CNG.hoc rename to devel/issues/hsolve/h10.CNG.hoc diff --git a/tests/issues/hsolve/h10.CNG.moose.py b/devel/issues/hsolve/h10.CNG.moose.py similarity index 100% rename from tests/issues/hsolve/h10.CNG.moose.py rename to devel/issues/hsolve/h10.CNG.moose.py diff --git a/tests/issues/hsolve/h10.CNG.swc b/devel/issues/hsolve/h10.CNG.swc similarity index 100% rename from tests/issues/hsolve/h10.CNG.swc rename to devel/issues/hsolve/h10.CNG.swc diff --git a/tests/issues/hsolve/run_h10.CNG.hoc b/devel/issues/hsolve/run_h10.CNG.hoc similarity index 100% rename from tests/issues/hsolve/run_h10.CNG.hoc rename to devel/issues/hsolve/run_h10.CNG.hoc diff --git a/tests/issues/issue_124.py b/devel/issues/issue_124.py similarity index 100% rename from tests/issues/issue_124.py rename to devel/issues/issue_124.py diff --git a/tests/issues/issue_239.py b/devel/issues/issue_239.py similarity index 100% rename from tests/issues/issue_239.py rename to devel/issues/issue_239.py diff --git a/tests/issues/issue_34.py b/devel/issues/issue_34.py similarity index 100% rename from tests/issues/issue_34.py rename to devel/issues/issue_34.py diff --git a/tests/issues/issue_45.py b/devel/issues/issue_45.py similarity index 100% rename from tests/issues/issue_45.py rename to devel/issues/issue_45.py diff --git a/tests/issues/issue_47.py b/devel/issues/issue_47.py similarity index 100% rename from tests/issues/issue_47.py rename to devel/issues/issue_47.py diff --git a/tests/issues/issue_93.py b/devel/issues/issue_93.py similarity index 100% rename from tests/issues/issue_93.py rename to devel/issues/issue_93.py diff --git a/diffusion/ConcChanInfo.h b/diffusion/ConcChanInfo.h index 9aeb984b..160915fe 100644 --- a/diffusion/ConcChanInfo.h +++ b/diffusion/ConcChanInfo.h @@ -14,22 +14,26 @@ */ class ConcChanInfo { -public: - ConcChanInfo(); - ConcChanInfo( unsigned int my, unsigned int other, - unsigned int chan, double perm, bool isSwapped ) - : myPool( my ), otherPool( other ), chanPool( chan ), - swapped( isSwapped ), - permeability( perm ) - {;} + public: + ConcChanInfo(); + ConcChanInfo( unsigned int my, unsigned int other, + unsigned int chan, double perm, bool isSwapped, bool _isLocal ) + : myPool( my ), otherPool( other ), chanPool( chan ), + swapped( isSwapped ), + isLocal( _isLocal ), + permeability( perm ) + {;} - unsigned int myPool; - unsigned int otherPool; - unsigned int chanPool; - bool swapped; // Flag records whether myPool/otherPool are - // swapped wrt inPool/outPool. System expects - // that inPool should be in same compt as chanPool. - double permeability; + unsigned int myPool; /// This is not Id, it is internal PoolIndex + /// Obtained using convertIdToPoolIndex. + unsigned int otherPool; /// Internal PoolIndex + unsigned int chanPool; /// Internal PoolIndex + bool swapped; // Flag records whether myPool/otherPool are + // swapped wrt inPool/outPool. System expects + // that inPool should be in same compt as chanPool. + bool isLocal; // Flag, records odd cases where the channel is + // entirely local to one compartment. + double permeability; }; #endif // _CONC_CHAN_INFO_H diff --git a/diffusion/Dsolve.cpp b/diffusion/Dsolve.cpp index d65b528a..11cb34c8 100644 --- a/diffusion/Dsolve.cpp +++ b/diffusion/Dsolve.cpp @@ -42,106 +42,104 @@ const Cinfo* Dsolve::initCinfo() /////////////////////////////////////////////////////// static ValueFinfo< Dsolve, Id > stoich ( - "stoich", - "Stoichiometry object for handling this reaction system.", - &Dsolve::setStoich, - &Dsolve::getStoich - ); + "stoich", + "Stoichiometry object for handling this reaction system.", + &Dsolve::setStoich, + &Dsolve::getStoich + ); static ElementValueFinfo< Dsolve, string > path ( - "path", - "Path of reaction system. Must include all the pools that " - "are to be handled by the Dsolve, can also include other " - "random objects, which will be ignored.", - &Dsolve::setPath, - &Dsolve::getPath - ); + "path", + "Path of reaction system. Must include all the pools that " + "are to be handled by the Dsolve, can also include other " + "random objects, which will be ignored.", + &Dsolve::setPath, + &Dsolve::getPath + ); static ReadOnlyValueFinfo< Dsolve, unsigned int > numVoxels( - "numVoxels", - "Number of voxels in the core reac-diff system, on the " - "current diffusion solver. ", - &Dsolve::getNumVoxels - ); + "numVoxels", + "Number of voxels in the core reac-diff system, on the " + "current diffusion solver. ", + &Dsolve::getNumVoxels + ); static ReadOnlyValueFinfo< Dsolve, unsigned int > numAllVoxels( - "numAllVoxels", - "Number of voxels in the core reac-diff system, on the " - "current diffusion solver. ", - &Dsolve::getNumVoxels - ); - static LookupValueFinfo< - Dsolve, unsigned int, vector< double > > nVec( - "nVec", - "vector of # of molecules along diffusion length, " - "looked up by pool index", - &Dsolve::setNvec, - &Dsolve::getNvec - ); + "numAllVoxels", + "Number of voxels in the core reac-diff system, on the " + "current diffusion solver. ", + &Dsolve::getNumVoxels + ); + + static LookupValueFinfo< Dsolve, unsigned int, vector< double > > nVec( + "nVec", + "vector of # of molecules along diffusion length, " + "looked up by pool index", + &Dsolve::setNvec, + &Dsolve::getNvec + ); static ValueFinfo< Dsolve, unsigned int > numPools( - "numPools", - "Number of molecular pools in the entire reac-diff system, " - "including variable, function and buffered.", - &Dsolve::setNumPools, - &Dsolve::getNumPools - ); + "numPools", + "Number of molecular pools in the entire reac-diff system, " + "including variable, function and buffered.", + &Dsolve::setNumPools, + &Dsolve::getNumPools + ); static ValueFinfo< Dsolve, Id > compartment ( - "compartment", - "Reac-diff compartment in which this diffusion system is " - "embedded.", - &Dsolve::setCompartment, - &Dsolve::getCompartment - ); + "compartment", + "Reac-diff compartment in which this diffusion system is " + "embedded.", + &Dsolve::setCompartment, + &Dsolve::getCompartment + ); static LookupValueFinfo< Dsolve, unsigned int, double > diffVol1 ( - "diffVol1", - "Volume used to set diffusion scaling: firstVol[ voxel# ] " - "Particularly relevant for diffusion between PSD and head.", - &Dsolve::setDiffVol1, - &Dsolve::getDiffVol1 - ); + "diffVol1", + "Volume used to set diffusion scaling: firstVol[ voxel# ] " + "Particularly relevant for diffusion between PSD and head.", + &Dsolve::setDiffVol1, + &Dsolve::getDiffVol1 + ); static LookupValueFinfo< Dsolve, unsigned int, double > diffVol2 ( - "diffVol2", - "Volume used to set diffusion scaling: secondVol[ voxel# ] " - "Particularly relevant for diffusion between spine and dend.", - &Dsolve::setDiffVol2, - &Dsolve::getDiffVol2 - ); + "diffVol2", + "Volume used to set diffusion scaling: secondVol[ voxel# ] " + "Particularly relevant for diffusion between spine and dend.", + &Dsolve::setDiffVol2, + &Dsolve::getDiffVol2 + ); static LookupValueFinfo< Dsolve, unsigned int, double > diffScale ( - "diffScale", - "Geometry term to set diffusion scaling: diffScale[ voxel# ] " - "Here the scaling term is given by cross-section area/length " - "Relevant for diffusion between spine head and dend, or PSD.", - &Dsolve::setDiffScale, - &Dsolve::getDiffScale - ); - + "diffScale", + "Geometry term to set diffusion scaling: diffScale[ voxel# ] " + "Here the scaling term is given by cross-section area/length " + "Relevant for diffusion between spine head and dend, or PSD.", + &Dsolve::setDiffScale, + &Dsolve::getDiffScale + ); - /////////////////////////////////////////////////////// // DestFinfo definitions static DestFinfo process( "process", - "Handles process call", - new ProcOpFunc< Dsolve >( &Dsolve::process ) + "Handles process call", + new ProcOpFunc< Dsolve >( &Dsolve::process ) ); static DestFinfo reinit( "reinit", - "Handles reinit call", - new ProcOpFunc< Dsolve >( &Dsolve::reinit ) + "Handles reinit call", + new ProcOpFunc< Dsolve >( &Dsolve::reinit ) ); static DestFinfo buildMeshJunctions( "buildMeshJunctions", - "Builds junctions between mesh on current Dsolve, and another" - " Dsolve. The meshes have to be compatible. ", - new EpFunc1< Dsolve, Id >(&Dsolve::buildMeshJunctions ) + "Builds junctions between mesh on current Dsolve, and another" + " Dsolve. The meshes have to be compatible. ", + new EpFunc1< Dsolve, Id >(&Dsolve::buildMeshJunctions ) ); static DestFinfo buildNeuroMeshJunctions( "buildNeuroMeshJunctions", "Builds junctions between NeuroMesh, SpineMesh and PsdMesh", - new EpFunc2< Dsolve, Id, Id >(&Dsolve::buildNeuroMeshJunctions ) - ); + new EpFunc2< Dsolve, Id, Id >(&Dsolve::buildNeuroMeshJunctions ) + ); /////////////////////////////////////////////////////// // Shared definitions @@ -158,19 +156,19 @@ const Cinfo* Dsolve::initCinfo() static Finfo* dsolveFinfos[] = { - &stoich, // ElementValue - &path, // ElementValue - &compartment, // Value - &numVoxels, // ReadOnlyValue - &numAllVoxels, // ReadOnlyValue - &nVec, // LookupValue - &numPools, // Value - &diffVol1, // LookupValue - &diffVol2, // LookupValue - &diffScale, // LookupValue - &buildMeshJunctions, // DestFinfo - &buildNeuroMeshJunctions, // DestFinfo - &proc, // SharedFinfo + &stoich, // ElementValue + &path, // ElementValue + &compartment, // Value + &numVoxels, // ReadOnlyValue + &numAllVoxels, // ReadOnlyValue + &nVec, // LookupValue + &numPools, // Value + &diffVol1, // LookupValue + &diffVol2, // LookupValue + &diffScale, // LookupValue + &buildMeshJunctions, // DestFinfo + &buildNeuroMeshJunctions, // DestFinfo + &proc, // SharedFinfo }; static Dinfo< Dsolve > dinfo; @@ -187,11 +185,8 @@ const Cinfo* Dsolve::initCinfo() static const Cinfo* dsolveCinfo = Dsolve::initCinfo(); -////////////////////////////////////////////////////////////// // Class definitions -////////////////////////////////////////////////////////////// -Dsolve::Dsolve() - : +Dsolve::Dsolve() : dt_( -1.0 ), numTotPools_( 0 ), numLocalPools_( 0 ), @@ -412,6 +407,8 @@ void Dsolve::calcJnChan( const DiffJunction& jn, Dsolve* other, double dt ) for ( unsigned int i = 0; i < jn.myChannels.size(); ++i ) { + if ( channels_[ jn.myChannels[i] ].isLocal ) + continue; ConcChanInfo& myChan = channels_[ jn.myChannels[i] ]; DiffPoolVec& myDv = pools_[ myChan.myPool ]; DiffPoolVec& otherDv = other->pools_[ myChan.otherPool ]; @@ -424,12 +421,12 @@ void Dsolve::calcJnChan( const DiffJunction& jn, Dsolve* other, double dt ) double lastN = myN; double otherN = otherDv.getN( j->second ); double chanN = chanDv.getN( j->first ); - // Stick in a conversion factor for the myN and otherN into - // concentrations. Note that SI is millimolar. - double perm = myChan.permeability * chanN * 1000.0 / NA; + // Stick in a conversion factor for the myN and otherN into + // concentrations. Note that SI is millimolar. + double perm = myChan.permeability * chanN / NA; myN = integ( myN, perm * myN/j->firstVol, perm * otherN/j->secondVol, dt ); - otherN += lastN - myN; // Mass consv + otherN += lastN - myN; // Mass consv if ( otherN < 0.0 ) // Avoid negatives { myN += otherN; @@ -446,6 +443,8 @@ void Dsolve::calcOtherJnChan( const DiffJunction& jn, Dsolve* other, double dt ) { for ( unsigned int i = 0; i < jn.otherChannels.size(); ++i ) { + if ( other->channels_[ jn.otherChannels[i] ].isLocal ) + continue; ConcChanInfo& otherChan = other->channels_[ jn.otherChannels[i] ]; // This is the DiffPoolVec for the pools on the other Dsolve, // the one with the channel. @@ -463,12 +462,12 @@ void Dsolve::calcOtherJnChan( const DiffJunction& jn, Dsolve* other, double dt ) double lastN = myN; double otherN = otherDv.getN( j->second ); double chanN = chanDv.getN( j->second ); - // Stick in a conversion factor for the myN and otherN into - // concentrations. Note that SI is millimolar. - double perm = otherChan.permeability * chanN * 1000.0 / NA; + // Stick in a conversion factor for the myN and otherN into + // concentrations. Note that SI is millimolar. + double perm = otherChan.permeability * chanN / NA; myN = integ( myN, perm * myN/j->firstVol, perm * otherN/j->secondVol, dt ); - otherN += lastN - myN; // Mass consv + otherN += lastN - myN; // Mass consv if ( otherN < 0.0 ) // Avoid negatives { myN += otherN; @@ -480,6 +479,49 @@ void Dsolve::calcOtherJnChan( const DiffJunction& jn, Dsolve* other, double dt ) } } +void Dsolve::calcLocalChan( double dt ) +{ + // There may be some chans which connect within the compartment. + // This is odd biologically, but happens for modelling convenience. + // The channels have a flag indicating if this is so. It is a simple + // calculation, but lacks numerical accuracy as it is outside the + // solver framework. + + ChemCompt* cc = reinterpret_cast< ChemCompt* >( compartment_.eref().data() ); + const vector< double >& vols = cc->vGetVoxelVolume(); + for (auto ch = channels_.begin(); ch != channels_.end(); ++ch ) + { + if ( ch->isLocal ) + { + DiffPoolVec& myDv = pools_[ ch->myPool ]; + DiffPoolVec& otherDv = pools_[ ch->otherPool ]; + DiffPoolVec& chanDv = pools_[ ch->chanPool ]; + assert( myDv.getNumVoxels() == numVoxels_ ); + for (unsigned int i = 0; i < numVoxels_; ++i ) + { + double myN = myDv.getN( i ); + double lastN = myN; + double otherN = otherDv.getN( i ); + double chanN = chanDv.getN( i ); + double vol = vols[i]; + // Stick in a conversion factor for the myN and otherN into + // concentrations. Note that SI is millimolar. + double perm = ch->permeability * chanN / NA; + myN = integ( myN, perm * myN/vol, perm * otherN/vol, dt ); + otherN += lastN - myN; // Mass consv + if ( otherN < 0.0 ) // Avoid negatives + { + myN += otherN; + otherN = 0.0; + } + myDv.setN( i, myN ); + otherDv.setN( i, otherN ); + } + } + } +} + + /** * Computes flux through a junction between diffusion solvers. * Most used at junctions on spines and PSDs, but can also be used @@ -525,6 +567,7 @@ void Dsolve::reinit( const Eref& e, ProcPtr p ) void Dsolve::updateJunctions( double dt ) { + calcLocalChan( dt ); for (auto i = junctions_.begin(); i != junctions_.end(); ++i ) calcJunction( *i, dt ); } @@ -532,7 +575,7 @@ void Dsolve::updateJunctions( double dt ) void Dsolve::calcJunction_chunk( const size_t begin, const size_t end, double dt ) { - for (size_t i = begin; i < min(end, junctions_.size()); i++) + for (size_t i = begin; i < min(end, junctions_.size()); i++) calcJunction( junctions_[i], dt ); } @@ -566,8 +609,7 @@ void Dsolve::setStoich( Id id ) // assert( poolIndex < pools_.size() ); Id pid( i + poolMapStart_ ); assert( pid.element()->cinfo()->isA( "PoolBase" ) ); - PoolBase* pb = - reinterpret_cast< PoolBase* >( pid.eref().data()); + PoolBase* pb = reinterpret_cast< PoolBase* >( pid.eref().data()); double diffConst = pb->getDiffConst( pid.eref() ); double motorConst = pb->getMotorConst( pid.eref() ); pools_[ poolIndex ].setId( pid.value() ); @@ -575,9 +617,9 @@ void Dsolve::setStoich( Id id ) pools_[ poolIndex ].setMotorConst( motorConst ); /* cout << i << " poolIndex=" << poolIndex << - ", id=" << pid.value() << - ", name=" << pid.element()->getName() << endl; - */ + ", id=" << pid.value() << + ", name=" << pid.element()->getName() << endl; + */ } } string chanpath = path_ + "[ISA=ConcChan]"; @@ -614,7 +656,8 @@ void Dsolve::fillConcChans( const vector< ObjId >& chans ) ret.clear(); unsigned int outPoolValue = outPool.id.value(); bool swapped = false; - if ( !( inPool.bad() or chanPool.bad() ) ) + bool isLocal = false; + if ( !( inPool.bad() || chanPool.bad() ) ) { unsigned int inPoolIndex = convertIdToPoolIndex( inPool.id ); unsigned int chanPoolIndex = convertIdToPoolIndex(chanPool.id); @@ -624,13 +667,24 @@ void Dsolve::fillConcChans( const vector< ObjId >& chans ) outPoolValue = inPool.id.value(); swapped = true; } + else + { + unsigned int outPoolIndex = convertIdToPoolIndex( outPool.id ); + // edge case where both in and out are on same compartment. + // Not much sense in bio, but a common convenience hack. + if ( outPoolIndex != ~0U ) + { + outPoolValue = outPoolIndex; + isLocal = true; + } + + } if ( ( inPoolIndex != ~0U) && (chanPoolIndex != ~0U ) ) { ConcChanInfo cci( inPoolIndex, outPoolValue, chanPoolIndex, Field< double >::get( *i, "permeability" ), - ////// Fix it below //////// - swapped + swapped, isLocal ); channels_.push_back( cci ); } @@ -878,13 +932,13 @@ void printJunction( Id self, Id other, const DiffJunction& jn ) cout << "Junction between " << self.path() << ", " << other.path() << endl; cout << "Pool indices: myPools, otherPools\n"; for ( unsigned int i = 0; i < jn.myPools.size(); ++i ) - cout << i << " " << jn.myPools[i] << " " << jn.otherPools[i] << endl; - cout << "Voxel junctions: first second firstVol secondVol diffScale\n"; + cout << i << " " << jn.myPools[i] << " " << jn.otherPools[i] << endl; + cout << "Voxel junctions: first second firstVol secondVol diffScale\n"; for ( unsigned int i = 0; i < jn.vj.size(); ++i ) { - cout << i << " " << jn.vj[i].first << " " << jn.vj[i].second << - " " << jn.vj[i].firstVol << " " << jn.vj[i].secondVol << - " " << jn.vj[i].diffScale << endl; + cout << i << " " << jn.vj[i].first << " " << jn.vj[i].second << + " " << jn.vj[i].firstVol << " " << jn.vj[i].secondVol << + " " << jn.vj[i].diffScale << endl; } } @@ -923,7 +977,7 @@ void Dsolve::mapDiffPoolsBetweenDsolves( DiffJunction& jn, * For example, if we had an enzyme in compartment 'src', whose product * should go to pool 'bar' in compartment 'dest', * the name of the enzyme product in compartment src would be - * bar_xfer_dest + * bar_xfer_dest */ void Dsolve::mapXfersBetweenDsolves( vector< unsigned int >& srcPools, vector< unsigned int >& destPools, @@ -972,26 +1026,36 @@ void Dsolve::mapChansBetweenDsolves( DiffJunction& jn, Id self, Id other) unsigned int outIndex; for ( unsigned int i = 0; i < ch.size(); ++i ) { - unsigned int chanIndex = ch[i].chanPool; - outIndex = otherSolve->convertIdToPoolIndex( ch[i].otherPool ); - if ( (outIndex != ~0U) && (chanIndex != ~0U ) ) + if ( ch[i].isLocal ) { jn.myChannels.push_back(i); - ch[i].otherPool = outIndex; // replace the Id with the index. - ch[i].chanPool = chanIndex; //chanIndex may be on either Dsolve + } + else + { + outIndex = otherSolve->convertIdToPoolIndex( ch[i].otherPool ); + if (outIndex != ~0U) + { + ch[i].otherPool = outIndex; // replace Id with the index. + jn.myChannels.push_back(i); + } } } // Now set up the other Dsolve. vector< ConcChanInfo >& ch2 = otherSolve->channels_; for ( unsigned int i = 0; i < ch2.size(); ++i ) { - unsigned int chanIndex = ch2[i].chanPool; - outIndex = selfSolve->convertIdToPoolIndex( ch2[i].otherPool ); - if ( (outIndex != ~0U) && (chanIndex != ~0U) ) + if ( ch2[i].isLocal ) { jn.otherChannels.push_back(i); - ch2[i].otherPool = outIndex; // replace the Id with the index - ch2[i].chanPool = chanIndex; //chanIndex may be on either Dsolve + } + else + { + outIndex = selfSolve->convertIdToPoolIndex( ch2[i].otherPool ); + if ( outIndex != ~0U ) + { + ch2[i].otherPool = outIndex; // replace Id with the index + jn.otherChannels.push_back(i); + } } } } @@ -1063,15 +1127,19 @@ void Dsolve::setNumAllVoxels( unsigned int num ) unsigned int Dsolve::convertIdToPoolIndex( const Id id ) const { + bool verbose = false; unsigned int i = id.value() - poolMapStart_; if ( i < poolMap_.size() ) { return poolMap_[i]; } - cout << "Warning: Dsolve::convertIdToPoollndex: Id out of range, (" << - poolMapStart_ << ", " << id << ", " << id.path() << ", " << - poolMap_.size() + poolMapStart_ << "\n"; - return 0; + if ( verbose ) + { + cout << "Warning: Dsolve::convertIdToPoollndex: Id out of range, (" << + poolMapStart_ << ", " << id << ", " << id.path() << ", " << + poolMap_.size() + poolMapStart_ << "\n"; + } + return ~0U; } unsigned int Dsolve::convertIdToPoolIndex( const Eref& e ) const @@ -1083,7 +1151,7 @@ void Dsolve::setN( const Eref& e, double v ) { unsigned int pid = convertIdToPoolIndex( e ); // Ignore silently, as this may be a valid pid for the ksolve to use. - if ( pid >= pools_.size() ) + if ( pid == ~0U || pid >= pools_.size() ) return; unsigned int vox = e.dataIndex(); if ( vox < numVoxels_ ) @@ -1098,7 +1166,7 @@ void Dsolve::setN( const Eref& e, double v ) double Dsolve::getN( const Eref& e ) const { unsigned int pid = convertIdToPoolIndex( e ); - if ( pid >= pools_.size() ) return 0.0; // ignore silently + if ( pid == ~0U || pid >= pools_.size() ) return 0.0; //ignore silently unsigned int vox = e.dataIndex(); if ( vox < numVoxels_ ) { @@ -1112,7 +1180,7 @@ double Dsolve::getN( const Eref& e ) const void Dsolve::setNinit( const Eref& e, double v ) { unsigned int pid = convertIdToPoolIndex( e ); - if ( pid >= pools_.size() ) // Ignore silently + if ( pid == ~0U || pid >= pools_.size() ) // Ignore silently return; unsigned int vox = e.dataIndex(); if ( vox < numVoxels_ ) @@ -1127,7 +1195,7 @@ void Dsolve::setNinit( const Eref& e, double v ) double Dsolve::getNinit( const Eref& e ) const { unsigned int pid = convertIdToPoolIndex( e ); - if ( pid >= pools_.size() ) return 0.0; // ignore silently + if ( pid == ~0U || pid >= pools_.size() ) return 0.0; //ignore silently unsigned int vox = e.dataIndex(); if ( vox < numVoxels_ ) { @@ -1141,36 +1209,52 @@ double Dsolve::getNinit( const Eref& e ) const void Dsolve::setDiffConst( const Eref& e, double v ) { unsigned int pid = convertIdToPoolIndex( e ); - if ( pid >= pools_.size() ) // Ignore silently, out of range. + if ( pid == ~0U || pid >= pools_.size() ) // Ignore silently, out of range. return; - pools_[ convertIdToPoolIndex( e ) ].setDiffConst( v ); + pools_[ pid ].setDiffConst( v ); } double Dsolve::getDiffConst( const Eref& e ) const { unsigned int pid = convertIdToPoolIndex( e ); - if ( pid >= pools_.size() ) // Ignore silently, out of range. + if ( pid == ~0U || pid >= pools_.size() ) // Ignore silently, out of range. return 0.0; - return pools_[ convertIdToPoolIndex( e ) ].getDiffConst(); + return pools_[ pid ].getDiffConst(); } void Dsolve::setMotorConst( const Eref& e, double v ) { unsigned int pid = convertIdToPoolIndex( e ); - if ( pid >= pools_.size() ) // Ignore silently, out of range. + if ( pid == ~0U || pid >= pools_.size() ) // Ignore silently, out of range. return; - pools_[ convertIdToPoolIndex( e ) ].setMotorConst( v ); + pools_[ pid ].setMotorConst( v ); } -void Dsolve::setNumPools( unsigned int numPoolSpecies ) +void Dsolve::setNumVarTotPools( unsigned int var, unsigned int tot ) { // Decompose numPoolSpecies here, assigning some to each node. - numTotPools_ = numPoolSpecies; - numLocalPools_ = numPoolSpecies; + numTotPools_ = tot; + numLocalPools_ = var; poolStartIndex_ = 0; - pools_.resize( numLocalPools_ ); - for ( unsigned int i = 0 ; i < numLocalPools_; ++i ) + pools_.resize( numTotPools_ ); + for ( unsigned int i = 0 ; i < numTotPools_; ++i ) + { + pools_[i].setNumVoxels( numVoxels_ ); + // pools_[i].setId( reversePoolMap_[i] ); + // pools_[i].setParent( me ); + } +} + +void Dsolve::setNumPools( unsigned int numVarPoolSpecies ) +{ + // Decompose numPoolSpecies here, assigning some to each node. + numTotPools_ = numVarPoolSpecies; + numLocalPools_ = numVarPoolSpecies; + poolStartIndex_ = 0; + + pools_.resize( numTotPools_ ); + for ( unsigned int i = 0 ; i < numTotPools_; ++i ) { pools_[i].setNumVoxels( numVoxels_ ); // pools_[i].setId( reversePoolMap_[i] ); diff --git a/diffusion/Dsolve.h b/diffusion/Dsolve.h index dc013d3c..e6b911ff 100644 --- a/diffusion/Dsolve.h +++ b/diffusion/Dsolve.h @@ -136,6 +136,8 @@ class Dsolve: public ZombiePoolInterface void setNumPools( unsigned int num ); unsigned int getNumPools() const; + void setNumVarTotPools( unsigned int var, unsigned int tot ); + unsigned int getNumLocalVoxels() const; VoxelPoolsBase* pools( unsigned int i ); double volume( unsigned int i ) const; @@ -185,6 +187,7 @@ class Dsolve: public ZombiePoolInterface void calcJnChan( const DiffJunction& jn, Dsolve* other, double dt ); void calcOtherJnChan( const DiffJunction& jn, Dsolve* other, double dt ); + void calcLocalChan( double dt ); void fillConcChans( const vector< ObjId >& chans ); /** diff --git a/diffusion/FastMatrixElim.h b/diffusion/FastMatrixElim.h index e05fa4b1..15ebb5e8 100644 --- a/diffusion/FastMatrixElim.h +++ b/diffusion/FastMatrixElim.h @@ -9,110 +9,110 @@ class FastMatrixElim: public SparseMatrix< double > { - public: - FastMatrixElim(); - FastMatrixElim( unsigned int nrows, unsigned int ncolumns ); - FastMatrixElim( const SparseMatrix< double >& orig ); +public: + FastMatrixElim(); + FastMatrixElim( unsigned int nrows, unsigned int ncolumns ); + FastMatrixElim( const SparseMatrix< double >& orig ); - void makeTestMatrix( const double* test, unsigned int numCompts ); + void makeTestMatrix( const double* test, unsigned int numCompts ); - /** - * Recursively scans the current matrix, to build tree of parent - * voxels using the contents of the sparase matrix to indicate - * connectivity. Emits warning noises and returns an empty vector if - * the entire tree cannot be traversed, or - * if the current matrix is not tree-like. - * Assumes row 0 is root row. User should always call with - * parentRow == 0; - * Doesn't work yet. - bool buildTree( unsigned int parentRow, - vector< unsigned int >& parentVoxel ) const; - */ + /** + * Recursively scans the current matrix, to build tree of parent + * voxels using the contents of the sparase matrix to indicate + * connectivity. Emits warning noises and returns an empty vector if + * the entire tree cannot be traversed, or + * if the current matrix is not tree-like. + * Assumes row 0 is root row. User should always call with + * parentRow == 0; + * Doesn't work yet. + bool buildTree( unsigned int parentRow, + vector< unsigned int >& parentVoxel ) const; + */ - /** - * Reduces the forward elimination phase into a series of operations - * defined by the fops vector. - */ - void buildForwardElim( vector< unsigned int >& diag, - vector< Triplet< double > >& fops ); - /** - * Reduces the backward substitution phase into a series of - * operations defined by the bops vector, and by the list of - * values on the diagonal. - */ - void buildBackwardSub( vector< unsigned int >& diag, - vector< Triplet< double > >& bops, vector< double >& diagVal ); - ///////////////////////////////////////////////////////////// - // Here we do stuff to set up the Hines ordering of the matrix. - ///////////////////////////////////////////////////////////// - /** - * Takes the tree specification in the form of a list of parent - * entries for each tree node, and reorders the matrix into the - * twig-first sequence required for fast elimination. - * Returns true if it succeeded in doing this; many matrices will - * not reorder correctly. - */ - bool hinesReorder( const vector< unsigned int >& parentVoxel, - vector< unsigned int >& lookupOldRowsFromNew ); + /** + * Reduces the forward elimination phase into a series of operations + * defined by the fops vector. + */ + void buildForwardElim( vector< unsigned int >& diag, + vector< Triplet< double > >& fops ); + /** + * Reduces the backward substitution phase into a series of + * operations defined by the bops vector, and by the list of + * values on the diagonal. + */ + void buildBackwardSub( vector< unsigned int >& diag, + vector< Triplet< double > >& bops, vector< double >& diagVal ); + ///////////////////////////////////////////////////////////// + // Here we do stuff to set up the Hines ordering of the matrix. + ///////////////////////////////////////////////////////////// + /** + * Takes the tree specification in the form of a list of parent + * entries for each tree node, and reorders the matrix into the + * twig-first sequence required for fast elimination. + * Returns true if it succeeded in doing this; many matrices will + * not reorder correctly. + */ + bool hinesReorder( const vector< unsigned int >& parentVoxel, + vector< unsigned int >& lookupOldRowsFromNew ); - /** - * static function. Reorders the ops and diagVal vectors so as to - * restore the original indexing of the input vectors. - */ - static void opsReorder( - const vector< unsigned int >& lookupOldRowsFromNew, - vector< Triplet< double > >& ops, - vector< double >& diagVal ); + /** + * static function. Reorders the ops and diagVal vectors so as to + * restore the original indexing of the input vectors. + */ + static void opsReorder( + const vector< unsigned int >& lookupOldRowsFromNew, + vector< Triplet< double > >& ops, + vector< double >& diagVal ); - /** - * Reorders rows of the matrix according to the vector - * lookupOldRowFromNew. The vector tells the function which old - * row to put in the ith row of the new matrix. Since the - * matrix has matching column entries, those get shuffled too. - */ - void shuffleRows( - const vector< unsigned int >& lookupOldRowFromNew ); + /** + * Reorders rows of the matrix according to the vector + * lookupOldRowFromNew. The vector tells the function which old + * row to put in the ith row of the new matrix. Since the + * matrix has matching column entries, those get shuffled too. + */ + void shuffleRows( + const vector< unsigned int >& lookupOldRowFromNew ); - /** - * Checks that the matrix shape (but not necessarily values) - * are symmetric, returns true if symmetric. - */ - bool checkSymmetricShape() const; + /** + * Checks that the matrix shape (but not necessarily values) + * are symmetric, returns true if symmetric. + */ + bool checkSymmetricShape() const; - bool operator==( const FastMatrixElim& other ) const; - bool isSymmetric() const; + bool operator==( const FastMatrixElim& other ) const; + bool isSymmetric() const; - /** - * This function incorporates molecule-specific diffusion and - * motor transport terms into the matrix. - */ - void setDiffusionAndTransport( - const vector< unsigned int >& parentVoxel, - double diffConst, double motorConst, double dt ); + /** + * This function incorporates molecule-specific diffusion and + * motor transport terms into the matrix. + */ + void setDiffusionAndTransport( + const vector< unsigned int >& parentVoxel, + double diffConst, double motorConst, double dt ); - /** - * This function makes the matrix for computing diffusion and - * transport equations. - */ - bool buildForDiffusion( - const vector< unsigned int >& parentVoxel, - const vector< double >& volume, - const vector< double >& area, - const vector< double >& length, - double diffConst, double motorConst, double dt ); + /** + * This function makes the matrix for computing diffusion and + * transport equations. + */ + bool buildForDiffusion( + const vector< unsigned int >& parentVoxel, + const vector< double >& volume, + const vector< double >& area, + const vector< double >& length, + double diffConst, double motorConst, double dt ); - /** - * Does the actual computation of the matrix inversion, which is - * equivalent to advancing one timestem in Backward Euler. - * Static function here to keep namespaces clean. - */ - static void advance( vector< double >& y, - const vector< Triplet< double > >& ops, //has both fops and bops - const vector< double >& diagVal ); + /** + * Does the actual computation of the matrix inversion, which is + * equivalent to advancing one timestem in Backward Euler. + * Static function here to keep namespaces clean. + */ + static void advance( vector< double >& y, + const vector< Triplet< double > >& ops, //has both fops and bops + const vector< double >& diagVal ); }; void sortByColumn( - vector< unsigned int >& col, vector< double >& entry ); + vector< unsigned int >& col, vector< double >& entry ); // Todo: Maintain an internal vector of the mapping between rows so that // the output vector can be updated in the right order, and input values diff --git a/diffusion/testDiffusion.cpp b/diffusion/testDiffusion.cpp index b4ad4170..b11bcf23 100644 --- a/diffusion/testDiffusion.cpp +++ b/diffusion/testDiffusion.cpp @@ -27,18 +27,19 @@ using namespace std; double checkAns( - const double* m, unsigned int numCompts, - const double* ans, const double* rhs ) + const double* m, unsigned int numCompts, + const double* ans, const double* rhs ) { - vector< double > check( numCompts, 0.0 ); - for ( unsigned int i = 0; i < numCompts; ++i ) { - for ( unsigned int j = 0; j < numCompts; ++j ) - check[i] += m[i*numCompts + j] * ans[j]; - } - double ret = 0.0; - for ( unsigned int i = 0; i < numCompts; ++i ) - ret += (check[i] - rhs[i]) * (check[i] - rhs[i] ); - return ret; + vector< double > check( numCompts, 0.0 ); + for ( unsigned int i = 0; i < numCompts; ++i ) + { + for ( unsigned int j = 0; j < numCompts; ++j ) + check[i] += m[i*numCompts + j] * ans[j]; + } + double ret = 0.0; + for ( unsigned int i = 0; i < numCompts; ++i ) + ret += (check[i] - rhs[i]) * (check[i] - rhs[i] ); + return ret; } @@ -47,425 +48,439 @@ void testFastMatrixElim() { -/* -2 11 - 1 4 - 3 10 - 9 5 - 6 - 7 - 8 - - 1 2 3 4 5 6 7 8 9 10 11 -1 x x x x -2 x x -3 x x x x -4 x x x x -5 x x x x -6 x x x x -7 x x x -8 x x -9 x x x x -10 x x -11 x x - static double test[] = { - 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, - 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 7, 0, 8, 9, 0, 0, 0, 0, 10, 0, 0, - 11, 0, 12, 13, 0, 0, 0, 0, 0, 0, 14, - 0, 0, 0, 0, 15, 16, 0, 0, 17, 18, 0, - 0, 0, 0, 0, 19, 20, 21, 0, 22, 0, 0, - 0, 0, 0, 0, 0, 23, 24, 25, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 26, 27, 0, 0, 0, - 0, 0, 28, 0, 29, 30, 0, 0, 31, 0, 0, - 0, 0, 0, 0, 32, 0, 0, 0, 0, 33, 0, - 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 35, - }; - const unsigned int numCompts = 11; -// static unsigned int parents[] = { 3,1,9,3,6,7,8,-1,6,5,4 }; - static unsigned int parents[] = { 2,0,8,2,5,6,7,-1,5,4,3 }; -*/ - -/* -1 3 - 2 4 - 7 5 - 8 6 - 9 - 10 - 11 - - 1 2 3 4 5 6 7 8 9 10 11 -1 x x -2 x x x -3 x x -4 x x x -5 x x -6 x x x -7 x x x x -8 x x x -9 x x x x -10 x x x -11 x x - static double test[] = { - 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 3, 4, 0, 0, 0, 0, 5, 0, 0, 0, 0, - 0, 0, 6, 7, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 8, 9, 0, 0, 10, 0, 0, 0, 0, - 0, 0, 0, 0, 11, 12, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 13, 14, 0, 0, 15, 0, 0, - 0, 16, 0, 17, 0, 0, 18, 19, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 20, 21, 22, 0, 0, - 0, 0, 0, 0, 0, 23, 0, 24, 25, 26, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 27, 28, 29, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 31, - }; - const unsigned int numCompts = 11; - static unsigned int parents[] = { 1,6,3,6,5,8,7,8,9,10,-1}; -*/ - -/* -Linear cable, 12 segments. -*/ - - static double test[] = { - 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 9, 10, 11, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 12, 13, 14, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 15, 16, 17, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 18, 19, 20, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 21, 22, 23, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 24, 25, 26, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 27, 28, 29, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 31, 32, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 34, - }; - const unsigned int numCompts = 12; - static unsigned int parents[] = { 1,2,3,4,5,6,7,8,9,10,11, unsigned(-1)}; - - /* - static double test[] = { - 1, 2, - 3, 4 - }; - const unsigned int numCompts = 2; - static double test[] = { - 1, 2, 0, 0, - 3, 4, 5, 0, - 0, 6, 7, 8, - 0, 0, 9, 10 - }; - const unsigned int numCompts = 4; - static double test[] = { - 1, 2, 0, 0, 0, 0, - 3, 4, 5, 0, 0, 0, - 0, 6, 7, 8, 0, 0, - 0, 0, 9, 10, 11, 0, - 0, 0, 0, 12, 13, 14, - 0, 0, 0, 0, 15, 16, - }; - const unsigned int numCompts = 6; - static double test[] = { - 1, 2, 0, 0, 0, 0, - 3, 4, 0, 0, 1, 0, - 0, 0, 7, 8, 0, 0, - 0, 0, 9, 10, 11, 0, - 0, 1, 0, 12, 13, 14, - 0, 0, 0, 0, 15, 16, - }; - const unsigned int numCompts = 6; - */ - // testSorting(); // seems to work fine. - FastMatrixElim fe; - vector< Triplet< double > > fops; - fe.makeTestMatrix( test, numCompts ); - // fe.print(); - vector< unsigned int > parentVoxel; - vector< unsigned int > lookupOldRowsFromNew; - parentVoxel.insert( parentVoxel.begin(), &parents[0], &parents[numCompts] ); - fe.hinesReorder( parentVoxel, lookupOldRowsFromNew ); - /* - */ - /* - vector< unsigned int > shuf; - for ( unsigned int i = 0; i < numCompts; ++i ) - shuf.push_back( i ); - shuf[0] = 1; - shuf[1] = 0; - fe.shuffleRows( shuf ); - */ - // fe.print(); - FastMatrixElim foo = fe; - - vector< unsigned int > diag; - vector< double > diagVal; - fe.buildForwardElim( diag, fops ); - // fe.print(); - fe.buildBackwardSub( diag, fops, diagVal ); - vector< double > y( numCompts, 1.0 ); - vector< double > ones( numCompts, 1.0 ); - FastMatrixElim::advance( y, fops, diagVal ); - /* - for ( unsigned int i = 0; i < numCompts; ++i ) - cout << "y" << i << "]= " << y[i] << endl; - */ - - // Here we verify the answer - - vector< double > alle; - for( unsigned int i = 0; i < numCompts; ++i ) { - for( unsigned int j = 0; j < numCompts; ++j ) { - alle.push_back( foo.get( i, j ) ); - } - } - // cout << "myCode: " << checkAns( &alle[0], numCompts, &y[0], &ones[0] ) << endl; - - assert( checkAns( &alle[0], numCompts, &y[0], &ones[0] ) < 1e-25 ); + /* + 2 11 + 1 4 + 3 10 + 9 5 + 6 + 7 + 8 + + 1 2 3 4 5 6 7 8 9 10 11 + 1 x x x x + 2 x x + 3 x x x x + 4 x x x x + 5 x x x x + 6 x x x x + 7 x x x + 8 x x + 9 x x x x + 10 x x + 11 x x + static double test[] = { + 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, + 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 8, 9, 0, 0, 0, 0, 10, 0, 0, + 11, 0, 12, 13, 0, 0, 0, 0, 0, 0, 14, + 0, 0, 0, 0, 15, 16, 0, 0, 17, 18, 0, + 0, 0, 0, 0, 19, 20, 21, 0, 22, 0, 0, + 0, 0, 0, 0, 0, 23, 24, 25, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 26, 27, 0, 0, 0, + 0, 0, 28, 0, 29, 30, 0, 0, 31, 0, 0, + 0, 0, 0, 0, 32, 0, 0, 0, 0, 33, 0, + 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 35, + }; + const unsigned int numCompts = 11; + // static unsigned int parents[] = { 3,1,9,3,6,7,8,-1,6,5,4 }; + static unsigned int parents[] = { 2,0,8,2,5,6,7,-1,5,4,3 }; + */ + + /* + 1 3 + 2 4 + 7 5 + 8 6 + 9 + 10 + 11 + + 1 2 3 4 5 6 7 8 9 10 11 + 1 x x + 2 x x x + 3 x x + 4 x x x + 5 x x + 6 x x x + 7 x x x x + 8 x x x + 9 x x x x + 10 x x x + 11 x x + static double test[] = { + 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 4, 0, 0, 0, 0, 5, 0, 0, 0, 0, + 0, 0, 6, 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8, 9, 0, 0, 10, 0, 0, 0, 0, + 0, 0, 0, 0, 11, 12, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 13, 14, 0, 0, 15, 0, 0, + 0, 16, 0, 17, 0, 0, 18, 19, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 20, 21, 22, 0, 0, + 0, 0, 0, 0, 0, 23, 0, 24, 25, 26, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 27, 28, 29, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 31, + }; + const unsigned int numCompts = 11; + static unsigned int parents[] = { 1,6,3,6,5,8,7,8,9,10,-1}; + */ + + /* + Linear cable, 12 segments. + */ + + static double test[] = + { + 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 10, 11, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 12, 13, 14, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 15, 16, 17, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 18, 19, 20, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 21, 22, 23, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 24, 25, 26, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 27, 28, 29, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 31, 32, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 34, + }; + const unsigned int numCompts = 12; + static unsigned int parents[] = { 1,2,3,4,5,6,7,8,9,10,11, unsigned(-1)}; + + /* + static double test[] = { + 1, 2, + 3, 4 + }; + const unsigned int numCompts = 2; + static double test[] = { + 1, 2, 0, 0, + 3, 4, 5, 0, + 0, 6, 7, 8, + 0, 0, 9, 10 + }; + const unsigned int numCompts = 4; + static double test[] = { + 1, 2, 0, 0, 0, 0, + 3, 4, 5, 0, 0, 0, + 0, 6, 7, 8, 0, 0, + 0, 0, 9, 10, 11, 0, + 0, 0, 0, 12, 13, 14, + 0, 0, 0, 0, 15, 16, + }; + const unsigned int numCompts = 6; + static double test[] = { + 1, 2, 0, 0, 0, 0, + 3, 4, 0, 0, 1, 0, + 0, 0, 7, 8, 0, 0, + 0, 0, 9, 10, 11, 0, + 0, 1, 0, 12, 13, 14, + 0, 0, 0, 0, 15, 16, + }; + const unsigned int numCompts = 6; + */ + // testSorting(); // seems to work fine. + FastMatrixElim fe; + vector< Triplet< double > > fops; + fe.makeTestMatrix( test, numCompts ); + // fe.print(); + vector< unsigned int > parentVoxel; + vector< unsigned int > lookupOldRowsFromNew; + parentVoxel.insert( parentVoxel.begin(), &parents[0], &parents[numCompts] ); + fe.hinesReorder( parentVoxel, lookupOldRowsFromNew ); + /* + */ + /* + vector< unsigned int > shuf; + for ( unsigned int i = 0; i < numCompts; ++i ) + shuf.push_back( i ); + shuf[0] = 1; + shuf[1] = 0; + fe.shuffleRows( shuf ); + */ + // fe.print(); + FastMatrixElim foo = fe; + + vector< unsigned int > diag; + vector< double > diagVal; + fe.buildForwardElim( diag, fops ); + fe.buildBackwardSub( diag, fops, diagVal ); + + // cout << endl << "fe" << endl; + // fe.print(); + // cout << "foo" << endl; + // foo.print( ); + + vector< double > y( numCompts, 1.0 ); + vector< double > ones( numCompts, 1.0 ); + FastMatrixElim::advance( y, fops, diagVal ); + + // Here we verify the answer + // cout << " row " << foo.nRows() << " cols " << foo.nColumns() << endl; + vector< double > alle; + + for( size_t i = 0; i < numCompts; ++i ) + for( size_t j = 0; j < numCompts; ++j ) + { + double x = foo.get(i, j); + alle.push_back( x ); + } + + // cout << "myCode: " << checkAns( alle.data(), numCompts, y.data(), ones.data() ) << endl; + + assert(checkAns( &alle[0], numCompts, &y[0], &ones[0] ) < 1e-25); #if USE_GSL - ///////////////////////////////////////////////////////////////////// - // Here we do the gsl test. - vector< double > temp( &test[0], &test[numCompts*numCompts] ); - gsl_matrix_view m = gsl_matrix_view_array( &temp[0], numCompts, numCompts ); - - vector< double > z( numCompts, 1.0 ); - gsl_vector_view b = gsl_vector_view_array( &z[0], numCompts ); - gsl_vector* x = gsl_vector_alloc( numCompts ); - int s; - gsl_permutation* p = gsl_permutation_alloc( numCompts ); - gsl_linalg_LU_decomp( &m.matrix, p, &s ); - gsl_linalg_LU_solve( &m.matrix, p, &b.vector, x); - vector< double > gslAns( numCompts ); - for ( unsigned int i = 0; i < numCompts; ++i ) { - gslAns[i] = gsl_vector_get( x, i ); - // cout << "x[" << i << "]= " << gslAns[i] << endl; - } - // cout << "GSL: " << checkAns( test, numCompts, &gslAns[0], &ones[0] ) << endl; - assert( checkAns( test, numCompts, &gslAns[0], &ones[0] ) < 1e-25 ); - gsl_permutation_free( p ); - gsl_vector_free( x ); - cout << "." << flush; + ///////////////////////////////////////////////////////////////////// + // Here we do the gsl test. + vector< double > temp( &test[0], &test[numCompts*numCompts] ); + gsl_matrix_view m = gsl_matrix_view_array( &temp[0], numCompts, numCompts ); + + vector< double > z( numCompts, 1.0 ); + gsl_vector_view b = gsl_vector_view_array( &z[0], numCompts ); + gsl_vector* x = gsl_vector_alloc( numCompts ); + int s; + gsl_permutation* p = gsl_permutation_alloc( numCompts ); + gsl_linalg_LU_decomp( &m.matrix, p, &s ); + gsl_linalg_LU_solve( &m.matrix, p, &b.vector, x); + vector< double > gslAns( numCompts ); + for ( unsigned int i = 0; i < numCompts; ++i ) + { + gslAns[i] = gsl_vector_get( x, i ); + // cout << "x[" << i << "]= " << gslAns[i] << endl; + } + // cout << "GSL: " << checkAns( test, numCompts, &gslAns[0], &ones[0] ) << endl; + assert( checkAns( test, numCompts, &gslAns[0], &ones[0] ) < 1e-25 ); + gsl_permutation_free( p ); + gsl_vector_free( x ); + cout << "." << flush; #endif } void testSorting() { - static unsigned int k[] = {20,40,60,80,100,10,30,50,70,90}; - static double d[] = {1,2,3,4,5,6,7,8,9,10}; - vector< unsigned int > col; - col.insert( col.begin(), k, k+10); - vector< double > entry; - entry.insert( entry.begin(), d, d+10); - sortByColumn( col, entry ); - - for ( unsigned int i = 0; i < col.size(); ++i ) - assert( col[i] == (i + 1) * 10 ); - - assert( entry[0] == 6 ); - assert( entry[1] == 1 ); - assert( entry[2] == 7 ); - assert( entry[3] == 2 ); - assert( entry[4] == 8 ); - assert( entry[5] == 3 ); - assert( entry[6] == 9 ); - assert( entry[7] == 4 ); - assert( entry[8] == 10 ); - assert( entry[9] == 5 ); - - /* - cout << "testing sorting\n"; - for ( unsigned int i = 0; i < col.size(); ++i ) { - cout << "d[" << i << "]= " << k[i] << - ", col[" << i << "]= " << col[i] << ", e=" << entry[i] << endl; - } - cout << endl; - */ - cout << "." << flush; + static unsigned int k[] = {20,40,60,80,100,10,30,50,70,90}; + static double d[] = {1,2,3,4,5,6,7,8,9,10}; + vector< unsigned int > col; + col.insert( col.begin(), k, k+10); + vector< double > entry; + entry.insert( entry.begin(), d, d+10); + sortByColumn( col, entry ); + + for ( unsigned int i = 0; i < col.size(); ++i ) + assert( col[i] == (i + 1) * 10 ); + + assert( entry[0] == 6 ); + assert( entry[1] == 1 ); + assert( entry[2] == 7 ); + assert( entry[3] == 2 ); + assert( entry[4] == 8 ); + assert( entry[5] == 3 ); + assert( entry[6] == 9 ); + assert( entry[7] == 4 ); + assert( entry[8] == 10 ); + assert( entry[9] == 5 ); + + /* + cout << "testing sorting\n"; + for ( unsigned int i = 0; i < col.size(); ++i ) { + cout << "d[" << i << "]= " << k[i] << + ", col[" << i << "]= " << col[i] << ", e=" << entry[i] << endl; + } + cout << endl; + */ + cout << "." << flush; } void testSetDiffusionAndTransport() { - static double test[] = { - 0, 2, 0, 0, 0, 0, - 1, 0, 2, 0, 0, 0, - 0, 1, 0, 2, 0, 0, - 0, 0, 1, 0, 2, 0, - 0, 0, 0, 1, 0, 2, - 0, 0, 0, 0, 1, 0, - }; - const unsigned int numCompts = 6; - FastMatrixElim fm; - fm.makeTestMatrix( test, numCompts ); - vector< unsigned int > parentVoxel( numCompts ); - parentVoxel[0] = -1; - parentVoxel[1] = 0; - parentVoxel[2] = 1; - parentVoxel[3] = 2; - parentVoxel[4] = 3; - parentVoxel[5] = 4; - - // cout << endl; - // fm.print(); - // cout << endl; - // fm.printInternal(); - fm.setDiffusionAndTransport( parentVoxel, 1, 10, 0.1 ); - // cout << endl; - // fm.print(); - // cout << endl; - // fm.printInternal(); - - for( unsigned int i =0; i < numCompts; ++i ) { - unsigned int start = 0; - if ( i > 0 ) - start = i - 1; - for( unsigned int j = start ; j < i+1 && j < numCompts ; ++j ) { - if ( i == j + 1 ) - assert( doubleEq( fm.get( i, j ), 0.1 ) ); - else if ( i + 1 == j ) { - assert( doubleEq( fm.get( i, j ), 2.2 ) ); - } else if ( i == j ) { - if ( i == 0 ) - assert( doubleEq( fm.get( i, j ), 0.8 ) ); - else if ( i == numCompts - 1 ) - assert( doubleEq( fm.get( i, j ), -0.1 ) ); - else - assert( doubleEq( fm.get( i, j ), -0.3 ) ); - } - } - } - cout << "." << flush; + static double test[] = + { + 0, 2, 0, 0, 0, 0, + 1, 0, 2, 0, 0, 0, + 0, 1, 0, 2, 0, 0, + 0, 0, 1, 0, 2, 0, + 0, 0, 0, 1, 0, 2, + 0, 0, 0, 0, 1, 0, + }; + const unsigned int numCompts = 6; + FastMatrixElim fm; + fm.makeTestMatrix( test, numCompts ); + vector< unsigned int > parentVoxel( numCompts ); + parentVoxel[0] = -1; + parentVoxel[1] = 0; + parentVoxel[2] = 1; + parentVoxel[3] = 2; + parentVoxel[4] = 3; + parentVoxel[5] = 4; + + // cout << endl; + // fm.print(); + // cout << endl; + // fm.printInternal(); + fm.setDiffusionAndTransport( parentVoxel, 1, 10, 0.1 ); + // cout << endl; + // fm.print(); + // cout << endl; + // fm.printInternal(); + + for( unsigned int i =0; i < numCompts; ++i ) + { + unsigned int start = 0; + if ( i > 0 ) + start = i - 1; + for( unsigned int j = start ; j < i+1 && j < numCompts ; ++j ) + { + if ( i == j + 1 ) + assert( doubleEq( fm.get( i, j ), 0.1 ) ); + else if ( i + 1 == j ) + { + assert( doubleEq( fm.get( i, j ), 2.2 ) ); + } + else if ( i == j ) + { + if ( i == 0 ) + assert( doubleEq( fm.get( i, j ), 0.8 ) ); + else if ( i == numCompts - 1 ) + assert( doubleEq( fm.get( i, j ), -0.1 ) ); + else + assert( doubleEq( fm.get( i, j ), -0.3 ) ); + } + } + } + cout << "." << flush; } void testCylDiffn() { - Shell* s = reinterpret_cast< Shell* >( Id().eref().data() ); - double len = 25e-6; - double r0 = 1e-6; - double r1 = 1e-6; - double diffLength = 1e-6; // 1e-6 is the highest dx for which error is OK - double runtime = 10.0; - double dt = 0.1; // 0.2 is the highest dt for which the error is in bounds - double diffConst = 1.0e-12; - Id model = s->doCreate( "Neutral", Id(), "model", 1 ); - Id cyl = s->doCreate( "CylMesh", model, "cyl", 1 ); - Field< double >::set( cyl, "r0", r0 ); - Field< double >::set( cyl, "r1", r1 ); - Field< double >::set( cyl, "x0", 0 ); - Field< double >::set( cyl, "x1", len ); - Field< double >::set( cyl, "diffLength", diffLength ); - unsigned int ndc = Field< unsigned int >::get( cyl, "numMesh" ); - assert( ndc == static_cast< unsigned int >( round( len / diffLength ))); - Id pool = s->doCreate( "Pool", cyl, "pool", 1 ); - Field< double >::set( pool, "diffConst", diffConst ); - - Id dsolve = s->doCreate( "Dsolve", model, "dsolve", 1 ); - Field< Id >::set( dsolve, "compartment", cyl ); - // Next: build by doing reinit - s->doUseClock( "/model/dsolve", "process", 1 ); - s->doSetClock( 1, dt ); - Field< string >::set( dsolve, "path", "/model/cyl/pool" ); - // Then find a way to test it. - vector< double > poolVec; - Field< double >::set( ObjId( pool, 0 ), "nInit", 1.0 ); - Field< double >::getVec( pool, "nInit", poolVec ); - assert( poolVec.size() == ndc ); - assert( doubleEq( poolVec[0], 1.0 ) ); - assert( doubleEq( poolVec[1], 0.0 ) ); - - vector< double > nvec = - LookupField< unsigned int, vector< double > >::get( - dsolve, "nVec", 0); - assert( nvec.size() == ndc ); - - s->doReinit(); - s->doStart( runtime ); - - nvec = LookupField< unsigned int, vector< double > >::get( - dsolve, "nVec", 0); - Field< double >::getVec( pool, "n", poolVec ); - assert( nvec.size() == poolVec.size() ); - for ( unsigned int i = 0; i < nvec.size(); ++i ) - assert( doubleEq( nvec[i], poolVec[i] ) ); - /* - cout << endl; - for ( unsigned int i = 0; i < nvec.size(); ++i ) - cout << nvec[i] << " "; - cout << endl; - */ - - double dx = diffLength; - double err = 0.0; - double analyticTot = 0.0; - double myTot = 0.0; - for ( unsigned int i = 0; i < nvec.size(); ++i ) { - double x = i * dx + dx * 0.5; - // This part is the solution as a func of x,t. - double y = dx * // This part represents the init n of 1 in dx - ( 1.0 / sqrt( PI * diffConst * runtime ) ) * - exp( -x * x / ( 4 * diffConst * runtime ) ); - err += ( y - nvec[i] ) * ( y - nvec[i] ); - //cout << i << " " << x << " " << y << " " << conc[i] << endl; - analyticTot += y; - myTot += nvec[i]; - } - assert( doubleEq( myTot, 1.0 ) ); - // cout << "analyticTot= " << analyticTot << ", myTot= " << myTot << endl; - assert( err < 1.0e-5 ); - - - s->doDelete( model ); - cout << "." << flush; + Shell* s = reinterpret_cast< Shell* >( Id().eref().data() ); + double len = 25e-6; + double r0 = 1e-6; + double r1 = 1e-6; + double diffLength = 1e-6; // 1e-6 is the highest dx for which error is OK + double runtime = 10.0; + double dt = 0.1; // 0.2 is the highest dt for which the error is in bounds + double diffConst = 1.0e-12; + Id model = s->doCreate( "Neutral", Id(), "model", 1 ); + Id cyl = s->doCreate( "CylMesh", model, "cyl", 1 ); + Field< double >::set( cyl, "r0", r0 ); + Field< double >::set( cyl, "r1", r1 ); + Field< double >::set( cyl, "x0", 0 ); + Field< double >::set( cyl, "x1", len ); + Field< double >::set( cyl, "diffLength", diffLength ); + unsigned int ndc = Field< unsigned int >::get( cyl, "numMesh" ); + assert( ndc == static_cast< unsigned int >( round( len / diffLength ))); + Id pool = s->doCreate( "Pool", cyl, "pool", 1 ); + Field< double >::set( pool, "diffConst", diffConst ); + + Id dsolve = s->doCreate( "Dsolve", model, "dsolve", 1 ); + Field< Id >::set( dsolve, "compartment", cyl ); + // Next: build by doing reinit + s->doUseClock( "/model/dsolve", "process", 1 ); + s->doSetClock( 1, dt ); + Field< string >::set( dsolve, "path", "/model/cyl/pool" ); + // Then find a way to test it. + vector< double > poolVec; + Field< double >::set( ObjId( pool, 0 ), "nInit", 1.0 ); + Field< double >::getVec( pool, "nInit", poolVec ); + assert( poolVec.size() == ndc ); + assert( doubleEq( poolVec[0], 1.0 ) ); + assert( doubleEq( poolVec[1], 0.0 ) ); + + vector< double > nvec = + LookupField< unsigned int, vector< double > >::get( + dsolve, "nVec", 0); + assert( nvec.size() == ndc ); + + s->doReinit(); + s->doStart( runtime ); + + nvec = LookupField< unsigned int, vector< double > >::get( + dsolve, "nVec", 0); + Field< double >::getVec( pool, "n", poolVec ); + assert( nvec.size() == poolVec.size() ); + for ( unsigned int i = 0; i < nvec.size(); ++i ) + assert( doubleEq( nvec[i], poolVec[i] ) ); + /* + cout << endl; + for ( unsigned int i = 0; i < nvec.size(); ++i ) + cout << nvec[i] << " "; + cout << endl; + */ + + double dx = diffLength; + double err = 0.0; + double analyticTot = 0.0; + double myTot = 0.0; + for ( unsigned int i = 0; i < nvec.size(); ++i ) + { + double x = i * dx + dx * 0.5; + // This part is the solution as a func of x,t. + double y = dx * // This part represents the init n of 1 in dx + ( 1.0 / sqrt( PI * diffConst * runtime ) ) * + exp( -x * x / ( 4 * diffConst * runtime ) ); + err += ( y - nvec[i] ) * ( y - nvec[i] ); + //cout << i << " " << x << " " << y << " " << conc[i] << endl; + analyticTot += y; + myTot += nvec[i]; + } + assert( doubleEq( myTot, 1.0 ) ); + // cout << "analyticTot= " << analyticTot << ", myTot= " << myTot << endl; + assert( err < 1.0e-5 ); + + + s->doDelete( model ); + cout << "." << flush; } void testTaperingCylDiffn() { - Shell* s = reinterpret_cast< Shell* >( Id().eref().data() ); - double len = 25e-6; - double r0 = 2e-6; - double r1 = 1e-6; - double diffLength = 1e-6; // 1e-6 is the highest dx for which error is OK - double runtime = 10.0; - double dt = 0.1; // 0.2 is the highest dt for which the error is in bounds - double diffConst = 1.0e-12; - // Should set explicitly, currently during creation of DiffPoolVec - //double diffConst = 1.0e-12; - Id model = s->doCreate( "Neutral", Id(), "model", 1 ); - Id cyl = s->doCreate( "CylMesh", model, "cyl", 1 ); - Field< double >::set( cyl, "r0", r0 ); - Field< double >::set( cyl, "r1", r1 ); - Field< double >::set( cyl, "x0", 0 ); - Field< double >::set( cyl, "x1", len ); - Field< double >::set( cyl, "diffLength", diffLength ); - unsigned int ndc = Field< unsigned int >::get( cyl, "numMesh" ); - assert( ndc == static_cast< unsigned int >( round( len / diffLength ))); - Id pool = s->doCreate( "Pool", cyl, "pool", 1 ); - Field< double >::set( pool, "diffConst", diffConst ); - - Id dsolve = s->doCreate( "Dsolve", model, "dsolve", 1 ); - Field< Id >::set( dsolve, "compartment", cyl ); - s->doUseClock( "/model/dsolve", "process", 1 ); - s->doSetClock( 1, dt ); - // Next: build by setting the path of the dsolve. - Field< string >::set( dsolve, "path", "/model/cyl/pool" ); - // Then find a way to test it. - assert( pool.element()->numData() == ndc ); - Field< double >::set( ObjId( pool, 0 ), "nInit", 1.0 ); - - s->doReinit(); - s->doStart( runtime ); - - double myTot = 0.0; - vector< double > poolVec; - Field< double >::getVec( pool, "n", poolVec ); - for ( unsigned int i = 0; i < poolVec.size(); ++i ) { - myTot += poolVec[i]; - } - assert( doubleEq( myTot, 1.0 ) ); - - s->doDelete( model ); - cout << "." << flush; + Shell* s = reinterpret_cast< Shell* >( Id().eref().data() ); + double len = 25e-6; + double r0 = 2e-6; + double r1 = 1e-6; + double diffLength = 1e-6; // 1e-6 is the highest dx for which error is OK + double runtime = 10.0; + double dt = 0.1; // 0.2 is the highest dt for which the error is in bounds + double diffConst = 1.0e-12; + // Should set explicitly, currently during creation of DiffPoolVec + //double diffConst = 1.0e-12; + Id model = s->doCreate( "Neutral", Id(), "model", 1 ); + Id cyl = s->doCreate( "CylMesh", model, "cyl", 1 ); + Field< double >::set( cyl, "r0", r0 ); + Field< double >::set( cyl, "r1", r1 ); + Field< double >::set( cyl, "x0", 0 ); + Field< double >::set( cyl, "x1", len ); + Field< double >::set( cyl, "diffLength", diffLength ); + unsigned int ndc = Field< unsigned int >::get( cyl, "numMesh" ); + assert( ndc == static_cast< unsigned int >( round( len / diffLength ))); + Id pool = s->doCreate( "Pool", cyl, "pool", 1 ); + Field< double >::set( pool, "diffConst", diffConst ); + + Id dsolve = s->doCreate( "Dsolve", model, "dsolve", 1 ); + Field< Id >::set( dsolve, "compartment", cyl ); + s->doUseClock( "/model/dsolve", "process", 1 ); + s->doSetClock( 1, dt ); + // Next: build by setting the path of the dsolve. + Field< string >::set( dsolve, "path", "/model/cyl/pool" ); + // Then find a way to test it. + assert( pool.element()->numData() == ndc ); + Field< double >::set( ObjId( pool, 0 ), "nInit", 1.0 ); + + s->doReinit(); + s->doStart( runtime ); + + double myTot = 0.0; + vector< double > poolVec; + Field< double >::getVec( pool, "n", poolVec ); + for ( unsigned int i = 0; i < poolVec.size(); ++i ) + { + myTot += poolVec[i]; + } + assert( doubleEq( myTot, 1.0 ) ); + + s->doDelete( model ); + cout << "." << flush; } /** @@ -497,429 +512,435 @@ void testTaperingCylDiffn() */ void testSmallCellDiffn() { - Id makeCompt( Id parentCompt, Id parentObj, - string name, double len, double dia, double theta ); - Shell* s = reinterpret_cast< Shell* >( Id().eref().data() ); - double len = 20e-6; - double dia = 10e-6; - double diffLength = 10e-6; - double dt = 1.0e-1; - double runtime = 100.0; - double diffConst = 1.0e-12; - Id model = s->doCreate( "Neutral", Id(), "model", 1 ); - Id soma = makeCompt( Id(), model, "soma", dia, dia, 90 ); - Id dend = makeCompt( soma, model, "dend", len, 3e-6, 0 ); - Id branch1 = makeCompt( dend, model, "branch1", len, 2e-6, 45.0 ); - Id branch2 = makeCompt( dend, model, "branch2", len, 2e-6, -45.0 ); - Id twig1 = makeCompt( branch1, model, "twig1", len, 1.5e-6, 90.0 ); - Id twig2 = makeCompt( branch1, model, "twig2", len, 1.5e-6, 0.0 ); - - Id nm = s->doCreate( "NeuroMesh", model, "neuromesh", 1 ); - Field< double >::set( nm, "diffLength", diffLength ); - Field< string >::set( nm, "geometryPolicy", "cylinder" ); - Field< string >::set( nm, "subTreePath", "/model/#" ); - //SetGet2< Id, string >::set( nm, "cellPortion", model, "/model/#" ); - unsigned int ns = Field< unsigned int >::get( nm, "numSegments" ); - assert( ns == 6 ); - unsigned int ndc = Field< unsigned int >::get( nm, "numDiffCompts" ); - assert( ndc == 11 ); - Id pool1 = s->doCreate( "Pool", nm, "pool1", 1 ); - Field< double >::set( pool1, "diffConst", diffConst ); - Id pool2 = s->doCreate( "Pool", nm, "pool2", 1 ); - Field< double >::set( pool2, "diffConst", diffConst ); - Id pool3 = s->doCreate( "Pool", nm, "pool3", 1 ); - Field< double >::set( pool3, "diffConst", 0.0 ); - - Id dsolve = s->doCreate( "Dsolve", model, "dsolve", 1 ); - Field< Id >::set( dsolve, "compartment", nm ); - s->doUseClock( "/model/dsolve", "process", 1 ); - s->doSetClock( 1, dt ); - // Next: build diffusion by setting path - Field< string >::set( dsolve, "path", "/model/neuromesh/pool#" ); - - vector< double > nvec = - LookupField< unsigned int, vector< double > >::get( - dsolve, "nVec", 0); - assert( nvec.size() == ndc ); - assert( pool1.element()->numData() == ndc ); - Field< double >::set( ObjId( pool1, 0 ), "nInit", 1.0 ); - Field< double >::set( ObjId( pool2, ndc - 1 ), "nInit", 2.0 ); - Field< double >::set( ObjId( pool3, 0 ), "nInit", 3.0 ); - - s->doReinit(); - nvec = LookupField< unsigned int, vector< double > >::get( - dsolve, "nVec", 0); - assert( doubleEq( nvec[0], 1.0 ) ); - assert( doubleEq( nvec[1], 0.0 ) ); - s->doStart( runtime ); - - nvec = LookupField< unsigned int, vector< double > >::get( - dsolve, "nVec", 0); - vector< double > pool1Vec; - Field< double >::getVec( pool1, "n", pool1Vec ); - assert( pool1Vec.size() == ndc ); - - vector< double > pool2Vec; - Field< double >::getVec( pool2, "n", pool2Vec ); - assert( pool2Vec.size() == ndc ); - - vector< double > pool3Vec; - Field< double >::getVec( pool3, "n", pool3Vec ); - assert( pool3Vec.size() == ndc ); - double myTot1 = 0; - double myTot2 = 0; - double myTot3 = 0; - for ( unsigned int i = 0; i < nvec.size(); ++i ) { - assert( doubleEq( pool1Vec[i], nvec[i] ) ); - myTot1 += nvec[i]; - myTot2 += pool2Vec[i]; - myTot3 += pool3Vec[i]; - } - assert( doubleEq( myTot1, 1.0 ) ); - assert( doubleEq( myTot2, 2.0 ) ); - assert( doubleEq( myTot3, 3.0 ) ); - assert( doubleEq( pool3Vec[0], 3.0 ) ); - - /* - cout << "Small cell: " << endl; - for ( unsigned int i = 0; i < nvec.size(); ++i ) - cout << nvec[i] << ", " << pool2Vec[i] << endl; - cout << endl; - */ - - - s->doDelete( model ); - cout << "." << flush; + Id makeCompt( Id parentCompt, Id parentObj, + string name, double len, double dia, double theta ); + Shell* s = reinterpret_cast< Shell* >( Id().eref().data() ); + double len = 20e-6; + double dia = 10e-6; + double diffLength = 10e-6; + double dt = 1.0e-1; + double runtime = 100.0; + double diffConst = 1.0e-12; + Id model = s->doCreate( "Neutral", Id(), "model", 1 ); + Id soma = makeCompt( Id(), model, "soma", dia, dia, 90 ); + Id dend = makeCompt( soma, model, "dend", len, 3e-6, 0 ); + Id branch1 = makeCompt( dend, model, "branch1", len, 2e-6, 45.0 ); + Id branch2 = makeCompt( dend, model, "branch2", len, 2e-6, -45.0 ); + Id twig1 = makeCompt( branch1, model, "twig1", len, 1.5e-6, 90.0 ); + Id twig2 = makeCompt( branch1, model, "twig2", len, 1.5e-6, 0.0 ); + + Id nm = s->doCreate( "NeuroMesh", model, "neuromesh", 1 ); + Field< double >::set( nm, "diffLength", diffLength ); + Field< string >::set( nm, "geometryPolicy", "cylinder" ); + Field< string >::set( nm, "subTreePath", "/model/#" ); + //SetGet2< Id, string >::set( nm, "cellPortion", model, "/model/#" ); + unsigned int ns = Field< unsigned int >::get( nm, "numSegments" ); + assert( ns == 6 ); + unsigned int ndc = Field< unsigned int >::get( nm, "numDiffCompts" ); + assert( ndc == 11 ); + Id pool1 = s->doCreate( "Pool", nm, "pool1", 1 ); + Field< double >::set( pool1, "diffConst", diffConst ); + Id pool2 = s->doCreate( "Pool", nm, "pool2", 1 ); + Field< double >::set( pool2, "diffConst", diffConst ); + Id pool3 = s->doCreate( "Pool", nm, "pool3", 1 ); + Field< double >::set( pool3, "diffConst", 0.0 ); + + Id dsolve = s->doCreate( "Dsolve", model, "dsolve", 1 ); + Field< Id >::set( dsolve, "compartment", nm ); + s->doUseClock( "/model/dsolve", "process", 1 ); + s->doSetClock( 1, dt ); + // Next: build diffusion by setting path + Field< string >::set( dsolve, "path", "/model/neuromesh/pool#" ); + + vector< double > nvec = + LookupField< unsigned int, vector< double > >::get( + dsolve, "nVec", 0); + assert( nvec.size() == ndc ); + assert( pool1.element()->numData() == ndc ); + Field< double >::set( ObjId( pool1, 0 ), "nInit", 1.0 ); + Field< double >::set( ObjId( pool2, ndc - 1 ), "nInit", 2.0 ); + Field< double >::set( ObjId( pool3, 0 ), "nInit", 3.0 ); + + s->doReinit(); + nvec = LookupField< unsigned int, vector< double > >::get( + dsolve, "nVec", 0); + assert( doubleEq( nvec[0], 1.0 ) ); + assert( doubleEq( nvec[1], 0.0 ) ); + s->doStart( runtime ); + + nvec = LookupField< unsigned int, vector< double > >::get( + dsolve, "nVec", 0); + vector< double > pool1Vec; + Field< double >::getVec( pool1, "n", pool1Vec ); + assert( pool1Vec.size() == ndc ); + + vector< double > pool2Vec; + Field< double >::getVec( pool2, "n", pool2Vec ); + assert( pool2Vec.size() == ndc ); + + vector< double > pool3Vec; + Field< double >::getVec( pool3, "n", pool3Vec ); + assert( pool3Vec.size() == ndc ); + double myTot1 = 0; + double myTot2 = 0; + double myTot3 = 0; + for ( unsigned int i = 0; i < nvec.size(); ++i ) + { + assert( doubleEq( pool1Vec[i], nvec[i] ) ); + myTot1 += nvec[i]; + myTot2 += pool2Vec[i]; + myTot3 += pool3Vec[i]; + } + assert( doubleEq( myTot1, 1.0 ) ); + assert( doubleEq( myTot2, 2.0 ) ); + assert( doubleEq( myTot3, 3.0 ) ); + assert( doubleEq( pool3Vec[0], 3.0 ) ); + + /* + cout << "Small cell: " << endl; + for ( unsigned int i = 0; i < nvec.size(); ++i ) + cout << nvec[i] << ", " << pool2Vec[i] << endl; + cout << endl; + */ + + + s->doDelete( model ); + cout << "." << flush; } void testCellDiffn() { - Id makeCompt( Id parentCompt, Id parentObj, - string name, double len, double dia, double theta ); - Shell* s = reinterpret_cast< Shell* >( Id().eref().data() ); - double len = 40e-6; - double dia = 10e-6; - double diffLength = 1e-6; - double dt = 1.0e-1; - double runtime = 100.0; - double diffConst = 1.0e-12; - Id model = s->doCreate( "Neutral", Id(), "model", 1 ); - Id soma = makeCompt( Id(), model, "soma", dia, dia, 90 ); - Id dend = makeCompt( soma, model, "dend", len, 3e-6, 0 ); - Id branch1 = makeCompt( dend, model, "branch1", len, 2e-6, 45.0 ); - Id branch2 = makeCompt( dend, model, "branch2", len, 2e-6, -45.0 ); - Id twig1 = makeCompt( branch1, model, "twig1", len, 1.5e-6, 90.0 ); - Id twig2 = makeCompt( branch1, model, "twig2", len, 1.5e-6, 0.0 ); - - Id nm = s->doCreate( "NeuroMesh", model, "neuromesh", 1 ); - Field< double >::set( nm, "diffLength", diffLength ); - Field< string >::set( nm, "geometryPolicy", "cylinder" ); - Field< string >::set( nm, "subTreePath", "/model/#" ); - //SetGet2< Id, string >::set( nm, "cellPortion", model, "/model/#" ); - unsigned int ns = Field< unsigned int >::get( nm, "numSegments" ); - assert( ns == 6 ); - unsigned int ndc = Field< unsigned int >::get( nm, "numDiffCompts" ); - assert( ndc == 210 ); - Id pool1 = s->doCreate( "Pool", nm, "pool1", 1 ); - Field< double >::set( pool1, "diffConst", diffConst ); - Id pool2 = s->doCreate( "Pool", nm, "pool2", 1 ); - Field< double >::set( pool2, "diffConst", diffConst ); - - Id dsolve = s->doCreate( "Dsolve", model, "dsolve", 1 ); - Field< Id >::set( dsolve, "compartment", nm ); - s->doUseClock( "/model/dsolve", "process", 1 ); - s->doSetClock( 1, dt ); - // Next: build by setting path - Field< string >::set( dsolve, "path", "/model/neuromesh/pool#" ); - - vector< double > nvec = - LookupField< unsigned int, vector< double > >::get( - dsolve, "nVec", 0); - assert( nvec.size() == ndc ); - assert( pool1.element()->numData() == ndc ); - Field< double >::set( ObjId( pool1, 0 ), "nInit", 1.0 ); - Field< double >::set( ObjId( pool2, ndc - 1 ), "nInit", 2.0 ); - - s->doReinit(); - s->doStart( runtime ); - - nvec = LookupField< unsigned int, vector< double > >::get( - dsolve, "nVec", 0); - vector< double > pool1Vec; - Field< double >::getVec( pool1, "n", pool1Vec ); - assert( pool1Vec.size() == ndc ); - - vector< double > pool2Vec; - Field< double >::getVec( pool2, "n", pool2Vec ); - assert( pool2Vec.size() == ndc ); - double myTot1 = 0; - double myTot2 = 0; - for ( unsigned int i = 0; i < nvec.size(); ++i ) { - assert( doubleEq( pool1Vec[i], nvec[i] ) ); - myTot1 += nvec[i]; - myTot2 += pool2Vec[i]; - } - assert( doubleEq( myTot1, 1.0 ) ); - assert( doubleEq( myTot2, 2.0 ) ); - - /* - cout << endl; - cout << "Big cell: " << endl; - for ( unsigned int i = 0; i < nvec.size(); ++i ) - cout << nvec[i] << ", " << pool2Vec[i] << endl; - cout << endl; - */ - - - s->doDelete( model ); - cout << "." << flush; + Id makeCompt( Id parentCompt, Id parentObj, + string name, double len, double dia, double theta ); + Shell* s = reinterpret_cast< Shell* >( Id().eref().data() ); + double len = 40e-6; + double dia = 10e-6; + double diffLength = 1e-6; + double dt = 1.0e-1; + double runtime = 100.0; + double diffConst = 1.0e-12; + Id model = s->doCreate( "Neutral", Id(), "model", 1 ); + Id soma = makeCompt( Id(), model, "soma", dia, dia, 90 ); + Id dend = makeCompt( soma, model, "dend", len, 3e-6, 0 ); + Id branch1 = makeCompt( dend, model, "branch1", len, 2e-6, 45.0 ); + Id branch2 = makeCompt( dend, model, "branch2", len, 2e-6, -45.0 ); + Id twig1 = makeCompt( branch1, model, "twig1", len, 1.5e-6, 90.0 ); + Id twig2 = makeCompt( branch1, model, "twig2", len, 1.5e-6, 0.0 ); + + Id nm = s->doCreate( "NeuroMesh", model, "neuromesh", 1 ); + Field< double >::set( nm, "diffLength", diffLength ); + Field< string >::set( nm, "geometryPolicy", "cylinder" ); + Field< string >::set( nm, "subTreePath", "/model/#" ); + //SetGet2< Id, string >::set( nm, "cellPortion", model, "/model/#" ); + unsigned int ns = Field< unsigned int >::get( nm, "numSegments" ); + assert( ns == 6 ); + unsigned int ndc = Field< unsigned int >::get( nm, "numDiffCompts" ); + assert( ndc == 210 ); + Id pool1 = s->doCreate( "Pool", nm, "pool1", 1 ); + Field< double >::set( pool1, "diffConst", diffConst ); + Id pool2 = s->doCreate( "Pool", nm, "pool2", 1 ); + Field< double >::set( pool2, "diffConst", diffConst ); + + Id dsolve = s->doCreate( "Dsolve", model, "dsolve", 1 ); + Field< Id >::set( dsolve, "compartment", nm ); + s->doUseClock( "/model/dsolve", "process", 1 ); + s->doSetClock( 1, dt ); + // Next: build by setting path + Field< string >::set( dsolve, "path", "/model/neuromesh/pool#" ); + + vector< double > nvec = + LookupField< unsigned int, vector< double > >::get( + dsolve, "nVec", 0); + assert( nvec.size() == ndc ); + assert( pool1.element()->numData() == ndc ); + Field< double >::set( ObjId( pool1, 0 ), "nInit", 1.0 ); + Field< double >::set( ObjId( pool2, ndc - 1 ), "nInit", 2.0 ); + + s->doReinit(); + s->doStart( runtime ); + + nvec = LookupField< unsigned int, vector< double > >::get( + dsolve, "nVec", 0); + vector< double > pool1Vec; + Field< double >::getVec( pool1, "n", pool1Vec ); + assert( pool1Vec.size() == ndc ); + + vector< double > pool2Vec; + Field< double >::getVec( pool2, "n", pool2Vec ); + assert( pool2Vec.size() == ndc ); + double myTot1 = 0; + double myTot2 = 0; + for ( unsigned int i = 0; i < nvec.size(); ++i ) + { + assert( doubleEq( pool1Vec[i], nvec[i] ) ); + myTot1 += nvec[i]; + myTot2 += pool2Vec[i]; + } + assert( doubleEq( myTot1, 1.0 ) ); + assert( doubleEq( myTot2, 2.0 ) ); + + /* + cout << endl; + cout << "Big cell: " << endl; + for ( unsigned int i = 0; i < nvec.size(); ++i ) + cout << nvec[i] << ", " << pool2Vec[i] << endl; + cout << endl; + */ + + + s->doDelete( model ); + cout << "." << flush; } void testCylDiffnWithStoich() { - Shell* s = reinterpret_cast< Shell* >( Id().eref().data() ); - double len = 25e-6; - double r0 = 1e-6; - double r1 = 1e-6; - double diffLength = 1e-6; // 1e-6 is the highest dx for which error is OK - double runtime = 10.0; - double dt0 = 0.1; // Used for diffusion. 0.2 is the highest dt for which the error is in bounds - double dt1 = 1; // Used for chem. - double diffConst = 1.0e-12; - Id model = s->doCreate( "Neutral", Id(), "model", 1 ); - Id cyl = s->doCreate( "CylMesh", model, "cyl", 1 ); - Field< double >::set( cyl, "r0", r0 ); - Field< double >::set( cyl, "r1", r1 ); - Field< double >::set( cyl, "x0", 0 ); - Field< double >::set( cyl, "x1", len ); - Field< double >::set( cyl, "diffLength", diffLength ); - unsigned int ndc = Field< unsigned int >::get( cyl, "numMesh" ); - assert( ndc == static_cast< unsigned int >( round( len / diffLength ))); - Id pool1 = s->doCreate( "Pool", cyl, "pool1", 1 ); - Id pool2 = s->doCreate( "Pool", cyl, "pool2", 1 ); - Field< double >::set( pool1, "diffConst", diffConst ); - Field< double >::set( pool2, "diffConst", diffConst/2 ); - - Id stoich = s->doCreate( "Stoich", model, "stoich", 1 ); - Id ksolve = s->doCreate( "Ksolve", model, "ksolve", 1 ); - Id dsolve = s->doCreate( "Dsolve", model, "dsolve", 1 ); - Field< Id >::set( stoich, "compartment", cyl ); - Field< Id >::set( stoich, "ksolve", ksolve ); - Field< Id >::set( stoich, "dsolve", dsolve ); - Field< string >::set( stoich, "path", "/model/cyl/#" ); - assert( pool1.element()->numData() == ndc ); - - // Then find a way to test it. - vector< double > poolVec; - Field< double >::set( ObjId( pool1, 0 ), "nInit", 1.0 ); - Field< double >::set( ObjId( pool2, 0 ), "nInit", 1.0 ); - Field< double >::getVec( pool1, "nInit", poolVec ); - assert( poolVec.size() == ndc ); - assert( doubleEq( poolVec[0], 1.0 ) ); - assert( doubleEq( poolVec[1], 0.0 ) ); - - vector< double > nvec = - LookupField< unsigned int, vector< double > >::get( - dsolve, "nVec", 0); - assert( nvec.size() == ndc ); - - // Next: build by doing reinit - s->doUseClock( "/model/dsolve", "process", 0 ); - s->doUseClock( "/model/ksolve", "process", 1 ); - s->doSetClock( 0, dt0 ); - s->doSetClock( 1, dt1 ); - s->doReinit(); - s->doStart( runtime ); - - nvec = LookupField< unsigned int, vector< double > >::get( - dsolve, "nVec", 0); - Field< double >::getVec( pool1, "n", poolVec ); - assert( nvec.size() == poolVec.size() ); - for ( unsigned int i = 0; i < nvec.size(); ++i ) - assert( doubleEq( nvec[i], poolVec[i] ) ); - /* - cout << endl; - for ( unsigned int i = 0; i < nvec.size(); ++i ) - cout << nvec[i] << " "; - cout << endl; - */ - - double dx = diffLength; - double err = 0.0; - double analyticTot = 0.0; - double myTot = 0.0; - for ( unsigned int i = 0; i < nvec.size(); ++i ) { - double x = i * dx + dx * 0.5; - // This part is the solution as a func of x,t. - double y = dx * // This part represents the init n of 1 in dx - ( 1.0 / sqrt( PI * diffConst * runtime ) ) * - exp( -x * x / ( 4 * diffConst * runtime ) ); - err += ( y - nvec[i] ) * ( y - nvec[i] ); - //cout << i << " " << x << " " << y << " " << conc[i] << endl; - analyticTot += y; - myTot += nvec[i]; - } - assert( doubleEq( myTot, 1.0 ) ); - // cout << "analyticTot= " << analyticTot << ", myTot= " << myTot << endl; - assert( err < 1.0e-5 ); - - - s->doDelete( model ); - cout << "." << flush; + Shell* s = reinterpret_cast< Shell* >( Id().eref().data() ); + double len = 25e-6; + double r0 = 1e-6; + double r1 = 1e-6; + double diffLength = 1e-6; // 1e-6 is the highest dx for which error is OK + double runtime = 10.0; + double dt0 = 0.1; // Used for diffusion. 0.2 is the highest dt for which the error is in bounds + double dt1 = 1; // Used for chem. + double diffConst = 1.0e-12; + Id model = s->doCreate( "Neutral", Id(), "model", 1 ); + Id cyl = s->doCreate( "CylMesh", model, "cyl", 1 ); + Field< double >::set( cyl, "r0", r0 ); + Field< double >::set( cyl, "r1", r1 ); + Field< double >::set( cyl, "x0", 0 ); + Field< double >::set( cyl, "x1", len ); + Field< double >::set( cyl, "diffLength", diffLength ); + unsigned int ndc = Field< unsigned int >::get( cyl, "numMesh" ); + assert( ndc == static_cast< unsigned int >( round( len / diffLength ))); + Id pool1 = s->doCreate( "Pool", cyl, "pool1", 1 ); + Id pool2 = s->doCreate( "Pool", cyl, "pool2", 1 ); + Field< double >::set( pool1, "diffConst", diffConst ); + Field< double >::set( pool2, "diffConst", diffConst/2 ); + + Id stoich = s->doCreate( "Stoich", model, "stoich", 1 ); + Id ksolve = s->doCreate( "Ksolve", model, "ksolve", 1 ); + Id dsolve = s->doCreate( "Dsolve", model, "dsolve", 1 ); + Field< Id >::set( stoich, "compartment", cyl ); + Field< Id >::set( stoich, "ksolve", ksolve ); + Field< Id >::set( stoich, "dsolve", dsolve ); + Field< string >::set( stoich, "path", "/model/cyl/#" ); + assert( pool1.element()->numData() == ndc ); + + // Then find a way to test it. + vector< double > poolVec; + Field< double >::set( ObjId( pool1, 0 ), "nInit", 1.0 ); + Field< double >::set( ObjId( pool2, 0 ), "nInit", 1.0 ); + Field< double >::getVec( pool1, "nInit", poolVec ); + assert( poolVec.size() == ndc ); + assert( doubleEq( poolVec[0], 1.0 ) ); + assert( doubleEq( poolVec[1], 0.0 ) ); + + vector< double > nvec = + LookupField< unsigned int, vector< double > >::get( + dsolve, "nVec", 0); + assert( nvec.size() == ndc ); + + // Next: build by doing reinit + s->doUseClock( "/model/dsolve", "process", 0 ); + s->doUseClock( "/model/ksolve", "process", 1 ); + s->doSetClock( 0, dt0 ); + s->doSetClock( 1, dt1 ); + s->doReinit(); + s->doStart( runtime ); + + nvec = LookupField< unsigned int, vector< double > >::get( + dsolve, "nVec", 0); + Field< double >::getVec( pool1, "n", poolVec ); + assert( nvec.size() == poolVec.size() ); + for ( unsigned int i = 0; i < nvec.size(); ++i ) + assert( doubleEq( nvec[i], poolVec[i] ) ); + /* + cout << endl; + for ( unsigned int i = 0; i < nvec.size(); ++i ) + cout << nvec[i] << " "; + cout << endl; + */ + + double dx = diffLength; + double err = 0.0; + double analyticTot = 0.0; + double myTot = 0.0; + for ( unsigned int i = 0; i < nvec.size(); ++i ) + { + double x = i * dx + dx * 0.5; + // This part is the solution as a func of x,t. + double y = dx * // This part represents the init n of 1 in dx + ( 1.0 / sqrt( PI * diffConst * runtime ) ) * + exp( -x * x / ( 4 * diffConst * runtime ) ); + err += ( y - nvec[i] ) * ( y - nvec[i] ); + //cout << i << " " << x << " " << y << " " << conc[i] << endl; + analyticTot += y; + myTot += nvec[i]; + } + assert( doubleEq( myTot, 1.0 ) ); + // cout << "analyticTot= " << analyticTot << ", myTot= " << myTot << endl; + assert( err < 1.0e-5 ); + + + s->doDelete( model ); + cout << "." << flush; } #if 0 void testBuildTree() { - static double test[] = { - 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, - 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 7, 0, 8, 9, 0, 0, 0, 0, 10, 0, 0, - 11, 0, 12, 13, 0, 0, 0, 0, 0, 0, 14, - 0, 0, 0, 0, 15, 16, 0, 0, 17, 18, 0, - 0, 0, 0, 0, 19, 20, 21, 0, 22, 0, 0, - 0, 0, 0, 0, 0, 23, 24, 25, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 26, 27, 0, 0, 0, - 0, 0, 28, 0, 29, 30, 0, 0, 31, 0, 0, - 0, 0, 0, 0, 32, 0, 0, 0, 0, 33, 0, - 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 35, - }; - const unsigned int numCompts = 11; - FastMatrixElim fe; - fe.makeTestMatrix( test, numCompts ); - fe.print(); - vector< unsigned int > parentVoxel; - bool ret = fe.buildTree( 0, parentVoxel ); - assert( ret ); - assert( parentVoxel[0] == static_cast< unsigned int >( -1 ) ); - assert( parentVoxel[1] == 0 ); - assert( parentVoxel[2] == 0 ); - assert( parentVoxel[3] == 0 ); - assert( parentVoxel[8] == 2 ); - assert( parentVoxel[10] == 3 ); - assert( parentVoxel[5] == 4 ); - assert( parentVoxel[9] == 4 ); - assert( parentVoxel[6] == 5 ); - assert( parentVoxel[7] == 6 ); - - assert( parentVoxel[10] == 2 ); - - /* - * This is the sequence of traversal. x means empty, s means sibling, - * . means below diagonal. The numbers are the sequence. - static double traverseIndex[] = { - // col 1 2 3 4 5 6 7 8 9 10 - #, 1, 2, 3, x, x, x, x, x, x, x, - ., #, x, x, x, x, x, x, x, x, x, - ., x, #, s, x, x, x, x, 4, x, x, - ., x, ., #, x, x, x, x, x, x, 5, - x, x, x, x, #, 6, x, x, s, 7, x, - x, x, x, x, ., #, 8, x, s, x, x, - x, x, x, x, x, ., #, 9, x, x, x, - x, x, x, x, x, x, ., #, x, x, x, - x, x, ., x, ., ., x, x, #, x, x, - x, x, x, x, ., x, x, x, x, #, x, - x, x, x, ., x, x, x, x, x, x, #, - }; - */ + static double test[] = + { + 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, + 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 8, 9, 0, 0, 0, 0, 10, 0, 0, + 11, 0, 12, 13, 0, 0, 0, 0, 0, 0, 14, + 0, 0, 0, 0, 15, 16, 0, 0, 17, 18, 0, + 0, 0, 0, 0, 19, 20, 21, 0, 22, 0, 0, + 0, 0, 0, 0, 0, 23, 24, 25, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 26, 27, 0, 0, 0, + 0, 0, 28, 0, 29, 30, 0, 0, 31, 0, 0, + 0, 0, 0, 0, 32, 0, 0, 0, 0, 33, 0, + 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 35, + }; + const unsigned int numCompts = 11; + FastMatrixElim fe; + fe.makeTestMatrix( test, numCompts ); + fe.print(); + vector< unsigned int > parentVoxel; + bool ret = fe.buildTree( 0, parentVoxel ); + assert( ret ); + assert( parentVoxel[0] == static_cast< unsigned int >( -1 ) ); + assert( parentVoxel[1] == 0 ); + assert( parentVoxel[2] == 0 ); + assert( parentVoxel[3] == 0 ); + assert( parentVoxel[8] == 2 ); + assert( parentVoxel[10] == 3 ); + assert( parentVoxel[5] == 4 ); + assert( parentVoxel[9] == 4 ); + assert( parentVoxel[6] == 5 ); + assert( parentVoxel[7] == 6 ); + + assert( parentVoxel[10] == 2 ); + + /* + * This is the sequence of traversal. x means empty, s means sibling, + * . means below diagonal. The numbers are the sequence. + static double traverseIndex[] = { + // col 1 2 3 4 5 6 7 8 9 10 + #, 1, 2, 3, x, x, x, x, x, x, x, + ., #, x, x, x, x, x, x, x, x, x, + ., x, #, s, x, x, x, x, 4, x, x, + ., x, ., #, x, x, x, x, x, x, 5, + x, x, x, x, #, 6, x, x, s, 7, x, + x, x, x, x, ., #, 8, x, s, x, x, + x, x, x, x, x, ., #, 9, x, x, x, + x, x, x, x, x, x, ., #, x, x, x, + x, x, ., x, ., ., x, x, #, x, x, + x, x, x, x, ., x, x, x, x, #, x, + x, x, x, ., x, x, x, x, x, x, #, + }; + */ } #endif void testCalcJunction() { - Shell* s = reinterpret_cast< Shell* >( Id().eref().data() ); - // Make a neuron with same-size dend and spine. PSD is tiny. - // Put a, b, c in dend, b, c, d in spine, c, d, f in psd. No reacs. - // See settling of all concs by diffusion, pairwise. - Id model = s->doCreate( "Neutral", Id(), "model", 1 ); - Id dend = s->doCreate( "Compartment", model, "dend", 1 ); - Id neck = s->doCreate( "Compartment", model, "spine_neck", 1 ); - Id head = s->doCreate( "Compartment", model, "spine_head", 1 ); - Field< double >::set( dend, "x", 10e-6 ); - Field< double >::set( dend, "diameter", 2e-6 ); - Field< double >::set( dend, "length", 10e-6 ); - Field< double >::set( neck, "x0", 9e-6 ); - Field< double >::set( neck, "x", 9e-6 ); - Field< double >::set( neck, "y", 1e-6 ); - Field< double >::set( neck, "diameter", 0.5e-6 ); - Field< double >::set( neck, "length", 1.0e-6 ); - Field< double >::set( head, "x0", 9e-6 ); - Field< double >::set( head, "x", 9e-6 ); - Field< double >::set( head, "y0", 1e-6 ); - Field< double >::set( head, "y", 11e-6 ); - Field< double >::set( head, "diameter", 2e-6 ); - Field< double >::set( head, "length", 10e-6 ); - s->doAddMsg( "Single", ObjId( dend ), "raxial", ObjId( neck ), "axial"); - s->doAddMsg( "Single", ObjId( neck ), "raxial", ObjId( head ), "axial"); - - Id nm = s->doCreate( "NeuroMesh", model, "nm", 1 ); - Field< double >::set( nm, "diffLength", 10e-6 ); - Field< bool >::set( nm, "separateSpines", true ); - Id sm = s->doCreate( "SpineMesh", model, "sm", 1 ); - Id pm = s->doCreate( "PsdMesh", model, "pm", 1 ); - ObjId mid = s->doAddMsg( "Single", ObjId( nm ), "spineListOut", ObjId( sm ), "spineList" ); - assert( !mid.bad() ); - mid = s->doAddMsg( "Single", ObjId( nm ), "psdListOut", ObjId( pm ), "psdList" ); - Field< string >::set( nm, "subTreePath", "/model/#" ); - //SetGet2< Id, string >::set( nm, "cellPortion", model, "/model/#" ); - - vector< Id > pools( 9 ); - static string names[] = {"a", "b", "c", "b", "c", "d", "c", "d", "e" }; - static Id parents[] = {nm, nm, nm, sm, sm, sm, pm, pm, pm}; - for ( unsigned int i = 0; i < 9; ++i ) { - pools[i] = s->doCreate( "Pool", parents[i], names[i], 1 ); - assert( pools[i] != Id() ); - Field< double >::set( pools[i], "concInit", 1.0 + 1.0 * i ); - Field< double >::set( pools[i], "diffConst", 1e-11 ); - if ( i < 6 ) { - double vol = Field< double >::get( pools[i], "volume" ); - assert( doubleEq( vol, 10e-6 * 1e-12 * PI ) ); - } - } - Id dendsolve = s->doCreate( "Dsolve", model, "dendsolve", 1 ); - Id spinesolve = s->doCreate( "Dsolve", model, "spinesolve", 1 ); - Id psdsolve = s->doCreate( "Dsolve", model, "psdsolve", 1 ); - Field< Id >::set( dendsolve, "compartment", nm ); - Field< Id >::set( spinesolve, "compartment", sm ); - Field< Id >::set( psdsolve, "compartment", pm ); - Field< string >::set( dendsolve, "path", "/model/nm/#" ); - Field< string >::set( spinesolve, "path", "/model/sm/#" ); - Field< string >::set( psdsolve, "path", "/model/pm/#" ); - assert( Field< unsigned int >::get( dendsolve, "numAllVoxels" ) == 1 ); - assert( Field< unsigned int >::get( spinesolve, "numAllVoxels" ) == 1 ); - assert( Field< unsigned int >::get( psdsolve, "numAllVoxels" ) == 1 ); - assert( Field< unsigned int >::get( dendsolve, "numPools" ) == 3 ); - assert( Field< unsigned int >::get( spinesolve, "numPools" ) == 3 ); - assert( Field< unsigned int >::get( psdsolve, "numPools" ) == 3 ); - SetGet2< Id, Id >::set( dendsolve, "buildNeuroMeshJunctions", - spinesolve, psdsolve ); - s->doSetClock( 0, 0.01 ); - s->doUseClock( "/model/#solve", "process", 0 ); - s->doReinit(); - s->doStart( 100 ); - - /* - for ( unsigned int i = 0; i < 9; ++i ) { - double c = Field< double >::get( pools[i], "conc" ); - double n = Field< double >::get( pools[i], "n" ); - double v = Field< double >::get( pools[i], "volume" ); - cout << pools[i].path() << ": " << c << ", " << n << ", " << - n / v << ", " << - v << endl; - } - */ - s->doDelete( model ); - cout << "." << flush; + Shell* s = reinterpret_cast< Shell* >( Id().eref().data() ); + // Make a neuron with same-size dend and spine. PSD is tiny. + // Put a, b, c in dend, b, c, d in spine, c, d, f in psd. No reacs. + // See settling of all concs by diffusion, pairwise. + Id model = s->doCreate( "Neutral", Id(), "model", 1 ); + Id dend = s->doCreate( "Compartment", model, "dend", 1 ); + Id neck = s->doCreate( "Compartment", model, "spine_neck", 1 ); + Id head = s->doCreate( "Compartment", model, "spine_head", 1 ); + Field< double >::set( dend, "x", 10e-6 ); + Field< double >::set( dend, "diameter", 2e-6 ); + Field< double >::set( dend, "length", 10e-6 ); + Field< double >::set( neck, "x0", 9e-6 ); + Field< double >::set( neck, "x", 9e-6 ); + Field< double >::set( neck, "y", 1e-6 ); + Field< double >::set( neck, "diameter", 0.5e-6 ); + Field< double >::set( neck, "length", 1.0e-6 ); + Field< double >::set( head, "x0", 9e-6 ); + Field< double >::set( head, "x", 9e-6 ); + Field< double >::set( head, "y0", 1e-6 ); + Field< double >::set( head, "y", 11e-6 ); + Field< double >::set( head, "diameter", 2e-6 ); + Field< double >::set( head, "length", 10e-6 ); + s->doAddMsg( "Single", ObjId( dend ), "raxial", ObjId( neck ), "axial"); + s->doAddMsg( "Single", ObjId( neck ), "raxial", ObjId( head ), "axial"); + + Id nm = s->doCreate( "NeuroMesh", model, "nm", 1 ); + Field< double >::set( nm, "diffLength", 10e-6 ); + Field< bool >::set( nm, "separateSpines", true ); + Id sm = s->doCreate( "SpineMesh", model, "sm", 1 ); + Id pm = s->doCreate( "PsdMesh", model, "pm", 1 ); + ObjId mid = s->doAddMsg( "Single", ObjId( nm ), "spineListOut", ObjId( sm ), "spineList" ); + assert( !mid.bad() ); + mid = s->doAddMsg( "Single", ObjId( nm ), "psdListOut", ObjId( pm ), "psdList" ); + Field< string >::set( nm, "subTreePath", "/model/#" ); + //SetGet2< Id, string >::set( nm, "cellPortion", model, "/model/#" ); + + vector< Id > pools( 9 ); + static string names[] = {"a", "b", "c", "b", "c", "d", "c", "d", "e" }; + static Id parents[] = {nm, nm, nm, sm, sm, sm, pm, pm, pm}; + for ( unsigned int i = 0; i < 9; ++i ) + { + pools[i] = s->doCreate( "Pool", parents[i], names[i], 1 ); + assert( pools[i] != Id() ); + Field< double >::set( pools[i], "concInit", 1.0 + 1.0 * i ); + Field< double >::set( pools[i], "diffConst", 1e-11 ); + if ( i < 6 ) + { + double vol = Field< double >::get( pools[i], "volume" ); + assert( doubleEq( vol, 10e-6 * 1e-12 * PI ) ); + } + } + Id dendsolve = s->doCreate( "Dsolve", model, "dendsolve", 1 ); + Id spinesolve = s->doCreate( "Dsolve", model, "spinesolve", 1 ); + Id psdsolve = s->doCreate( "Dsolve", model, "psdsolve", 1 ); + Field< Id >::set( dendsolve, "compartment", nm ); + Field< Id >::set( spinesolve, "compartment", sm ); + Field< Id >::set( psdsolve, "compartment", pm ); + Field< string >::set( dendsolve, "path", "/model/nm/#" ); + Field< string >::set( spinesolve, "path", "/model/sm/#" ); + Field< string >::set( psdsolve, "path", "/model/pm/#" ); + assert( Field< unsigned int >::get( dendsolve, "numAllVoxels" ) == 1 ); + assert( Field< unsigned int >::get( spinesolve, "numAllVoxels" ) == 1 ); + assert( Field< unsigned int >::get( psdsolve, "numAllVoxels" ) == 1 ); + assert( Field< unsigned int >::get( dendsolve, "numPools" ) == 3 ); + assert( Field< unsigned int >::get( spinesolve, "numPools" ) == 3 ); + assert( Field< unsigned int >::get( psdsolve, "numPools" ) == 3 ); + SetGet2< Id, Id >::set( dendsolve, "buildNeuroMeshJunctions", + spinesolve, psdsolve ); + s->doSetClock( 0, 0.01 ); + s->doUseClock( "/model/#solve", "process", 0 ); + s->doReinit(); + s->doStart( 100 ); + + /* + for ( unsigned int i = 0; i < 9; ++i ) { + double c = Field< double >::get( pools[i], "conc" ); + double n = Field< double >::get( pools[i], "n" ); + double v = Field< double >::get( pools[i], "volume" ); + cout << pools[i].path() << ": " << c << ", " << n << ", " << + n / v << ", " << + v << endl; + } + */ + s->doDelete( model ); + cout << "." << flush; } void testDiffusion() { - testSorting(); - testFastMatrixElim(); - testSetDiffusionAndTransport(); - testCylDiffn(); - testTaperingCylDiffn(); - testSmallCellDiffn(); - testCellDiffn(); - testCylDiffnWithStoich(); - testCalcJunction(); + testSorting(); + testFastMatrixElim(); + testSetDiffusionAndTransport(); + testCylDiffn(); + testTaperingCylDiffn(); + testSmallCellDiffn(); + testCellDiffn(); + testCylDiffnWithStoich(); + testCalcJunction(); } diff --git a/external/boost-numeric-bindings/boost/numeric/bindings/lapack/gees.hpp b/external/boost-numeric-bindings/boost/numeric/bindings/lapack/gees.hpp index 472ef367..2c2531c9 100644 --- a/external/boost-numeric-bindings/boost/numeric/bindings/lapack/gees.hpp +++ b/external/boost-numeric-bindings/boost/numeric/bindings/lapack/gees.hpp @@ -140,9 +140,7 @@ namespace boost { namespace numeric { namespace bindings { >::value)); #endif -#ifndef NDEBUG typedef typename MatrA::value_type value_type ; -#endif int const n = traits::matrix_size1 (a); assert (n == traits::matrix_size2 (a)); @@ -187,9 +185,7 @@ namespace boost { namespace numeric { namespace bindings { >::value)); #endif -#ifndef NDEBUG typedef typename MatrA::value_type value_type ; -#endif int const n = traits::matrix_size1 (a); assert (n == traits::matrix_size2 (a)); @@ -269,9 +265,7 @@ namespace boost { namespace numeric { namespace bindings { inline int operator() (char jobvs, MatrA& a, EigVal& w, SchVec& vs, optimal_workspace ) const { typedef typename MatrA::value_type value_type ; -#ifndef NDEBUG typedef typename traits::type_traits< value_type >::real_type real_type ; -#endif int n = traits::matrix_size1( a ); @@ -284,10 +278,7 @@ namespace boost { namespace numeric { namespace bindings { inline int operator() (char jobvs, MatrA& a, EigVal& w, SchVec& vs, minimal_workspace ) const { typedef typename MatrA::value_type value_type ; - -#ifndef NDEBUG typedef typename traits::type_traits< value_type >::real_type real_type ; -#endif int n = traits::matrix_size1( a ); diff --git a/external/boost-numeric-bindings/boost/numeric/bindings/lapack/gesdd.hpp b/external/boost-numeric-bindings/boost/numeric/bindings/lapack/gesdd.hpp index b7d39f0f..f0ab7604 100644 --- a/external/boost-numeric-bindings/boost/numeric/bindings/lapack/gesdd.hpp +++ b/external/boost-numeric-bindings/boost/numeric/bindings/lapack/gesdd.hpp @@ -428,14 +428,9 @@ namespace boost { namespace numeric { namespace bindings { || (jobz == 'A' && traits::leading_dimension (vt) >= n) || (jobz == 'S' && traits::leading_dimension (vt) >= minmn)); -#ifndef BOOST_NUMERIC_BINDINGS_POOR_MANS_TRAITS - typedef typename traits::matrix_traits::value_type val_t; -#else - typedef typename MatrA::value_type val_t; -#endif - assert (traits::vector_size (w) - >= detail::gesdd_min_work (val_t(), jobz, m, n)); - assert (traits::vector_size (iw) >= detail::gesdd_iwork (m, n)); + //assert (traits::vector_size (w) + // >= detail::gesdd_min_work (val_t(), jobz, m, n)); + //assert (traits::vector_size (iw) >= detail::gesdd_iwork (m, n)); int info; detail::gesdd (jobz, m, n, @@ -507,16 +502,13 @@ namespace boost { namespace numeric { namespace bindings { && traits::leading_dimension (vt) >= n) || (jobz == 'A' && traits::leading_dimension (vt) >= n) || (jobz == 'S' && traits::leading_dimension (vt) >= minmn)); -#ifndef BOOST_NUMERIC_BINDINGS_POOR_MANS_TRAITS - typedef typename traits::matrix_traits::value_type val_t; -#else - typedef typename MatrA::value_type val_t; -#endif +#if 0 assert (traits::vector_size (w) >= detail::gesdd_min_work (val_t(), jobz, m, n)); assert (traits::vector_size (rw) >= detail::gesdd_rwork (val_t(), jobz, m, n)); assert (traits::vector_size (iw) >= detail::gesdd_iwork (m, n)); +#endif int info; detail::gesdd (jobz, m, n, diff --git a/external/boost-numeric-bindings/boost/numeric/bindings/lapack/gesvd.hpp b/external/boost-numeric-bindings/boost/numeric/bindings/lapack/gesvd.hpp index eba01080..3533b691 100644 --- a/external/boost-numeric-bindings/boost/numeric/bindings/lapack/gesvd.hpp +++ b/external/boost-numeric-bindings/boost/numeric/bindings/lapack/gesvd.hpp @@ -295,9 +295,7 @@ namespace boost { namespace numeric { namespace bindings { || (jobvt == 'A' && traits::leading_dimension (vt) >= n) || (jobvt == 'S' && traits::leading_dimension (vt) >= minmn)); #ifndef BOOST_NUMERIC_BINDINGS_POOR_MANS_TRAITS -#ifndef NDEBUG typedef typename traits::matrix_traits::value_type val_t; -#endif #else typedef typename MatrA::value_type val_t; #endif @@ -363,13 +361,9 @@ namespace boost { namespace numeric { namespace bindings { || (jobvt == 'O' && traits::leading_dimension (vt) >= 1) || (jobvt == 'A' && traits::leading_dimension (vt) >= n) || (jobvt == 'S' && traits::leading_dimension (vt) >= minmn)); -#ifndef BOOST_NUMERIC_BINDINGS_POOR_MANS_TRAITS - typedef typename traits::matrix_traits::value_type val_t; -#else - typedef typename MatrA::value_type val_t; -#endif - assert (traits::vector_size(w) >= detail::gesvd_min_work(val_t(),m,n)); - assert (traits::vector_size(rw) >= detail::gesvd_rwork(val_t(),m,n)); + + // assert (traits::vector_size(w) >= detail::gesvd_min_work(val_t(),m,n)); + // assert (traits::vector_size(rw) >= detail::gesvd_rwork(val_t(),m,n)); int info; detail::gesvd (jobu, jobvt, m, n, diff --git a/external/boost-numeric-bindings/boost/numeric/bindings/lapack/ormqr.hpp b/external/boost-numeric-bindings/boost/numeric/bindings/lapack/ormqr.hpp index efbec080..f7be063c 100644 --- a/external/boost-numeric-bindings/boost/numeric/bindings/lapack/ormqr.hpp +++ b/external/boost-numeric-bindings/boost/numeric/bindings/lapack/ormqr.hpp @@ -214,7 +214,7 @@ namespace boost { namespace numeric { namespace bindings { template inline int ormqr (char side, char trans, const A& a, const Tau& tau, C& c, detail::workspace1 workspace ) { - typedef typename A::value_type value_type ; + // typedef typename A::value_type value_type ; return detail::ormqr( side, trans, a, tau, c, workspace.w_ ); } diff --git a/external/boost-numeric-bindings/boost/numeric/bindings/lapack/syev.hpp b/external/boost-numeric-bindings/boost/numeric/bindings/lapack/syev.hpp index fdd5253b..89e75bee 100644 --- a/external/boost-numeric-bindings/boost/numeric/bindings/lapack/syev.hpp +++ b/external/boost-numeric-bindings/boost/numeric/bindings/lapack/syev.hpp @@ -137,9 +137,7 @@ namespace boost { namespace numeric { namespace bindings { inline int syev (char jobz, char uplo, A& a, W& w, detail::workspace1 workspace ) { -#ifndef NDEBUG typedef typename A::value_type value_type ; -#endif return detail::syev(jobz, uplo, a, w, workspace.w_); } // syev() @@ -198,9 +196,7 @@ namespace boost { namespace numeric { namespace bindings { template inline int syev (char jobz, A& a, W& w, detail::workspace1 workspace ) { -#ifndef NDEBUG typedef typename A::value_type value_type ; -#endif char uplo = traits::matrix_uplo_tag( a ) ; #ifndef BOOST_NUMERIC_BINDINGS_NO_STRUCTURE_CHECK typedef typename traits::matrix_traits::matrix_structure matrix_structure ; diff --git a/external/exprtk/exprtk.hpp b/external/exprtk/exprtk.hpp new file mode 100644 index 00000000..75ee0de4 --- /dev/null +++ b/external/exprtk/exprtk.hpp @@ -0,0 +1,38962 @@ +/* + ****************************************************************** + * C++ Mathematical Expression Toolkit Library * + * * + * Author: Arash Partow (1999-2020) * + * URL: http://www.partow.net/programming/exprtk/index.html * + * * + * Copyright notice: * + * Free use of the C++ Mathematical Expression Toolkit Library is * + * permitted under the guidelines and in accordance with the most * + * current version of the MIT License. * + * http://www.opensource.org/licenses/MIT * + * * + * Example expressions: * + * (00) (y + x / y) * (x - y / x) * + * (01) (x^2 / sin(2 * pi / y)) - x / 2 * + * (02) sqrt(1 - (x^2)) * + * (03) 1 - sin(2 * x) + cos(pi / y) * + * (04) a * exp(2 * t) + c * + * (05) if(((x + 2) == 3) and ((y + 5) <= 9),1 + w, 2 / z) * + * (06) (avg(x,y) <= x + y ? x - y : x * y) + 2 * pi / x * + * (07) z := x + sin(2 * pi / y) * + * (08) u := 2 * (pi * z) / (w := x + cos(y / pi)) * + * (09) clamp(-1,sin(2 * pi * x) + cos(y / 2 * pi),+1) * + * (10) inrange(-2,m,+2) == if(({-2 <= m} and [m <= +2]),1,0) * + * (11) (2sin(x)cos(2y)7 + 1) == (2 * sin(x) * cos(2*y) * 7 + 1) * + * (12) (x ilike 's*ri?g') and [y < (3 z^7 + w)] * + * * + ****************************************************************** +*/ + + +#ifndef INCLUDE_EXPRTK_HPP +#define INCLUDE_EXPRTK_HPP + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace exprtk +{ + #ifdef exprtk_enable_debugging + #define exprtk_debug(params) printf params + #else + #define exprtk_debug(params) (void)0 + #endif + + #define exprtk_error_location \ + "exprtk.hpp:" + details::to_str(__LINE__) \ + + #if defined(__GNUC__) && (__GNUC__ >= 7) + + #define exprtk_disable_fallthrough_begin \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") \ + + #define exprtk_disable_fallthrough_end \ + _Pragma ("GCC diagnostic pop") \ + + #else + #define exprtk_disable_fallthrough_begin (void)0; + #define exprtk_disable_fallthrough_end (void)0; + #endif + + namespace details + { + typedef unsigned char uchar_t; + typedef char char_t; + typedef uchar_t* uchar_ptr; + typedef char_t* char_ptr; + typedef uchar_t const* uchar_cptr; + typedef char_t const* char_cptr; + + inline bool is_whitespace(const char_t c) + { + return (' ' == c) || ('\n' == c) || + ('\r' == c) || ('\t' == c) || + ('\b' == c) || ('\v' == c) || + ('\f' == c) ; + } + + inline bool is_operator_char(const char_t c) + { + return ('+' == c) || ('-' == c) || + ('*' == c) || ('/' == c) || + ('^' == c) || ('<' == c) || + ('>' == c) || ('=' == c) || + (',' == c) || ('!' == c) || + ('(' == c) || (')' == c) || + ('[' == c) || (']' == c) || + ('{' == c) || ('}' == c) || + ('%' == c) || (':' == c) || + ('?' == c) || ('&' == c) || + ('|' == c) || (';' == c) ; + } + + inline bool is_letter(const char_t c) + { + return (('a' <= c) && (c <= 'z')) || + (('A' <= c) && (c <= 'Z')) ; + } + + inline bool is_digit(const char_t c) + { + return ('0' <= c) && (c <= '9'); + } + + inline bool is_letter_or_digit(const char_t c) + { + return is_letter(c) || is_digit(c); + } + + inline bool is_left_bracket(const char_t c) + { + return ('(' == c) || ('[' == c) || ('{' == c); + } + + inline bool is_right_bracket(const char_t c) + { + return (')' == c) || (']' == c) || ('}' == c); + } + + inline bool is_bracket(const char_t c) + { + return is_left_bracket(c) || is_right_bracket(c); + } + + inline bool is_sign(const char_t c) + { + return ('+' == c) || ('-' == c); + } + + inline bool is_invalid(const char_t c) + { + return !is_whitespace (c) && + !is_operator_char(c) && + !is_letter (c) && + !is_digit (c) && + ('.' != c) && + ('_' != c) && + ('$' != c) && + ('~' != c) && + ('\'' != c); + } + + #ifndef exprtk_disable_caseinsensitivity + inline void case_normalise(std::string& s) + { + for (std::size_t i = 0; i < s.size(); ++i) + { + s[i] = static_cast(std::tolower(s[i])); + } + } + + inline bool imatch(const char_t c1, const char_t c2) + { + return std::tolower(c1) == std::tolower(c2); + } + + inline bool imatch(const std::string& s1, const std::string& s2) + { + if (s1.size() == s2.size()) + { + for (std::size_t i = 0; i < s1.size(); ++i) + { + if (std::tolower(s1[i]) != std::tolower(s2[i])) + { + return false; + } + } + + return true; + } + + return false; + } + + struct ilesscompare + { + inline bool operator() (const std::string& s1, const std::string& s2) const + { + const std::size_t length = std::min(s1.size(),s2.size()); + + for (std::size_t i = 0; i < length; ++i) + { + const char_t c1 = static_cast(std::tolower(s1[i])); + const char_t c2 = static_cast(std::tolower(s2[i])); + + if (c1 > c2) + return false; + else if (c1 < c2) + return true; + } + + return s1.size() < s2.size(); + } + }; + + #else + inline void case_normalise(std::string&) + {} + + inline bool imatch(const char_t c1, const char_t c2) + { + return c1 == c2; + } + + inline bool imatch(const std::string& s1, const std::string& s2) + { + return s1 == s2; + } + + struct ilesscompare + { + inline bool operator() (const std::string& s1, const std::string& s2) const + { + return s1 < s2; + } + }; + #endif + + inline bool is_valid_sf_symbol(const std::string& symbol) + { + // Special function: $f12 or $F34 + return (4 == symbol.size()) && + ('$' == symbol[0]) && + imatch('f',symbol[1]) && + is_digit(symbol[2]) && + is_digit(symbol[3]); + } + + inline const char_t& front(const std::string& s) + { + return s[0]; + } + + inline const char_t& back(const std::string& s) + { + return s[s.size() - 1]; + } + + inline std::string to_str(int i) + { + if (0 == i) + return std::string("0"); + + std::string result; + + if (i < 0) + { + for ( ; i; i /= 10) + { + result += '0' + char(-(i % 10)); + } + + result += '-'; + } + else + { + for ( ; i; i /= 10) + { + result += '0' + char(i % 10); + } + } + + std::reverse(result.begin(), result.end()); + + return result; + } + + inline std::string to_str(std::size_t i) + { + return to_str(static_cast(i)); + } + + inline bool is_hex_digit(const std::string::value_type digit) + { + return (('0' <= digit) && (digit <= '9')) || + (('A' <= digit) && (digit <= 'F')) || + (('a' <= digit) && (digit <= 'f')) ; + } + + inline uchar_t hex_to_bin(uchar_t h) + { + if (('0' <= h) && (h <= '9')) + return (h - '0'); + else + return static_cast(std::toupper(h) - 'A'); + } + + template + inline void parse_hex(Iterator& itr, Iterator end, std::string::value_type& result) + { + if ( + (end != (itr )) && + (end != (itr + 1)) && + (end != (itr + 2)) && + (end != (itr + 3)) && + ('0' == *(itr )) && + ( + ('x' == *(itr + 1)) || + ('X' == *(itr + 1)) + ) && + (is_hex_digit(*(itr + 2))) && + (is_hex_digit(*(itr + 3))) + ) + { + result = hex_to_bin(static_cast(*(itr + 2))) << 4 | + hex_to_bin(static_cast(*(itr + 3))) ; + itr += 3; + } + else + result = '\0'; + } + + inline void cleanup_escapes(std::string& s) + { + typedef std::string::iterator str_itr_t; + + str_itr_t itr1 = s.begin(); + str_itr_t itr2 = s.begin(); + str_itr_t end = s.end (); + + std::size_t removal_count = 0; + + while (end != itr1) + { + if ('\\' == (*itr1)) + { + ++removal_count; + + if (end == ++itr1) + break; + else if ('\\' != (*itr1)) + { + switch (*itr1) + { + case 'n' : (*itr1) = '\n'; break; + case 'r' : (*itr1) = '\r'; break; + case 't' : (*itr1) = '\t'; break; + case '0' : parse_hex(itr1, end, (*itr1)); + removal_count += 3; + break; + } + + continue; + } + } + + if (itr1 != itr2) + { + (*itr2) = (*itr1); + } + + ++itr1; + ++itr2; + } + + s.resize(s.size() - removal_count); + } + + class build_string + { + public: + + build_string(const std::size_t& initial_size = 64) + { + data_.reserve(initial_size); + } + + inline build_string& operator << (const std::string& s) + { + data_ += s; + return (*this); + } + + inline build_string& operator << (char_cptr s) + { + data_ += std::string(s); + return (*this); + } + + inline operator std::string () const + { + return data_; + } + + inline std::string as_string() const + { + return data_; + } + + private: + + std::string data_; + }; + + static const std::string reserved_words[] = + { + "break", "case", "continue", "default", "false", "for", + "if", "else", "ilike", "in", "like", "and", "nand", "nor", + "not", "null", "or", "repeat", "return", "shl", "shr", + "swap", "switch", "true", "until", "var", "while", "xnor", + "xor", "&", "|" + }; + + static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string); + + static const std::string reserved_symbols[] = + { + "abs", "acos", "acosh", "and", "asin", "asinh", "atan", + "atanh", "atan2", "avg", "break", "case", "ceil", "clamp", + "continue", "cos", "cosh", "cot", "csc", "default", + "deg2grad", "deg2rad", "equal", "erf", "erfc", "exp", + "expm1", "false", "floor", "for", "frac", "grad2deg", + "hypot", "iclamp", "if", "else", "ilike", "in", "inrange", + "like", "log", "log10", "log2", "logn", "log1p", "mand", + "max", "min", "mod", "mor", "mul", "ncdf", "nand", "nor", + "not", "not_equal", "null", "or", "pow", "rad2deg", + "repeat", "return", "root", "round", "roundn", "sec", "sgn", + "shl", "shr", "sin", "sinc", "sinh", "sqrt", "sum", "swap", + "switch", "tan", "tanh", "true", "trunc", "until", "var", + "while", "xnor", "xor", "&", "|" + }; + + static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string); + + static const std::string base_function_list[] = + { + "abs", "acos", "acosh", "asin", "asinh", "atan", "atanh", + "atan2", "avg", "ceil", "clamp", "cos", "cosh", "cot", + "csc", "equal", "erf", "erfc", "exp", "expm1", "floor", + "frac", "hypot", "iclamp", "like", "log", "log10", "log2", + "logn", "log1p", "mand", "max", "min", "mod", "mor", "mul", + "ncdf", "pow", "root", "round", "roundn", "sec", "sgn", + "sin", "sinc", "sinh", "sqrt", "sum", "swap", "tan", "tanh", + "trunc", "not_equal", "inrange", "deg2grad", "deg2rad", + "rad2deg", "grad2deg" + }; + + static const std::size_t base_function_list_size = sizeof(base_function_list) / sizeof(std::string); + + static const std::string logic_ops_list[] = + { + "and", "nand", "nor", "not", "or", "xnor", "xor", "&", "|" + }; + + static const std::size_t logic_ops_list_size = sizeof(logic_ops_list) / sizeof(std::string); + + static const std::string cntrl_struct_list[] = + { + "if", "switch", "for", "while", "repeat", "return" + }; + + static const std::size_t cntrl_struct_list_size = sizeof(cntrl_struct_list) / sizeof(std::string); + + static const std::string arithmetic_ops_list[] = + { + "+", "-", "*", "/", "%", "^" + }; + + static const std::size_t arithmetic_ops_list_size = sizeof(arithmetic_ops_list) / sizeof(std::string); + + static const std::string assignment_ops_list[] = + { + ":=", "+=", "-=", + "*=", "/=", "%=" + }; + + static const std::size_t assignment_ops_list_size = sizeof(assignment_ops_list) / sizeof(std::string); + + static const std::string inequality_ops_list[] = + { + "<", "<=", "==", + "=", "!=", "<>", + ">=", ">" + }; + + static const std::size_t inequality_ops_list_size = sizeof(inequality_ops_list) / sizeof(std::string); + + inline bool is_reserved_word(const std::string& symbol) + { + for (std::size_t i = 0; i < reserved_words_size; ++i) + { + if (imatch(symbol, reserved_words[i])) + { + return true; + } + } + + return false; + } + + inline bool is_reserved_symbol(const std::string& symbol) + { + for (std::size_t i = 0; i < reserved_symbols_size; ++i) + { + if (imatch(symbol, reserved_symbols[i])) + { + return true; + } + } + + return false; + } + + inline bool is_base_function(const std::string& function_name) + { + for (std::size_t i = 0; i < base_function_list_size; ++i) + { + if (imatch(function_name, base_function_list[i])) + { + return true; + } + } + + return false; + } + + inline bool is_control_struct(const std::string& cntrl_strct) + { + for (std::size_t i = 0; i < cntrl_struct_list_size; ++i) + { + if (imatch(cntrl_strct, cntrl_struct_list[i])) + { + return true; + } + } + + return false; + } + + inline bool is_logic_opr(const std::string& lgc_opr) + { + for (std::size_t i = 0; i < logic_ops_list_size; ++i) + { + if (imatch(lgc_opr, logic_ops_list[i])) + { + return true; + } + } + + return false; + } + + struct cs_match + { + static inline bool cmp(const char_t c0, const char_t c1) + { + return (c0 == c1); + } + }; + + struct cis_match + { + static inline bool cmp(const char_t c0, const char_t c1) + { + return (std::tolower(c0) == std::tolower(c1)); + } + }; + + template + inline bool match_impl(const Iterator pattern_begin, + const Iterator pattern_end , + const Iterator data_begin , + const Iterator data_end , + const typename std::iterator_traits::value_type& zero_or_more, + const typename std::iterator_traits::value_type& zero_or_one ) + { + const Iterator null_itr(0); + + Iterator d_itr = data_begin; + Iterator p_itr = pattern_begin; + Iterator tb_p_itr = null_itr; + Iterator tb_d_itr = null_itr; + + while (d_itr != data_end) + { + if (zero_or_more == *p_itr) + { + while ((pattern_end != p_itr) && ((zero_or_more == *p_itr) || (zero_or_one == *p_itr))) + { + ++p_itr; + } + + if (pattern_end == p_itr) + return true; + + const typename std::iterator_traits::value_type c = *(p_itr); + + while ((data_end != d_itr) && !Compare::cmp(c,*d_itr)) + { + ++d_itr; + } + + tb_p_itr = p_itr; + tb_d_itr = d_itr; + + continue; + } + else if (!Compare::cmp(*p_itr, *d_itr) && (zero_or_one != *p_itr)) + { + if (null_itr == tb_d_itr) + return false; + + d_itr = tb_d_itr++; + p_itr = tb_p_itr; + + continue; + } + + ++p_itr; + ++d_itr; + } + + while ((pattern_end != p_itr) && ((zero_or_more == *p_itr) || (zero_or_one == *p_itr))) + { + ++p_itr; + } + + return (pattern_end == p_itr); + } + + inline bool wc_match(const std::string& wild_card, + const std::string& str) + { + return match_impl(wild_card.data(), + wild_card.data() + wild_card.size(), + str.data(), + str.data() + str.size(), + '*', + '?'); + } + + inline bool wc_imatch(const std::string& wild_card, + const std::string& str) + { + return match_impl(wild_card.data(), + wild_card.data() + wild_card.size(), + str.data(), + str.data() + str.size(), + '*', + '?'); + } + + inline bool sequence_match(const std::string& pattern, + const std::string& str, + std::size_t& diff_index, + char_t& diff_value) + { + if (str.empty()) + { + return ("Z" == pattern); + } + else if ('*' == pattern[0]) + return false; + + typedef std::string::const_iterator itr_t; + + itr_t p_itr = pattern.begin(); + itr_t s_itr = str .begin(); + + itr_t p_end = pattern.end(); + itr_t s_end = str .end(); + + while ((s_end != s_itr) && (p_end != p_itr)) + { + if ('*' == (*p_itr)) + { + const char_t target = static_cast(std::toupper(*(p_itr - 1))); + + if ('*' == target) + { + diff_index = static_cast(std::distance(str.begin(),s_itr)); + diff_value = static_cast(std::toupper(*p_itr)); + + return false; + } + else + ++p_itr; + + while (s_itr != s_end) + { + if (target != std::toupper(*s_itr)) + break; + else + ++s_itr; + } + + continue; + } + else if ( + ('?' != *p_itr) && + std::toupper(*p_itr) != std::toupper(*s_itr) + ) + { + diff_index = static_cast(std::distance(str.begin(),s_itr)); + diff_value = static_cast(std::toupper(*p_itr)); + + return false; + } + + ++p_itr; + ++s_itr; + } + + return ( + (s_end == s_itr) && + ( + (p_end == p_itr) || + ('*' == *p_itr) + ) + ); + } + + static const double pow10[] = { + 1.0, + 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, + 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, + 1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012, + 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016 + }; + + static const std::size_t pow10_size = sizeof(pow10) / sizeof(double); + + namespace numeric + { + namespace constant + { + static const double e = 2.71828182845904523536028747135266249775724709369996; + static const double pi = 3.14159265358979323846264338327950288419716939937510; + static const double pi_2 = 1.57079632679489661923132169163975144209858469968755; + static const double pi_4 = 0.78539816339744830961566084581987572104929234984378; + static const double pi_180 = 0.01745329251994329576923690768488612713442871888542; + static const double _1_pi = 0.31830988618379067153776752674502872406891929148091; + static const double _2_pi = 0.63661977236758134307553505349005744813783858296183; + static const double _180_pi = 57.29577951308232087679815481410517033240547246656443; + static const double log2 = 0.69314718055994530941723212145817656807550013436026; + static const double sqrt2 = 1.41421356237309504880168872420969807856967187537695; + } + + namespace details + { + struct unknown_type_tag { unknown_type_tag() {} }; + struct real_type_tag { real_type_tag () {} }; + struct complex_type_tag { complex_type_tag() {} }; + struct int_type_tag { int_type_tag () {} }; + + template + struct number_type + { + typedef unknown_type_tag type; + number_type() {} + }; + + #define exprtk_register_real_type_tag(T) \ + template<> struct number_type \ + { typedef real_type_tag type; number_type() {} }; \ + + #define exprtk_register_complex_type_tag(T) \ + template<> struct number_type > \ + { typedef complex_type_tag type; number_type() {} }; \ + + #define exprtk_register_int_type_tag(T) \ + template<> struct number_type \ + { typedef int_type_tag type; number_type() {} }; \ + + exprtk_register_real_type_tag(double ) + exprtk_register_real_type_tag(long double) + exprtk_register_real_type_tag(float ) + + exprtk_register_complex_type_tag(double ) + exprtk_register_complex_type_tag(long double) + exprtk_register_complex_type_tag(float ) + + exprtk_register_int_type_tag(short ) + exprtk_register_int_type_tag(int ) + exprtk_register_int_type_tag(long long int ) + exprtk_register_int_type_tag(unsigned short ) + exprtk_register_int_type_tag(unsigned int ) + exprtk_register_int_type_tag(unsigned long long int) + + #undef exprtk_register_real_type_tag + #undef exprtk_register_int_type_tag + + template + struct epsilon_type + { + static inline T value() + { + const T epsilon = T(0.0000000001); + return epsilon; + } + }; + + template <> + struct epsilon_type + { + static inline float value() + { + const float epsilon = float(0.000001f); + return epsilon; + } + }; + + template <> + struct epsilon_type + { + static inline long double value() + { + const long double epsilon = (long double)(0.000000000001); + return epsilon; + } + }; + + template + inline bool is_nan_impl(const T v, real_type_tag) + { + return std::not_equal_to()(v,v); + } + + template + inline int to_int32_impl(const T v, real_type_tag) + { + return static_cast(v); + } + + template + inline long long int to_int64_impl(const T v, real_type_tag) + { + return static_cast(v); + } + + template + inline bool is_true_impl(const T v) + { + return std::not_equal_to()(T(0),v); + } + + template + inline bool is_false_impl(const T v) + { + return std::equal_to()(T(0),v); + } + + template + inline T abs_impl(const T v, real_type_tag) + { + return ((v < T(0)) ? -v : v); + } + + template + inline T min_impl(const T v0, const T v1, real_type_tag) + { + return std::min(v0,v1); + } + + template + inline T max_impl(const T v0, const T v1, real_type_tag) + { + return std::max(v0,v1); + } + + template + inline T equal_impl(const T v0, const T v1, real_type_tag) + { + const T epsilon = epsilon_type::value(); + return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(T(1),std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? T(1) : T(0); + } + + inline float equal_impl(const float v0, const float v1, real_type_tag) + { + const float epsilon = epsilon_type::value(); + return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(1.0f,std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? 1.0f : 0.0f; + } + + template + inline T equal_impl(const T v0, const T v1, int_type_tag) + { + return (v0 == v1) ? 1 : 0; + } + + template + inline T expm1_impl(const T v, real_type_tag) + { + // return std::expm1(v); + if (abs_impl(v,real_type_tag()) < T(0.00001)) + return v + (T(0.5) * v * v); + else + return std::exp(v) - T(1); + } + + template + inline T expm1_impl(const T v, int_type_tag) + { + return T(std::exp(v)) - T(1); + } + + template + inline T nequal_impl(const T v0, const T v1, real_type_tag) + { + typedef real_type_tag rtg; + const T epsilon = epsilon_type::value(); + return (abs_impl(v0 - v1,rtg()) > (std::max(T(1),std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? T(1) : T(0); + } + + inline float nequal_impl(const float v0, const float v1, real_type_tag) + { + typedef real_type_tag rtg; + const float epsilon = epsilon_type::value(); + return (abs_impl(v0 - v1,rtg()) > (std::max(1.0f,std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? 1.0f : 0.0f; + } + + template + inline T nequal_impl(const T v0, const T v1, int_type_tag) + { + return (v0 != v1) ? 1 : 0; + } + + template + inline T modulus_impl(const T v0, const T v1, real_type_tag) + { + return std::fmod(v0,v1); + } + + template + inline T modulus_impl(const T v0, const T v1, int_type_tag) + { + return v0 % v1; + } + + template + inline T pow_impl(const T v0, const T v1, real_type_tag) + { + return std::pow(v0,v1); + } + + template + inline T pow_impl(const T v0, const T v1, int_type_tag) + { + return std::pow(static_cast(v0),static_cast(v1)); + } + + template + inline T logn_impl(const T v0, const T v1, real_type_tag) + { + return std::log(v0) / std::log(v1); + } + + template + inline T logn_impl(const T v0, const T v1, int_type_tag) + { + return static_cast(logn_impl(static_cast(v0),static_cast(v1),real_type_tag())); + } + + template + inline T log1p_impl(const T v, real_type_tag) + { + if (v > T(-1)) + { + if (abs_impl(v,real_type_tag()) > T(0.0001)) + { + return std::log(T(1) + v); + } + else + return (T(-0.5) * v + T(1)) * v; + } + else + return std::numeric_limits::quiet_NaN(); + } + + template + inline T log1p_impl(const T v, int_type_tag) + { + if (v > T(-1)) + { + return std::log(T(1) + v); + } + else + return std::numeric_limits::quiet_NaN(); + } + + template + inline T root_impl(const T v0, const T v1, real_type_tag) + { + if (v1 < T(0)) + return std::numeric_limits::quiet_NaN(); + + const std::size_t n = static_cast(v1); + + if ((v0 < T(0)) && (0 == (n % 2))) + return std::numeric_limits::quiet_NaN(); + + return std::pow(v0, T(1) / n); + } + + template + inline T root_impl(const T v0, const T v1, int_type_tag) + { + return root_impl(static_cast(v0),static_cast(v1),real_type_tag()); + } + + template + inline T round_impl(const T v, real_type_tag) + { + return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5))); + } + + template + inline T roundn_impl(const T v0, const T v1, real_type_tag) + { + const int index = std::max(0, std::min(pow10_size - 1, (int)std::floor(v1))); + const T p10 = T(pow10[index]); + + if (v0 < T(0)) + return T(std::ceil ((v0 * p10) - T(0.5)) / p10); + else + return T(std::floor((v0 * p10) + T(0.5)) / p10); + } + + template + inline T roundn_impl(const T v0, const T, int_type_tag) + { + return v0; + } + + template + inline T hypot_impl(const T v0, const T v1, real_type_tag) + { + return std::sqrt((v0 * v0) + (v1 * v1)); + } + + template + inline T hypot_impl(const T v0, const T v1, int_type_tag) + { + return static_cast(std::sqrt(static_cast((v0 * v0) + (v1 * v1)))); + } + + template + inline T atan2_impl(const T v0, const T v1, real_type_tag) + { + return std::atan2(v0,v1); + } + + template + inline T atan2_impl(const T, const T, int_type_tag) + { + return 0; + } + + template + inline T shr_impl(const T v0, const T v1, real_type_tag) + { + return v0 * (T(1) / std::pow(T(2),static_cast(static_cast(v1)))); + } + + template + inline T shr_impl(const T v0, const T v1, int_type_tag) + { + return v0 >> v1; + } + + template + inline T shl_impl(const T v0, const T v1, real_type_tag) + { + return v0 * std::pow(T(2),static_cast(static_cast(v1))); + } + + template + inline T shl_impl(const T v0, const T v1, int_type_tag) + { + return v0 << v1; + } + + template + inline T sgn_impl(const T v, real_type_tag) + { + if (v > T(0)) return T(+1); + else if (v < T(0)) return T(-1); + else return T( 0); + } + + template + inline T sgn_impl(const T v, int_type_tag) + { + if (v > T(0)) return T(+1); + else if (v < T(0)) return T(-1); + else return T( 0); + } + + template + inline T and_impl(const T v0, const T v1, real_type_tag) + { + return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0); + } + + template + inline T and_impl(const T v0, const T v1, int_type_tag) + { + return v0 && v1; + } + + template + inline T nand_impl(const T v0, const T v1, real_type_tag) + { + return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0); + } + + template + inline T nand_impl(const T v0, const T v1, int_type_tag) + { + return !(v0 && v1); + } + + template + inline T or_impl(const T v0, const T v1, real_type_tag) + { + return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0); + } + + template + inline T or_impl(const T v0, const T v1, int_type_tag) + { + return (v0 || v1); + } + + template + inline T nor_impl(const T v0, const T v1, real_type_tag) + { + return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0); + } + + template + inline T nor_impl(const T v0, const T v1, int_type_tag) + { + return !(v0 || v1); + } + + template + inline T xor_impl(const T v0, const T v1, real_type_tag) + { + return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0); + } + + template + inline T xor_impl(const T v0, const T v1, int_type_tag) + { + return v0 ^ v1; + } + + template + inline T xnor_impl(const T v0, const T v1, real_type_tag) + { + const bool v0_true = is_true_impl(v0); + const bool v1_true = is_true_impl(v1); + + if ((v0_true && v1_true) || (!v0_true && !v1_true)) + return T(1); + else + return T(0); + } + + template + inline T xnor_impl(const T v0, const T v1, int_type_tag) + { + const bool v0_true = is_true_impl(v0); + const bool v1_true = is_true_impl(v1); + + if ((v0_true && v1_true) || (!v0_true && !v1_true)) + return T(1); + else + return T(0); + } + + #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER) + #define exprtk_define_erf(TT,impl) \ + inline TT erf_impl(TT v) { return impl(v); } \ + + exprtk_define_erf( float,::erff) + exprtk_define_erf( double,::erf ) + exprtk_define_erf(long double,::erfl) + #undef exprtk_define_erf + #endif + + template + inline T erf_impl(T v, real_type_tag) + { + #if defined(_MSC_VER) && (_MSC_VER < 1900) + // Credits: Abramowitz & Stegun Equations 7.1.25-28 + static const T c[] = { + T( 1.26551223), T(1.00002368), + T( 0.37409196), T(0.09678418), + T(-0.18628806), T(0.27886807), + T(-1.13520398), T(1.48851587), + T(-0.82215223), T(0.17087277) + }; + + const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag())); + + T result = T(1) - t * std::exp((-v * v) - + c[0] + t * (c[1] + t * + (c[2] + t * (c[3] + t * + (c[4] + t * (c[5] + t * + (c[6] + t * (c[7] + t * + (c[8] + t * (c[9])))))))))); + + return (v >= T(0)) ? result : -result; + #else + return erf_impl(v); + #endif + } + + template + inline T erf_impl(T v, int_type_tag) + { + return erf_impl(static_cast(v),real_type_tag()); + } + + #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER) + #define exprtk_define_erfc(TT,impl) \ + inline TT erfc_impl(TT v) { return impl(v); } \ + + exprtk_define_erfc( float,::erfcf) + exprtk_define_erfc( double,::erfc ) + exprtk_define_erfc(long double,::erfcl) + #undef exprtk_define_erfc + #endif + + template + inline T erfc_impl(T v, real_type_tag) + { + #if defined(_MSC_VER) && (_MSC_VER < 1900) + return T(1) - erf_impl(v,real_type_tag()); + #else + return erfc_impl(v); + #endif + } + + template + inline T erfc_impl(T v, int_type_tag) + { + return erfc_impl(static_cast(v),real_type_tag()); + } + + template + inline T ncdf_impl(T v, real_type_tag) + { + T cnd = T(0.5) * (T(1) + erf_impl( + abs_impl(v,real_type_tag()) / + T(numeric::constant::sqrt2),real_type_tag())); + return (v < T(0)) ? (T(1) - cnd) : cnd; + } + + template + inline T ncdf_impl(T v, int_type_tag) + { + return ncdf_impl(static_cast(v),real_type_tag()); + } + + template + inline T sinc_impl(T v, real_type_tag) + { + if (std::abs(v) >= std::numeric_limits::epsilon()) + return(std::sin(v) / v); + else + return T(1); + } + + template + inline T sinc_impl(T v, int_type_tag) + { + return sinc_impl(static_cast(v),real_type_tag()); + } + + template inline T acos_impl(const T v, real_type_tag) { return std::acos (v); } + template inline T acosh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) - T(1))); } + template inline T asin_impl(const T v, real_type_tag) { return std::asin (v); } + template inline T asinh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) + T(1))); } + template inline T atan_impl(const T v, real_type_tag) { return std::atan (v); } + template inline T atanh_impl(const T v, real_type_tag) { return (std::log(T(1) + v) - std::log(T(1) - v)) / T(2); } + template inline T ceil_impl(const T v, real_type_tag) { return std::ceil (v); } + template inline T cos_impl(const T v, real_type_tag) { return std::cos (v); } + template inline T cosh_impl(const T v, real_type_tag) { return std::cosh (v); } + template inline T exp_impl(const T v, real_type_tag) { return std::exp (v); } + template inline T floor_impl(const T v, real_type_tag) { return std::floor(v); } + template inline T log_impl(const T v, real_type_tag) { return std::log (v); } + template inline T log10_impl(const T v, real_type_tag) { return std::log10(v); } + template inline T log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); } + template inline T neg_impl(const T v, real_type_tag) { return -v; } + template inline T pos_impl(const T v, real_type_tag) { return +v; } + template inline T sin_impl(const T v, real_type_tag) { return std::sin (v); } + template inline T sinh_impl(const T v, real_type_tag) { return std::sinh (v); } + template inline T sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); } + template inline T tan_impl(const T v, real_type_tag) { return std::tan (v); } + template inline T tanh_impl(const T v, real_type_tag) { return std::tanh (v); } + template inline T cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); } + template inline T sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); } + template inline T csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); } + template inline T r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); } + template inline T d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180)); } + template inline T d2g_impl(const T v, real_type_tag) { return (v * T(20.0/9.0)); } + template inline T g2d_impl(const T v, real_type_tag) { return (v * T(9.0/20.0)); } + template inline T notl_impl(const T v, real_type_tag) { return (std::not_equal_to()(T(0),v) ? T(0) : T(1)); } + template inline T frac_impl(const T v, real_type_tag) { return (v - static_cast(v)); } + template inline T trunc_impl(const T v, real_type_tag) { return T(static_cast(v)); } + + template inline T const_pi_impl(real_type_tag) { return T(numeric::constant::pi); } + template inline T const_e_impl (real_type_tag) { return T(numeric::constant::e); } + + template inline T abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); } + template inline T exp_impl(const T v, int_type_tag) { return std::exp (v); } + template inline T log_impl(const T v, int_type_tag) { return std::log (v); } + template inline T log10_impl(const T v, int_type_tag) { return std::log10(v); } + template inline T log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); } + template inline T neg_impl(const T v, int_type_tag) { return -v; } + template inline T pos_impl(const T v, int_type_tag) { return +v; } + template inline T ceil_impl(const T v, int_type_tag) { return v; } + template inline T floor_impl(const T v, int_type_tag) { return v; } + template inline T round_impl(const T v, int_type_tag) { return v; } + template inline T notl_impl(const T v, int_type_tag) { return !v; } + template inline T sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); } + template inline T frac_impl(const T , int_type_tag) { return T(0); } + template inline T trunc_impl(const T v, int_type_tag) { return v; } + template inline T acos_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T acosh_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T asin_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T asinh_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T atan_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T atanh_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T cos_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T cosh_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T sin_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T sinh_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T tan_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T tanh_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T cot_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T sec_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T csc_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + + template + inline bool is_integer_impl(const T& v, real_type_tag) + { + return std::equal_to()(T(0),std::fmod(v,T(1))); + } + + template + inline bool is_integer_impl(const T&, int_type_tag) + { + return true; + } + } + + template + struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; }; + + template<> struct numeric_info { enum { length = 10, size = 16, bound_length = 9}; }; + template<> struct numeric_info { enum { min_exp = -38, max_exp = +38}; }; + template<> struct numeric_info { enum { min_exp = -308, max_exp = +308}; }; + template<> struct numeric_info { enum { min_exp = -308, max_exp = +308}; }; + + template + inline int to_int32(const T v) + { + const typename details::number_type::type num_type; + return to_int32_impl(v, num_type); + } + + template + inline long long int to_int64(const T v) + { + const typename details::number_type::type num_type; + return to_int64_impl(v, num_type); + } + + template + inline bool is_nan(const T v) + { + const typename details::number_type::type num_type; + return is_nan_impl(v, num_type); + } + + template + inline T min(const T v0, const T v1) + { + const typename details::number_type::type num_type; + return min_impl(v0, v1, num_type); + } + + template + inline T max(const T v0, const T v1) + { + const typename details::number_type::type num_type; + return max_impl(v0, v1, num_type); + } + + template + inline T equal(const T v0, const T v1) + { + const typename details::number_type::type num_type; + return equal_impl(v0, v1, num_type); + } + + template + inline T nequal(const T v0, const T v1) + { + const typename details::number_type::type num_type; + return nequal_impl(v0, v1, num_type); + } + + template + inline T modulus(const T v0, const T v1) + { + const typename details::number_type::type num_type; + return modulus_impl(v0, v1, num_type); + } + + template + inline T pow(const T v0, const T v1) + { + const typename details::number_type::type num_type; + return pow_impl(v0, v1, num_type); + } + + template + inline T logn(const T v0, const T v1) + { + const typename details::number_type::type num_type; + return logn_impl(v0, v1, num_type); + } + + template + inline T root(const T v0, const T v1) + { + const typename details::number_type::type num_type; + return root_impl(v0, v1, num_type); + } + + template + inline T roundn(const T v0, const T v1) + { + const typename details::number_type::type num_type; + return roundn_impl(v0, v1, num_type); + } + + template + inline T hypot(const T v0, const T v1) + { + const typename details::number_type::type num_type; + return hypot_impl(v0, v1, num_type); + } + + template + inline T atan2(const T v0, const T v1) + { + const typename details::number_type::type num_type; + return atan2_impl(v0, v1, num_type); + } + + template + inline T shr(const T v0, const T v1) + { + const typename details::number_type::type num_type; + return shr_impl(v0, v1, num_type); + } + + template + inline T shl(const T v0, const T v1) + { + const typename details::number_type::type num_type; + return shl_impl(v0, v1, num_type); + } + + template + inline T and_opr(const T v0, const T v1) + { + const typename details::number_type::type num_type; + return and_impl(v0, v1, num_type); + } + + template + inline T nand_opr(const T v0, const T v1) + { + const typename details::number_type::type num_type; + return nand_impl(v0, v1, num_type); + } + + template + inline T or_opr(const T v0, const T v1) + { + const typename details::number_type::type num_type; + return or_impl(v0, v1, num_type); + } + + template + inline T nor_opr(const T v0, const T v1) + { + const typename details::number_type::type num_type; + return nor_impl(v0, v1, num_type); + } + + template + inline T xor_opr(const T v0, const T v1) + { + const typename details::number_type::type num_type; + return xor_impl(v0, v1, num_type); + } + + template + inline T xnor_opr(const T v0, const T v1) + { + const typename details::number_type::type num_type; + return xnor_impl(v0, v1, num_type); + } + + template + inline bool is_integer(const T v) + { + const typename details::number_type::type num_type; + return is_integer_impl(v, num_type); + } + + template + struct fast_exp + { + static inline T result(T v) + { + unsigned int k = N; + T l = T(1); + + while (k) + { + if (k & 1) + { + l *= v; + --k; + } + + v *= v; + k >>= 1; + } + + return l; + } + }; + + template struct fast_exp { static inline T result(T v) { T v_5 = fast_exp::result(v); return v_5 * v_5; } }; + template struct fast_exp { static inline T result(T v) { return fast_exp::result(v) * v; } }; + template struct fast_exp { static inline T result(T v) { T v_4 = fast_exp::result(v); return v_4 * v_4; } }; + template struct fast_exp { static inline T result(T v) { return fast_exp::result(v) * v; } }; + template struct fast_exp { static inline T result(T v) { T v_3 = fast_exp::result(v); return v_3 * v_3; } }; + template struct fast_exp { static inline T result(T v) { return fast_exp::result(v) * v; } }; + template struct fast_exp { static inline T result(T v) { T v_2 = v * v; return v_2 * v_2; } }; + template struct fast_exp { static inline T result(T v) { return v * v * v; } }; + template struct fast_exp { static inline T result(T v) { return v * v; } }; + template struct fast_exp { static inline T result(T v) { return v; } }; + template struct fast_exp { static inline T result(T ) { return T(1); } }; + + #define exprtk_define_unary_function(FunctionName) \ + template \ + inline T FunctionName (const T v) \ + { \ + const typename details::number_type::type num_type; \ + return FunctionName##_impl(v,num_type); \ + } \ + + exprtk_define_unary_function(abs ) + exprtk_define_unary_function(acos ) + exprtk_define_unary_function(acosh) + exprtk_define_unary_function(asin ) + exprtk_define_unary_function(asinh) + exprtk_define_unary_function(atan ) + exprtk_define_unary_function(atanh) + exprtk_define_unary_function(ceil ) + exprtk_define_unary_function(cos ) + exprtk_define_unary_function(cosh ) + exprtk_define_unary_function(exp ) + exprtk_define_unary_function(expm1) + exprtk_define_unary_function(floor) + exprtk_define_unary_function(log ) + exprtk_define_unary_function(log10) + exprtk_define_unary_function(log2 ) + exprtk_define_unary_function(log1p) + exprtk_define_unary_function(neg ) + exprtk_define_unary_function(pos ) + exprtk_define_unary_function(round) + exprtk_define_unary_function(sin ) + exprtk_define_unary_function(sinc ) + exprtk_define_unary_function(sinh ) + exprtk_define_unary_function(sqrt ) + exprtk_define_unary_function(tan ) + exprtk_define_unary_function(tanh ) + exprtk_define_unary_function(cot ) + exprtk_define_unary_function(sec ) + exprtk_define_unary_function(csc ) + exprtk_define_unary_function(r2d ) + exprtk_define_unary_function(d2r ) + exprtk_define_unary_function(d2g ) + exprtk_define_unary_function(g2d ) + exprtk_define_unary_function(notl ) + exprtk_define_unary_function(sgn ) + exprtk_define_unary_function(erf ) + exprtk_define_unary_function(erfc ) + exprtk_define_unary_function(ncdf ) + exprtk_define_unary_function(frac ) + exprtk_define_unary_function(trunc) + #undef exprtk_define_unary_function + } + + template + inline T compute_pow10(T d, const int exponent) + { + static const double fract10[] = + { + 0.0, + 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, 1.0E+009, 1.0E+010, + 1.0E+011, 1.0E+012, 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016, 1.0E+017, 1.0E+018, 1.0E+019, 1.0E+020, + 1.0E+021, 1.0E+022, 1.0E+023, 1.0E+024, 1.0E+025, 1.0E+026, 1.0E+027, 1.0E+028, 1.0E+029, 1.0E+030, + 1.0E+031, 1.0E+032, 1.0E+033, 1.0E+034, 1.0E+035, 1.0E+036, 1.0E+037, 1.0E+038, 1.0E+039, 1.0E+040, + 1.0E+041, 1.0E+042, 1.0E+043, 1.0E+044, 1.0E+045, 1.0E+046, 1.0E+047, 1.0E+048, 1.0E+049, 1.0E+050, + 1.0E+051, 1.0E+052, 1.0E+053, 1.0E+054, 1.0E+055, 1.0E+056, 1.0E+057, 1.0E+058, 1.0E+059, 1.0E+060, + 1.0E+061, 1.0E+062, 1.0E+063, 1.0E+064, 1.0E+065, 1.0E+066, 1.0E+067, 1.0E+068, 1.0E+069, 1.0E+070, + 1.0E+071, 1.0E+072, 1.0E+073, 1.0E+074, 1.0E+075, 1.0E+076, 1.0E+077, 1.0E+078, 1.0E+079, 1.0E+080, + 1.0E+081, 1.0E+082, 1.0E+083, 1.0E+084, 1.0E+085, 1.0E+086, 1.0E+087, 1.0E+088, 1.0E+089, 1.0E+090, + 1.0E+091, 1.0E+092, 1.0E+093, 1.0E+094, 1.0E+095, 1.0E+096, 1.0E+097, 1.0E+098, 1.0E+099, 1.0E+100, + 1.0E+101, 1.0E+102, 1.0E+103, 1.0E+104, 1.0E+105, 1.0E+106, 1.0E+107, 1.0E+108, 1.0E+109, 1.0E+110, + 1.0E+111, 1.0E+112, 1.0E+113, 1.0E+114, 1.0E+115, 1.0E+116, 1.0E+117, 1.0E+118, 1.0E+119, 1.0E+120, + 1.0E+121, 1.0E+122, 1.0E+123, 1.0E+124, 1.0E+125, 1.0E+126, 1.0E+127, 1.0E+128, 1.0E+129, 1.0E+130, + 1.0E+131, 1.0E+132, 1.0E+133, 1.0E+134, 1.0E+135, 1.0E+136, 1.0E+137, 1.0E+138, 1.0E+139, 1.0E+140, + 1.0E+141, 1.0E+142, 1.0E+143, 1.0E+144, 1.0E+145, 1.0E+146, 1.0E+147, 1.0E+148, 1.0E+149, 1.0E+150, + 1.0E+151, 1.0E+152, 1.0E+153, 1.0E+154, 1.0E+155, 1.0E+156, 1.0E+157, 1.0E+158, 1.0E+159, 1.0E+160, + 1.0E+161, 1.0E+162, 1.0E+163, 1.0E+164, 1.0E+165, 1.0E+166, 1.0E+167, 1.0E+168, 1.0E+169, 1.0E+170, + 1.0E+171, 1.0E+172, 1.0E+173, 1.0E+174, 1.0E+175, 1.0E+176, 1.0E+177, 1.0E+178, 1.0E+179, 1.0E+180, + 1.0E+181, 1.0E+182, 1.0E+183, 1.0E+184, 1.0E+185, 1.0E+186, 1.0E+187, 1.0E+188, 1.0E+189, 1.0E+190, + 1.0E+191, 1.0E+192, 1.0E+193, 1.0E+194, 1.0E+195, 1.0E+196, 1.0E+197, 1.0E+198, 1.0E+199, 1.0E+200, + 1.0E+201, 1.0E+202, 1.0E+203, 1.0E+204, 1.0E+205, 1.0E+206, 1.0E+207, 1.0E+208, 1.0E+209, 1.0E+210, + 1.0E+211, 1.0E+212, 1.0E+213, 1.0E+214, 1.0E+215, 1.0E+216, 1.0E+217, 1.0E+218, 1.0E+219, 1.0E+220, + 1.0E+221, 1.0E+222, 1.0E+223, 1.0E+224, 1.0E+225, 1.0E+226, 1.0E+227, 1.0E+228, 1.0E+229, 1.0E+230, + 1.0E+231, 1.0E+232, 1.0E+233, 1.0E+234, 1.0E+235, 1.0E+236, 1.0E+237, 1.0E+238, 1.0E+239, 1.0E+240, + 1.0E+241, 1.0E+242, 1.0E+243, 1.0E+244, 1.0E+245, 1.0E+246, 1.0E+247, 1.0E+248, 1.0E+249, 1.0E+250, + 1.0E+251, 1.0E+252, 1.0E+253, 1.0E+254, 1.0E+255, 1.0E+256, 1.0E+257, 1.0E+258, 1.0E+259, 1.0E+260, + 1.0E+261, 1.0E+262, 1.0E+263, 1.0E+264, 1.0E+265, 1.0E+266, 1.0E+267, 1.0E+268, 1.0E+269, 1.0E+270, + 1.0E+271, 1.0E+272, 1.0E+273, 1.0E+274, 1.0E+275, 1.0E+276, 1.0E+277, 1.0E+278, 1.0E+279, 1.0E+280, + 1.0E+281, 1.0E+282, 1.0E+283, 1.0E+284, 1.0E+285, 1.0E+286, 1.0E+287, 1.0E+288, 1.0E+289, 1.0E+290, + 1.0E+291, 1.0E+292, 1.0E+293, 1.0E+294, 1.0E+295, 1.0E+296, 1.0E+297, 1.0E+298, 1.0E+299, 1.0E+300, + 1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308 + }; + + static const int fract10_size = static_cast(sizeof(fract10) / sizeof(double)); + + const int e = std::abs(exponent); + + if (exponent >= std::numeric_limits::min_exponent10) + { + if (e < fract10_size) + { + if (exponent > 0) + return T(d * fract10[e]); + else + return T(d / fract10[e]); + } + else + return T(d * std::pow(10.0, 10.0 * exponent)); + } + else + { + d /= T(fract10[ -std::numeric_limits::min_exponent10]); + return T(d / fract10[-exponent + std::numeric_limits::min_exponent10]); + } + } + + template + inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, T& result) + { + if (itr == end) + return false; + + const bool negative = ('-' == (*itr)); + + if (negative || ('+' == (*itr))) + { + if (end == ++itr) + return false; + } + + static const uchar_t zero = static_cast('0'); + + while ((end != itr) && (zero == (*itr))) ++itr; + + bool return_result = true; + unsigned int digit = 0; + const std::size_t length = static_cast(std::distance(itr,end)); + + if (length <= 4) + { + exprtk_disable_fallthrough_begin + switch (length) + { + #ifdef exprtk_use_lut + + #define exprtk_process_digit \ + if ((digit = details::digit_table[(int)*itr++]) < 10) \ + result = result * 10 + (digit); \ + else \ + { \ + return_result = false; \ + break; \ + } \ + + #else + + #define exprtk_process_digit \ + if ((digit = (*itr++ - zero)) < 10) \ + result = result * T(10) + digit; \ + else \ + { \ + return_result = false; \ + break; \ + } \ + + #endif + + case 4 : exprtk_process_digit + case 3 : exprtk_process_digit + case 2 : exprtk_process_digit + case 1 : if ((digit = (*itr - zero))>= 10) { digit = 0; return_result = false; } + + #undef exprtk_process_digit + } + exprtk_disable_fallthrough_end + } + else + return_result = false; + + if (length && return_result) + { + result = result * 10 + static_cast(digit); + ++itr; + } + + result = negative ? -result : result; + return return_result; + } + + template + static inline bool parse_nan(Iterator& itr, const Iterator end, T& t) + { + typedef typename std::iterator_traits::value_type type; + + static const std::size_t nan_length = 3; + + if (std::distance(itr,end) != static_cast(nan_length)) + return false; + + if (static_cast('n') == (*itr)) + { + if ( + (static_cast('a') != *(itr + 1)) || + (static_cast('n') != *(itr + 2)) + ) + { + return false; + } + } + else if ( + (static_cast('A') != *(itr + 1)) || + (static_cast('N') != *(itr + 2)) + ) + { + return false; + } + + t = std::numeric_limits::quiet_NaN(); + + return true; + } + + template + static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, bool negative) + { + static const char_t inf_uc[] = "INFINITY"; + static const char_t inf_lc[] = "infinity"; + static const std::size_t inf_length = 8; + + const std::size_t length = static_cast(std::distance(itr,end)); + + if ((3 != length) && (inf_length != length)) + return false; + + char_cptr inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc; + + while (end != itr) + { + if (*inf_itr == static_cast(*itr)) + { + ++itr; + ++inf_itr; + continue; + } + else + return false; + } + + if (negative) + t = -std::numeric_limits::infinity(); + else + t = std::numeric_limits::infinity(); + + return true; + } + + template + inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag) + { + if (end == itr_external) return false; + + Iterator itr = itr_external; + + T d = T(0); + + const bool negative = ('-' == (*itr)); + + if (negative || '+' == (*itr)) + { + if (end == ++itr) + return false; + } + + bool instate = false; + + static const char_t zero = static_cast('0'); + + #define parse_digit_1(d) \ + if ((digit = (*itr - zero)) < 10) \ + { d = d * T(10) + digit; } \ + else \ + { break; } \ + if (end == ++itr) break; \ + + #define parse_digit_2(d) \ + if ((digit = (*itr - zero)) < 10) \ + { d = d * T(10) + digit; } \ + else { break; } \ + ++itr; \ + + if ('.' != (*itr)) + { + const Iterator curr = itr; + + while ((end != itr) && (zero == (*itr))) ++itr; + + unsigned int digit; + + while (end != itr) + { + // Note: For 'physical' superscalar architectures it + // is advised that the following loop be: 4xPD1 and 1xPD2 + #ifdef exprtk_enable_superscalar + parse_digit_1(d) + parse_digit_1(d) + #endif + parse_digit_1(d) + parse_digit_1(d) + parse_digit_2(d) + } + + if (curr != itr) instate = true; + } + + int exponent = 0; + + if (end != itr) + { + if ('.' == (*itr)) + { + const Iterator curr = ++itr; + unsigned int digit; + T tmp_d = T(0); + + while (end != itr) + { + #ifdef exprtk_enable_superscalar + parse_digit_1(tmp_d) + parse_digit_1(tmp_d) + parse_digit_1(tmp_d) + #endif + parse_digit_1(tmp_d) + parse_digit_1(tmp_d) + parse_digit_2(tmp_d) + } + + if (curr != itr) + { + instate = true; + d += compute_pow10(tmp_d,static_cast(-std::distance(curr,itr))); + } + + #undef parse_digit_1 + #undef parse_digit_2 + } + + if (end != itr) + { + typename std::iterator_traits::value_type c = (*itr); + + if (('e' == c) || ('E' == c)) + { + int exp = 0; + + if (!details::string_to_type_converter_impl_ref(++itr, end, exp)) + { + if (end == itr) + return false; + else + c = (*itr); + } + + exponent += exp; + } + + if (end != itr) + { + if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c)) + ++itr; + else if ('#' == c) + { + if (end == ++itr) + return false; + else if (('I' <= (*itr)) && ((*itr) <= 'n')) + { + if (('i' == (*itr)) || ('I' == (*itr))) + { + return parse_inf(itr, end, t, negative); + } + else if (('n' == (*itr)) || ('N' == (*itr))) + { + return parse_nan(itr, end, t); + } + else + return false; + } + else + return false; + } + else if (('I' <= (*itr)) && ((*itr) <= 'n')) + { + if (('i' == (*itr)) || ('I' == (*itr))) + { + return parse_inf(itr, end, t, negative); + } + else if (('n' == (*itr)) || ('N' == (*itr))) + { + return parse_nan(itr, end, t); + } + else + return false; + } + else + return false; + } + } + } + + if ((end != itr) || (!instate)) + return false; + else if (exponent) + d = compute_pow10(d,exponent); + + t = static_cast((negative) ? -d : d); + return true; + } + + template + inline bool string_to_real(const std::string& s, T& t) + { + const typename numeric::details::number_type::type num_type; + + char_cptr begin = s.data(); + char_cptr end = s.data() + s.size(); + + return string_to_real(begin, end, t, num_type); + } + + template + struct functor_t + { + /* + Note: The following definitions for Type, may require tweaking + based on the compiler and target architecture. The benchmark + should provide enough information to make the right choice. + */ + //typedef T Type; + //typedef const T Type; + typedef const T& Type; + typedef T& RefType; + typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3); + typedef T (*tfunc_t)(Type t0, Type t1, Type t2); + typedef T (*bfunc_t)(Type t0, Type t1); + typedef T (*ufunc_t)(Type t0); + }; + + } // namespace details + + namespace lexer + { + struct token + { + enum token_type + { + e_none = 0, e_error = 1, e_err_symbol = 2, + e_err_number = 3, e_err_string = 4, e_err_sfunc = 5, + e_eof = 6, e_number = 7, e_symbol = 8, + e_string = 9, e_assign = 10, e_addass = 11, + e_subass = 12, e_mulass = 13, e_divass = 14, + e_modass = 15, e_shr = 16, e_shl = 17, + e_lte = 18, e_ne = 19, e_gte = 20, + e_swap = 21, e_lt = '<', e_gt = '>', + e_eq = '=', e_rbracket = ')', e_lbracket = '(', + e_rsqrbracket = ']', e_lsqrbracket = '[', e_rcrlbracket = '}', + e_lcrlbracket = '{', e_comma = ',', e_add = '+', + e_sub = '-', e_div = '/', e_mul = '*', + e_mod = '%', e_pow = '^', e_colon = ':', + e_ternary = '?' + }; + + token() + : type(e_none), + value(""), + position(std::numeric_limits::max()) + {} + + void clear() + { + type = e_none; + value = ""; + position = std::numeric_limits::max(); + } + + template + inline token& set_operator(const token_type tt, + const Iterator begin, const Iterator end, + const Iterator base_begin = Iterator(0)) + { + type = tt; + value.assign(begin,end); + if (base_begin) + position = static_cast(std::distance(base_begin,begin)); + return (*this); + } + + template + inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) + { + type = e_symbol; + value.assign(begin,end); + if (base_begin) + position = static_cast(std::distance(base_begin,begin)); + return (*this); + } + + template + inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) + { + type = e_number; + value.assign(begin,end); + if (base_begin) + position = static_cast(std::distance(base_begin,begin)); + return (*this); + } + + template + inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) + { + type = e_string; + value.assign(begin,end); + if (base_begin) + position = static_cast(std::distance(base_begin,begin)); + return (*this); + } + + inline token& set_string(const std::string& s, const std::size_t p) + { + type = e_string; + value = s; + position = p; + return (*this); + } + + template + inline token& set_error(const token_type et, + const Iterator begin, const Iterator end, + const Iterator base_begin = Iterator(0)) + { + if ( + (e_error == et) || + (e_err_symbol == et) || + (e_err_number == et) || + (e_err_string == et) || + (e_err_sfunc == et) + ) + { + type = et; + } + else + type = e_error; + + value.assign(begin,end); + + if (base_begin) + position = static_cast(std::distance(base_begin,begin)); + + return (*this); + } + + static inline std::string to_str(token_type t) + { + switch (t) + { + case e_none : return "NONE"; + case e_error : return "ERROR"; + case e_err_symbol : return "ERROR_SYMBOL"; + case e_err_number : return "ERROR_NUMBER"; + case e_err_string : return "ERROR_STRING"; + case e_eof : return "EOF"; + case e_number : return "NUMBER"; + case e_symbol : return "SYMBOL"; + case e_string : return "STRING"; + case e_assign : return ":="; + case e_addass : return "+="; + case e_subass : return "-="; + case e_mulass : return "*="; + case e_divass : return "/="; + case e_modass : return "%="; + case e_shr : return ">>"; + case e_shl : return "<<"; + case e_lte : return "<="; + case e_ne : return "!="; + case e_gte : return ">="; + case e_lt : return "<"; + case e_gt : return ">"; + case e_eq : return "="; + case e_rbracket : return ")"; + case e_lbracket : return "("; + case e_rsqrbracket : return "]"; + case e_lsqrbracket : return "["; + case e_rcrlbracket : return "}"; + case e_lcrlbracket : return "{"; + case e_comma : return ","; + case e_add : return "+"; + case e_sub : return "-"; + case e_div : return "/"; + case e_mul : return "*"; + case e_mod : return "%"; + case e_pow : return "^"; + case e_colon : return ":"; + case e_ternary : return "?"; + case e_swap : return "<=>"; + default : return "UNKNOWN"; + } + } + + inline bool is_error() const + { + return ( + (e_error == type) || + (e_err_symbol == type) || + (e_err_number == type) || + (e_err_string == type) || + (e_err_sfunc == type) + ); + } + + token_type type; + std::string value; + std::size_t position; + }; + + class generator + { + public: + + typedef token token_t; + typedef std::vector token_list_t; + typedef std::vector::iterator token_list_itr_t; + typedef details::char_t char_t; + + generator() + : base_itr_(0), + s_itr_ (0), + s_end_ (0) + { + clear(); + } + + inline void clear() + { + base_itr_ = 0; + s_itr_ = 0; + s_end_ = 0; + token_list_.clear(); + token_itr_ = token_list_.end(); + store_token_itr_ = token_list_.end(); + } + + inline bool process(const std::string& str) + { + base_itr_ = str.data(); + s_itr_ = str.data(); + s_end_ = str.data() + str.size(); + + eof_token_.set_operator(token_t::e_eof,s_end_,s_end_,base_itr_); + token_list_.clear(); + + while (!is_end(s_itr_)) + { + scan_token(); + + if (!token_list_.empty() && token_list_.back().is_error()) + return false; + } + + return true; + } + + inline bool empty() const + { + return token_list_.empty(); + } + + inline std::size_t size() const + { + return token_list_.size(); + } + + inline void begin() + { + token_itr_ = token_list_.begin(); + store_token_itr_ = token_list_.begin(); + } + + inline void store() + { + store_token_itr_ = token_itr_; + } + + inline void restore() + { + token_itr_ = store_token_itr_; + } + + inline token_t& next_token() + { + if (token_list_.end() != token_itr_) + { + return *token_itr_++; + } + else + return eof_token_; + } + + inline token_t& peek_next_token() + { + if (token_list_.end() != token_itr_) + { + return *token_itr_; + } + else + return eof_token_; + } + + inline token_t& operator[](const std::size_t& index) + { + if (index < token_list_.size()) + return token_list_[index]; + else + return eof_token_; + } + + inline token_t operator[](const std::size_t& index) const + { + if (index < token_list_.size()) + return token_list_[index]; + else + return eof_token_; + } + + inline bool finished() const + { + return (token_list_.end() == token_itr_); + } + + inline void insert_front(token_t::token_type tk_type) + { + if ( + !token_list_.empty() && + (token_list_.end() != token_itr_) + ) + { + token_t t = *token_itr_; + + t.type = tk_type; + token_itr_ = token_list_.insert(token_itr_,t); + } + } + + inline std::string substr(const std::size_t& begin, const std::size_t& end) + { + const details::char_cptr begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_; + const details::char_cptr end_itr = ((base_itr_ + end) < s_end_) ? (base_itr_ + end) : s_end_; + + return std::string(begin_itr,end_itr); + } + + inline std::string remaining() const + { + if (finished()) + return ""; + else if (token_list_.begin() != token_itr_) + return std::string(base_itr_ + (token_itr_ - 1)->position,s_end_); + else + return std::string(base_itr_ + token_itr_->position,s_end_); + } + + private: + + inline bool is_end(details::char_cptr itr) + { + return (s_end_ == itr); + } + + inline bool is_comment_start(details::char_cptr itr) + { + #ifndef exprtk_disable_comments + const char_t c0 = *(itr + 0); + const char_t c1 = *(itr + 1); + + if ('#' == c0) + return true; + else if (!is_end(itr + 1)) + { + if (('/' == c0) && ('/' == c1)) return true; + if (('/' == c0) && ('*' == c1)) return true; + } + #endif + return false; + } + + inline void skip_whitespace() + { + while (!is_end(s_itr_) && details::is_whitespace(*s_itr_)) + { + ++s_itr_; + } + } + + inline void skip_comments() + { + #ifndef exprtk_disable_comments + // The following comment styles are supported: + // 1. // .... \n + // 2. # .... \n + // 3. /* .... */ + struct test + { + static inline bool comment_start(const char_t c0, const char_t c1, int& mode, int& incr) + { + mode = 0; + if ('#' == c0) { mode = 1; incr = 1; } + else if ('/' == c0) + { + if ('/' == c1) { mode = 1; incr = 2; } + else if ('*' == c1) { mode = 2; incr = 2; } + } + return (0 != mode); + } + + static inline bool comment_end(const char_t c0, const char_t c1, int& mode) + { + if ( + ((1 == mode) && ('\n' == c0)) || + ((2 == mode) && ( '*' == c0) && ('/' == c1)) + ) + { + mode = 0; + return true; + } + else + return false; + } + }; + + int mode = 0; + int increment = 0; + + if (is_end(s_itr_)) + return; + else if (!test::comment_start(*s_itr_, *(s_itr_ + 1), mode, increment)) + return; + + details::char_cptr cmt_start = s_itr_; + + s_itr_ += increment; + + while (!is_end(s_itr_)) + { + if ((1 == mode) && test::comment_end(*s_itr_, 0, mode)) + { + ++s_itr_; + return; + } + + if ((2 == mode)) + { + if (!is_end((s_itr_ + 1)) && test::comment_end(*s_itr_, *(s_itr_ + 1), mode)) + { + s_itr_ += 2; + return; + } + } + + ++s_itr_; + } + + if (2 == mode) + { + token_t t; + t.set_error(token::e_error, cmt_start, cmt_start + mode, base_itr_); + token_list_.push_back(t); + } + #endif + } + + inline void scan_token() + { + if (details::is_whitespace(*s_itr_)) + { + skip_whitespace(); + return; + } + else if (is_comment_start(s_itr_)) + { + skip_comments(); + return; + } + else if (details::is_operator_char(*s_itr_)) + { + scan_operator(); + return; + } + else if (details::is_letter(*s_itr_)) + { + scan_symbol(); + return; + } + else if (details::is_digit((*s_itr_)) || ('.' == (*s_itr_))) + { + scan_number(); + return; + } + else if ('$' == (*s_itr_)) + { + scan_special_function(); + return; + } + #ifndef exprtk_disable_string_capabilities + else if ('\'' == (*s_itr_)) + { + scan_string(); + return; + } + #endif + else if ('~' == (*s_itr_)) + { + token_t t; + t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); + token_list_.push_back(t); + ++s_itr_; + return; + } + else + { + token_t t; + t.set_error(token::e_error, s_itr_, s_itr_ + 2, base_itr_); + token_list_.push_back(t); + ++s_itr_; + } + } + + inline void scan_operator() + { + token_t t; + + const char_t c0 = s_itr_[0]; + + if (!is_end(s_itr_ + 1)) + { + const char_t c1 = s_itr_[1]; + + if (!is_end(s_itr_ + 2)) + { + const char_t c2 = s_itr_[2]; + + if ((c0 == '<') && (c1 == '=') && (c2 == '>')) + { + t.set_operator(token_t::e_swap, s_itr_, s_itr_ + 3, base_itr_); + token_list_.push_back(t); + s_itr_ += 3; + return; + } + } + + token_t::token_type ttype = token_t::e_none; + + if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte; + else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte; + else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne; + else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne; + else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq; + else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign; + else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl; + else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr; + else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass; + else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass; + else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass; + else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass; + else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass; + + if (token_t::e_none != ttype) + { + t.set_operator(ttype, s_itr_, s_itr_ + 2, base_itr_); + token_list_.push_back(t); + s_itr_ += 2; + return; + } + } + + if ('<' == c0) + t.set_operator(token_t::e_lt , s_itr_, s_itr_ + 1, base_itr_); + else if ('>' == c0) + t.set_operator(token_t::e_gt , s_itr_, s_itr_ + 1, base_itr_); + else if (';' == c0) + t.set_operator(token_t::e_eof, s_itr_, s_itr_ + 1, base_itr_); + else if ('&' == c0) + t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); + else if ('|' == c0) + t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); + else + t.set_operator(token_t::token_type(c0), s_itr_, s_itr_ + 1, base_itr_); + + token_list_.push_back(t); + ++s_itr_; + } + + inline void scan_symbol() + { + details::char_cptr initial_itr = s_itr_; + + while (!is_end(s_itr_)) + { + if (!details::is_letter_or_digit(*s_itr_) && ('_' != (*s_itr_))) + { + if ('.' != (*s_itr_)) + break; + /* + Permit symbols that contain a 'dot' + Allowed : abc.xyz, a123.xyz, abc.123, abc_.xyz a123_.xyz abc._123 + Disallowed: .abc, abc., abc., abc. + */ + if ( + (s_itr_ != initial_itr) && + !is_end(s_itr_ + 1) && + !details::is_letter_or_digit(*(s_itr_ + 1)) && + ('_' != (*(s_itr_ + 1))) + ) + break; + } + + ++s_itr_; + } + + token_t t; + t.set_symbol(initial_itr,s_itr_,base_itr_); + token_list_.push_back(t); + } + + inline void scan_number() + { + /* + Attempt to match a valid numeric value in one of the following formats: + (01) 123456 + (02) 123456. + (03) 123.456 + (04) 123.456e3 + (05) 123.456E3 + (06) 123.456e+3 + (07) 123.456E+3 + (08) 123.456e-3 + (09) 123.456E-3 + (00) .1234 + (11) .1234e3 + (12) .1234E+3 + (13) .1234e+3 + (14) .1234E-3 + (15) .1234e-3 + */ + + details::char_cptr initial_itr = s_itr_; + bool dot_found = false; + bool e_found = false; + bool post_e_sign_found = false; + bool post_e_digit_found = false; + token_t t; + + while (!is_end(s_itr_)) + { + if ('.' == (*s_itr_)) + { + if (dot_found) + { + t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); + token_list_.push_back(t); + return; + } + + dot_found = true; + ++s_itr_; + + continue; + } + else if ('e' == std::tolower(*s_itr_)) + { + const char_t& c = *(s_itr_ + 1); + + if (is_end(s_itr_ + 1)) + { + t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); + token_list_.push_back(t); + + return; + } + else if ( + ('+' != c) && + ('-' != c) && + !details::is_digit(c) + ) + { + t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); + token_list_.push_back(t); + + return; + } + + e_found = true; + ++s_itr_; + + continue; + } + else if (e_found && details::is_sign(*s_itr_) && !post_e_digit_found) + { + if (post_e_sign_found) + { + t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); + token_list_.push_back(t); + + return; + } + + post_e_sign_found = true; + ++s_itr_; + + continue; + } + else if (e_found && details::is_digit(*s_itr_)) + { + post_e_digit_found = true; + ++s_itr_; + + continue; + } + else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_)) + break; + else + ++s_itr_; + } + + t.set_numeric(initial_itr, s_itr_, base_itr_); + token_list_.push_back(t); + + return; + } + + inline void scan_special_function() + { + details::char_cptr initial_itr = s_itr_; + token_t t; + + // $fdd(x,x,x) = at least 11 chars + if (std::distance(s_itr_,s_end_) < 11) + { + t.set_error(token::e_err_sfunc, initial_itr, s_itr_, base_itr_); + token_list_.push_back(t); + + return; + } + + if ( + !(('$' == *s_itr_) && + (details::imatch ('f',*(s_itr_ + 1))) && + (details::is_digit(*(s_itr_ + 2))) && + (details::is_digit(*(s_itr_ + 3)))) + ) + { + t.set_error(token::e_err_sfunc, initial_itr, s_itr_, base_itr_); + token_list_.push_back(t); + + return; + } + + s_itr_ += 4; // $fdd = 4chars + + t.set_symbol(initial_itr, s_itr_, base_itr_); + token_list_.push_back(t); + + return; + } + + #ifndef exprtk_disable_string_capabilities + inline void scan_string() + { + details::char_cptr initial_itr = s_itr_ + 1; + token_t t; + + if (std::distance(s_itr_,s_end_) < 2) + { + t.set_error(token::e_err_string, s_itr_, s_end_, base_itr_); + token_list_.push_back(t); + return; + } + + ++s_itr_; + + bool escaped_found = false; + bool escaped = false; + + while (!is_end(s_itr_)) + { + if (!escaped && ('\\' == *s_itr_)) + { + escaped_found = true; + escaped = true; + ++s_itr_; + + continue; + } + else if (!escaped) + { + if ('\'' == *s_itr_) + break; + } + else if (escaped) + { + if (!is_end(s_itr_) && ('0' == *(s_itr_))) + { + /* + Note: The following 'awkward' conditional is + due to various broken msvc compilers. + */ + #if defined(_MSC_VER) && (_MSC_VER == 1600) + const bool within_range = !is_end(s_itr_ + 2) && + !is_end(s_itr_ + 3) ; + #else + const bool within_range = !is_end(s_itr_ + 1) && + !is_end(s_itr_ + 2) && + !is_end(s_itr_ + 3) ; + #endif + + const bool x_seperator = ('x' == *(s_itr_ + 1)) || + ('X' == *(s_itr_ + 1)) ; + + const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) && + details::is_hex_digit(*(s_itr_ + 3)) ; + + if (!within_range || !x_seperator || !both_digits) + { + t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); + token_list_.push_back(t); + + return; + } + else + s_itr_ += 3; + } + + escaped = false; + } + + ++s_itr_; + } + + if (is_end(s_itr_)) + { + t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); + token_list_.push_back(t); + + return; + } + + if (!escaped_found) + t.set_string(initial_itr, s_itr_, base_itr_); + else + { + std::string parsed_string(initial_itr,s_itr_); + + details::cleanup_escapes(parsed_string); + + t.set_string( + parsed_string, + static_cast(std::distance(base_itr_,initial_itr))); + } + + token_list_.push_back(t); + ++s_itr_; + + return; + } + #endif + + private: + + token_list_t token_list_; + token_list_itr_t token_itr_; + token_list_itr_t store_token_itr_; + token_t eof_token_; + details::char_cptr base_itr_; + details::char_cptr s_itr_; + details::char_cptr s_end_; + + friend class token_scanner; + friend class token_modifier; + friend class token_inserter; + friend class token_joiner; + }; + + class helper_interface + { + public: + + virtual void init() { } + virtual void reset() { } + virtual bool result() { return true; } + virtual std::size_t process(generator&) { return 0; } + virtual ~helper_interface() { } + }; + + class token_scanner : public helper_interface + { + public: + + virtual ~token_scanner() + {} + + explicit token_scanner(const std::size_t& stride) + : stride_(stride) + { + if (stride > 4) + { + throw std::invalid_argument("token_scanner() - Invalid stride value"); + } + } + + inline std::size_t process(generator& g) + { + if (g.token_list_.size() >= stride_) + { + for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) + { + token t; + + switch (stride_) + { + case 1 : + { + const token& t0 = g.token_list_[i]; + + if (!operator()(t0)) + { + return i; + } + } + break; + + case 2 : + { + const token& t0 = g.token_list_[i ]; + const token& t1 = g.token_list_[i + 1]; + + if (!operator()(t0, t1)) + { + return i; + } + } + break; + + case 3 : + { + const token& t0 = g.token_list_[i ]; + const token& t1 = g.token_list_[i + 1]; + const token& t2 = g.token_list_[i + 2]; + + if (!operator()(t0, t1, t2)) + { + return i; + } + } + break; + + case 4 : + { + const token& t0 = g.token_list_[i ]; + const token& t1 = g.token_list_[i + 1]; + const token& t2 = g.token_list_[i + 2]; + const token& t3 = g.token_list_[i + 3]; + + if (!operator()(t0, t1, t2, t3)) + { + return i; + } + } + break; + } + } + } + + return (g.token_list_.size() - stride_ + 1); + } + + virtual bool operator() (const token&) + { + return false; + } + + virtual bool operator() (const token&, const token&) + { + return false; + } + + virtual bool operator() (const token&, const token&, const token&) + { + return false; + } + + virtual bool operator() (const token&, const token&, const token&, const token&) + { + return false; + } + + private: + + const std::size_t stride_; + }; + + class token_modifier : public helper_interface + { + public: + + inline std::size_t process(generator& g) + { + std::size_t changes = 0; + + for (std::size_t i = 0; i < g.token_list_.size(); ++i) + { + if (modify(g.token_list_[i])) changes++; + } + + return changes; + } + + virtual bool modify(token& t) = 0; + }; + + class token_inserter : public helper_interface + { + public: + + explicit token_inserter(const std::size_t& stride) + : stride_(stride) + { + if (stride > 5) + { + throw std::invalid_argument("token_inserter() - Invalid stride value"); + } + } + + inline std::size_t process(generator& g) + { + if (g.token_list_.empty()) + return 0; + else if (g.token_list_.size() < stride_) + return 0; + + std::size_t changes = 0; + + for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) + { + int insert_index = -1; + token t; + + switch (stride_) + { + case 1 : insert_index = insert(g.token_list_[i],t); + break; + + case 2 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], t); + break; + + case 3 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], t); + break; + + case 4 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], g.token_list_[i + 3], t); + break; + + case 5 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], g.token_list_[i + 3], g.token_list_[i + 4], t); + break; + } + + typedef std::iterator_traits::difference_type diff_t; + + if ((insert_index >= 0) && (insert_index <= (static_cast(stride_) + 1))) + { + g.token_list_.insert( + g.token_list_.begin() + static_cast(i + static_cast(insert_index)), t); + + changes++; + } + } + + return changes; + } + + #define token_inserter_empty_body \ + { \ + return -1; \ + } \ + + inline virtual int insert(const token&, token&) + token_inserter_empty_body + + inline virtual int insert(const token&, const token&, token&) + token_inserter_empty_body + + inline virtual int insert(const token&, const token&, const token&, token&) + token_inserter_empty_body + + inline virtual int insert(const token&, const token&, const token&, const token&, token&) + token_inserter_empty_body + + inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&) + token_inserter_empty_body + + #undef token_inserter_empty_body + + private: + + const std::size_t stride_; + }; + + class token_joiner : public helper_interface + { + public: + + explicit token_joiner(const std::size_t& stride) + : stride_(stride) + {} + + inline std::size_t process(generator& g) + { + if (g.token_list_.empty()) + return 0; + + switch (stride_) + { + case 2 : return process_stride_2(g); + case 3 : return process_stride_3(g); + default : return 0; + } + } + + virtual bool join(const token&, const token&, token&) { return false; } + virtual bool join(const token&, const token&, const token&, token&) { return false; } + + private: + + inline std::size_t process_stride_2(generator& g) + { + typedef std::iterator_traits::difference_type diff_t; + + if (g.token_list_.size() < 2) + return 0; + + std::size_t changes = 0; + + for (int i = 0; i < static_cast(g.token_list_.size() - 1); ++i) + { + token t; + + while (join(g[i], g[i + 1], t)) + { + g.token_list_[i] = t; + + g.token_list_.erase(g.token_list_.begin() + static_cast(i + 1)); + + ++changes; + + if (static_cast(i + 1) >= g.token_list_.size()) + break; + } + } + + return changes; + } + + inline std::size_t process_stride_3(generator& g) + { + typedef std::iterator_traits::difference_type diff_t; + + if (g.token_list_.size() < 3) + return 0; + + std::size_t changes = 0; + + for (int i = 0; i < static_cast(g.token_list_.size() - 2); ++i) + { + token t; + + while (join(g[i], g[i + 1], g[i + 2], t)) + { + g.token_list_[i] = t; + + g.token_list_.erase(g.token_list_.begin() + static_cast(i + 1), + g.token_list_.begin() + static_cast(i + 3)); + ++changes; + + if (static_cast(i + 2) >= g.token_list_.size()) + break; + } + } + + return changes; + } + + const std::size_t stride_; + }; + + namespace helper + { + + inline void dump(lexer::generator& generator) + { + for (std::size_t i = 0; i < generator.size(); ++i) + { + lexer::token t = generator[i]; + printf("Token[%02d] @ %03d %6s --> '%s'\n", + static_cast(i), + static_cast(t.position), + t.to_str(t.type).c_str(), + t.value.c_str()); + } + } + + class commutative_inserter : public lexer::token_inserter + { + public: + + using lexer::token_inserter::insert; + + commutative_inserter() + : lexer::token_inserter(2) + {} + + inline void ignore_symbol(const std::string& symbol) + { + ignore_set_.insert(symbol); + } + + inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token) + { + bool match = false; + new_token.type = lexer::token::e_mul; + new_token.value = "*"; + new_token.position = t1.position; + + if (t0.type == lexer::token::e_symbol) + { + if (ignore_set_.end() != ignore_set_.find(t0.value)) + { + return -1; + } + else if (!t0.value.empty() && ('$' == t0.value[0])) + { + return -1; + } + } + + if (t1.type == lexer::token::e_symbol) + { + if (ignore_set_.end() != ignore_set_.find(t1.value)) + { + return -1; + } + } + if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_symbol )) match = true; + else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lbracket )) match = true; + else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lcrlbracket)) match = true; + else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lsqrbracket)) match = true; + else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_number )) match = true; + else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_number )) match = true; + else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number )) match = true; + else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number )) match = true; + else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_symbol )) match = true; + else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol )) match = true; + else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol )) match = true; + else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_symbol )) match = true; + + return (match) ? 1 : -1; + } + + private: + + std::set ignore_set_; + }; + + class operator_joiner : public token_joiner + { + public: + + explicit operator_joiner(const std::size_t& stride) + : token_joiner(stride) + {} + + inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t) + { + // ': =' --> ':=' + if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq)) + { + t.type = lexer::token::e_assign; + t.value = ":="; + t.position = t0.position; + + return true; + } + // '+ =' --> '+=' + else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq)) + { + t.type = lexer::token::e_addass; + t.value = "+="; + t.position = t0.position; + + return true; + } + // '- =' --> '-=' + else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq)) + { + t.type = lexer::token::e_subass; + t.value = "-="; + t.position = t0.position; + + return true; + } + // '* =' --> '*=' + else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq)) + { + t.type = lexer::token::e_mulass; + t.value = "*="; + t.position = t0.position; + + return true; + } + // '/ =' --> '/=' + else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq)) + { + t.type = lexer::token::e_divass; + t.value = "/="; + t.position = t0.position; + + return true; + } + // '% =' --> '%=' + else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq)) + { + t.type = lexer::token::e_modass; + t.value = "%="; + t.position = t0.position; + + return true; + } + // '> =' --> '>=' + else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq)) + { + t.type = lexer::token::e_gte; + t.value = ">="; + t.position = t0.position; + + return true; + } + // '< =' --> '<=' + else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq)) + { + t.type = lexer::token::e_lte; + t.value = "<="; + t.position = t0.position; + + return true; + } + // '= =' --> '==' + else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq)) + { + t.type = lexer::token::e_eq; + t.value = "=="; + t.position = t0.position; + + return true; + } + // '! =' --> '!=' + else if ((static_cast(t0.type) == '!') && (t1.type == lexer::token::e_eq)) + { + t.type = lexer::token::e_ne; + t.value = "!="; + t.position = t0.position; + + return true; + } + // '< >' --> '<>' + else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt)) + { + t.type = lexer::token::e_ne; + t.value = "<>"; + t.position = t0.position; + + return true; + } + // '<= >' --> '<=>' + else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt)) + { + t.type = lexer::token::e_swap; + t.value = "<=>"; + t.position = t0.position; + + return true; + } + // '+ -' --> '-' + else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_sub)) + { + t.type = lexer::token::e_sub; + t.value = "-"; + t.position = t0.position; + + return true; + } + // '- +' --> '-' + else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_add)) + { + t.type = lexer::token::e_sub; + t.value = "-"; + t.position = t0.position; + + return true; + } + // '- -' --> '+' + else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_sub)) + { + /* + Note: May need to reconsider this when wanting to implement + pre/postfix decrement operator + */ + t.type = lexer::token::e_add; + t.value = "+"; + t.position = t0.position; + + return true; + } + else + return false; + } + + inline bool join(const lexer::token& t0, const lexer::token& t1, const lexer::token& t2, lexer::token& t) + { + // '[ * ]' --> '[*]' + if ( + (t0.type == lexer::token::e_lsqrbracket) && + (t1.type == lexer::token::e_mul ) && + (t2.type == lexer::token::e_rsqrbracket) + ) + { + t.type = lexer::token::e_symbol; + t.value = "[*]"; + t.position = t0.position; + + return true; + } + else + return false; + } + }; + + class bracket_checker : public lexer::token_scanner + { + public: + + using lexer::token_scanner::operator(); + + bracket_checker() + : token_scanner(1), + state_(true) + {} + + bool result() + { + if (!stack_.empty()) + { + lexer::token t; + t.value = stack_.top().first; + t.position = stack_.top().second; + error_token_ = t; + state_ = false; + + return false; + } + else + return state_; + } + + lexer::token error_token() + { + return error_token_; + } + + void reset() + { + // Why? because msvc doesn't support swap properly. + stack_ = std::stack >(); + state_ = true; + error_token_.clear(); + } + + bool operator() (const lexer::token& t) + { + if ( + !t.value.empty() && + (lexer::token::e_string != t.type) && + (lexer::token::e_symbol != t.type) && + exprtk::details::is_bracket(t.value[0]) + ) + { + details::char_t c = t.value[0]; + + if (t.type == lexer::token::e_lbracket ) stack_.push(std::make_pair(')',t.position)); + else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position)); + else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position)); + else if (exprtk::details::is_right_bracket(c)) + { + if (stack_.empty()) + { + state_ = false; + error_token_ = t; + + return false; + } + else if (c != stack_.top().first) + { + state_ = false; + error_token_ = t; + + return false; + } + else + stack_.pop(); + } + } + + return true; + } + + private: + + bool state_; + std::stack > stack_; + lexer::token error_token_; + }; + + class numeric_checker : public lexer::token_scanner + { + public: + + using lexer::token_scanner::operator(); + + numeric_checker() + : token_scanner (1), + current_index_(0) + {} + + bool result() + { + return error_list_.empty(); + } + + void reset() + { + error_list_.clear(); + current_index_ = 0; + } + + bool operator() (const lexer::token& t) + { + if (token::e_number == t.type) + { + double v; + + if (!exprtk::details::string_to_real(t.value,v)) + { + error_list_.push_back(current_index_); + } + } + + ++current_index_; + + return true; + } + + std::size_t error_count() const + { + return error_list_.size(); + } + + std::size_t error_index(const std::size_t& i) + { + if (i < error_list_.size()) + return error_list_[i]; + else + return std::numeric_limits::max(); + } + + void clear_errors() + { + error_list_.clear(); + } + + private: + + std::size_t current_index_; + std::vector error_list_; + }; + + class symbol_replacer : public lexer::token_modifier + { + private: + + typedef std::map,details::ilesscompare> replace_map_t; + + public: + + bool remove(const std::string& target_symbol) + { + const replace_map_t::iterator itr = replace_map_.find(target_symbol); + + if (replace_map_.end() == itr) + return false; + + replace_map_.erase(itr); + + return true; + } + + bool add_replace(const std::string& target_symbol, + const std::string& replace_symbol, + const lexer::token::token_type token_type = lexer::token::e_symbol) + { + const replace_map_t::iterator itr = replace_map_.find(target_symbol); + + if (replace_map_.end() != itr) + { + return false; + } + + replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type); + + return true; + } + + void clear() + { + replace_map_.clear(); + } + + private: + + bool modify(lexer::token& t) + { + if (lexer::token::e_symbol == t.type) + { + if (replace_map_.empty()) + return false; + + const replace_map_t::iterator itr = replace_map_.find(t.value); + + if (replace_map_.end() != itr) + { + t.value = itr->second.first; + t.type = itr->second.second; + + return true; + } + } + + return false; + } + + replace_map_t replace_map_; + }; + + class sequence_validator : public lexer::token_scanner + { + private: + + typedef std::pair token_pair_t; + typedef std::set set_t; + + public: + + using lexer::token_scanner::operator(); + + sequence_validator() + : lexer::token_scanner(2) + { + add_invalid(lexer::token::e_number, lexer::token::e_number); + add_invalid(lexer::token::e_string, lexer::token::e_string); + add_invalid(lexer::token::e_number, lexer::token::e_string); + add_invalid(lexer::token::e_string, lexer::token::e_number); + + add_invalid_set1(lexer::token::e_assign ); + add_invalid_set1(lexer::token::e_shr ); + add_invalid_set1(lexer::token::e_shl ); + add_invalid_set1(lexer::token::e_lte ); + add_invalid_set1(lexer::token::e_ne ); + add_invalid_set1(lexer::token::e_gte ); + add_invalid_set1(lexer::token::e_lt ); + add_invalid_set1(lexer::token::e_gt ); + add_invalid_set1(lexer::token::e_eq ); + add_invalid_set1(lexer::token::e_comma ); + add_invalid_set1(lexer::token::e_add ); + add_invalid_set1(lexer::token::e_sub ); + add_invalid_set1(lexer::token::e_div ); + add_invalid_set1(lexer::token::e_mul ); + add_invalid_set1(lexer::token::e_mod ); + add_invalid_set1(lexer::token::e_pow ); + add_invalid_set1(lexer::token::e_colon ); + add_invalid_set1(lexer::token::e_ternary); + } + + bool result() + { + return error_list_.empty(); + } + + bool operator() (const lexer::token& t0, const lexer::token& t1) + { + const set_t::value_type p = std::make_pair(t0.type,t1.type); + + if (invalid_bracket_check(t0.type,t1.type)) + { + error_list_.push_back(std::make_pair(t0,t1)); + } + else if (invalid_comb_.find(p) != invalid_comb_.end()) + { + error_list_.push_back(std::make_pair(t0,t1)); + } + + return true; + } + + std::size_t error_count() const + { + return error_list_.size(); + } + + std::pair error(const std::size_t index) + { + if (index < error_list_.size()) + { + return error_list_[index]; + } + else + { + static const lexer::token error_token; + return std::make_pair(error_token,error_token); + } + } + + void clear_errors() + { + error_list_.clear(); + } + + private: + + void add_invalid(lexer::token::token_type base, lexer::token::token_type t) + { + invalid_comb_.insert(std::make_pair(base,t)); + } + + void add_invalid_set1(lexer::token::token_type t) + { + add_invalid(t, lexer::token::e_assign); + add_invalid(t, lexer::token::e_shr ); + add_invalid(t, lexer::token::e_shl ); + add_invalid(t, lexer::token::e_lte ); + add_invalid(t, lexer::token::e_ne ); + add_invalid(t, lexer::token::e_gte ); + add_invalid(t, lexer::token::e_lt ); + add_invalid(t, lexer::token::e_gt ); + add_invalid(t, lexer::token::e_eq ); + add_invalid(t, lexer::token::e_comma ); + add_invalid(t, lexer::token::e_div ); + add_invalid(t, lexer::token::e_mul ); + add_invalid(t, lexer::token::e_mod ); + add_invalid(t, lexer::token::e_pow ); + add_invalid(t, lexer::token::e_colon ); + } + + bool invalid_bracket_check(lexer::token::token_type base, lexer::token::token_type t) + { + if (details::is_right_bracket(static_cast(base))) + { + switch (t) + { + case lexer::token::e_assign : return (']' != base); + case lexer::token::e_string : return (')' != base); + default : return false; + } + } + else if (details::is_left_bracket(static_cast(base))) + { + if (details::is_right_bracket(static_cast(t))) + return false; + else if (details::is_left_bracket(static_cast(t))) + return false; + else + { + switch (t) + { + case lexer::token::e_number : return false; + case lexer::token::e_symbol : return false; + case lexer::token::e_string : return false; + case lexer::token::e_add : return false; + case lexer::token::e_sub : return false; + case lexer::token::e_colon : return false; + case lexer::token::e_ternary : return false; + default : return true ; + } + } + } + else if (details::is_right_bracket(static_cast(t))) + { + switch (base) + { + case lexer::token::e_number : return false; + case lexer::token::e_symbol : return false; + case lexer::token::e_string : return false; + case lexer::token::e_eof : return false; + case lexer::token::e_colon : return false; + case lexer::token::e_ternary : return false; + default : return true ; + } + } + else if (details::is_left_bracket(static_cast(t))) + { + switch (base) + { + case lexer::token::e_rbracket : return true; + case lexer::token::e_rsqrbracket : return true; + case lexer::token::e_rcrlbracket : return true; + default : return false; + } + } + + return false; + } + + set_t invalid_comb_; + std::vector > error_list_; + }; + + class sequence_validator_3tokens : public lexer::token_scanner + { + private: + + typedef lexer::token::token_type token_t; + typedef std::pair > token_triplet_t; + typedef std::set set_t; + + public: + + using lexer::token_scanner::operator(); + + sequence_validator_3tokens() + : lexer::token_scanner(3) + { + add_invalid(lexer::token::e_number, lexer::token::e_number, lexer::token::e_number); + add_invalid(lexer::token::e_string, lexer::token::e_string, lexer::token::e_string); + add_invalid(lexer::token::e_comma , lexer::token::e_comma , lexer::token::e_comma ); + + add_invalid(lexer::token::e_add , lexer::token::e_add , lexer::token::e_add ); + add_invalid(lexer::token::e_sub , lexer::token::e_sub , lexer::token::e_sub ); + add_invalid(lexer::token::e_div , lexer::token::e_div , lexer::token::e_div ); + add_invalid(lexer::token::e_mul , lexer::token::e_mul , lexer::token::e_mul ); + add_invalid(lexer::token::e_mod , lexer::token::e_mod , lexer::token::e_mod ); + add_invalid(lexer::token::e_pow , lexer::token::e_pow , lexer::token::e_pow ); + + add_invalid(lexer::token::e_add , lexer::token::e_sub , lexer::token::e_add ); + add_invalid(lexer::token::e_sub , lexer::token::e_add , lexer::token::e_sub ); + add_invalid(lexer::token::e_div , lexer::token::e_mul , lexer::token::e_div ); + add_invalid(lexer::token::e_mul , lexer::token::e_div , lexer::token::e_mul ); + add_invalid(lexer::token::e_mod , lexer::token::e_pow , lexer::token::e_mod ); + add_invalid(lexer::token::e_pow , lexer::token::e_mod , lexer::token::e_pow ); + } + + bool result() + { + return error_list_.empty(); + } + + bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2) + { + const set_t::value_type p = std::make_pair(t0.type,std::make_pair(t1.type,t2.type)); + + if (invalid_comb_.find(p) != invalid_comb_.end()) + { + error_list_.push_back(std::make_pair(t0,t1)); + } + + return true; + } + + std::size_t error_count() const + { + return error_list_.size(); + } + + std::pair error(const std::size_t index) + { + if (index < error_list_.size()) + { + return error_list_[index]; + } + else + { + static const lexer::token error_token; + return std::make_pair(error_token,error_token); + } + } + + void clear_errors() + { + error_list_.clear(); + } + + private: + + void add_invalid(token_t t0, token_t t1, token_t t2) + { + invalid_comb_.insert(std::make_pair(t0,std::make_pair(t1,t2))); + } + + set_t invalid_comb_; + std::vector > error_list_; + }; + + struct helper_assembly + { + inline bool register_scanner(lexer::token_scanner* scanner) + { + if (token_scanner_list.end() != std::find(token_scanner_list.begin(), + token_scanner_list.end (), + scanner)) + { + return false; + } + + token_scanner_list.push_back(scanner); + + return true; + } + + inline bool register_modifier(lexer::token_modifier* modifier) + { + if (token_modifier_list.end() != std::find(token_modifier_list.begin(), + token_modifier_list.end (), + modifier)) + { + return false; + } + + token_modifier_list.push_back(modifier); + + return true; + } + + inline bool register_joiner(lexer::token_joiner* joiner) + { + if (token_joiner_list.end() != std::find(token_joiner_list.begin(), + token_joiner_list.end (), + joiner)) + { + return false; + } + + token_joiner_list.push_back(joiner); + + return true; + } + + inline bool register_inserter(lexer::token_inserter* inserter) + { + if (token_inserter_list.end() != std::find(token_inserter_list.begin(), + token_inserter_list.end (), + inserter)) + { + return false; + } + + token_inserter_list.push_back(inserter); + + return true; + } + + inline bool run_modifiers(lexer::generator& g) + { + error_token_modifier = reinterpret_cast(0); + + for (std::size_t i = 0; i < token_modifier_list.size(); ++i) + { + lexer::token_modifier& modifier = (*token_modifier_list[i]); + + modifier.reset(); + modifier.process(g); + + if (!modifier.result()) + { + error_token_modifier = token_modifier_list[i]; + + return false; + } + } + + return true; + } + + inline bool run_joiners(lexer::generator& g) + { + error_token_joiner = reinterpret_cast(0); + + for (std::size_t i = 0; i < token_joiner_list.size(); ++i) + { + lexer::token_joiner& joiner = (*token_joiner_list[i]); + + joiner.reset(); + joiner.process(g); + + if (!joiner.result()) + { + error_token_joiner = token_joiner_list[i]; + + return false; + } + } + + return true; + } + + inline bool run_inserters(lexer::generator& g) + { + error_token_inserter = reinterpret_cast(0); + + for (std::size_t i = 0; i < token_inserter_list.size(); ++i) + { + lexer::token_inserter& inserter = (*token_inserter_list[i]); + + inserter.reset(); + inserter.process(g); + + if (!inserter.result()) + { + error_token_inserter = token_inserter_list[i]; + + return false; + } + } + + return true; + } + + inline bool run_scanners(lexer::generator& g) + { + error_token_scanner = reinterpret_cast(0); + + for (std::size_t i = 0; i < token_scanner_list.size(); ++i) + { + lexer::token_scanner& scanner = (*token_scanner_list[i]); + + scanner.reset(); + scanner.process(g); + + if (!scanner.result()) + { + error_token_scanner = token_scanner_list[i]; + + return false; + } + } + + return true; + } + + std::vector token_scanner_list; + std::vector token_modifier_list; + std::vector token_joiner_list; + std::vector token_inserter_list; + + lexer::token_scanner* error_token_scanner; + lexer::token_modifier* error_token_modifier; + lexer::token_joiner* error_token_joiner; + lexer::token_inserter* error_token_inserter; + }; + } + + class parser_helper + { + public: + + typedef token token_t; + typedef generator generator_t; + + inline bool init(const std::string& str) + { + if (!lexer_.process(str)) + { + return false; + } + + lexer_.begin(); + + next_token(); + + return true; + } + + inline generator_t& lexer() + { + return lexer_; + } + + inline const generator_t& lexer() const + { + return lexer_; + } + + inline void store_token() + { + lexer_.store(); + store_current_token_ = current_token_; + } + + inline void restore_token() + { + lexer_.restore(); + current_token_ = store_current_token_; + } + + inline void next_token() + { + current_token_ = lexer_.next_token(); + } + + inline const token_t& current_token() const + { + return current_token_; + } + + enum token_advance_mode + { + e_hold = 0, + e_advance = 1 + }; + + inline void advance_token(const token_advance_mode mode) + { + if (e_advance == mode) + { + next_token(); + } + } + + inline bool token_is(const token_t::token_type& ttype, const token_advance_mode mode = e_advance) + { + if (current_token().type != ttype) + { + return false; + } + + advance_token(mode); + + return true; + } + + inline bool token_is(const token_t::token_type& ttype, + const std::string& value, + const token_advance_mode mode = e_advance) + { + if ( + (current_token().type != ttype) || + !exprtk::details::imatch(value,current_token().value) + ) + { + return false; + } + + advance_token(mode); + + return true; + } + + inline bool peek_token_is(const token_t::token_type& ttype) + { + return (lexer_.peek_next_token().type == ttype); + } + + inline bool peek_token_is(const std::string& s) + { + return (exprtk::details::imatch(lexer_.peek_next_token().value,s)); + } + + private: + + generator_t lexer_; + token_t current_token_; + token_t store_current_token_; + }; + } + + template + class vector_view + { + public: + + typedef T* data_ptr_t; + + vector_view(data_ptr_t data, const std::size_t& size) + : size_(size), + data_(data), + data_ref_(0) + {} + + vector_view(const vector_view& vv) + : size_(vv.size_), + data_(vv.data_), + data_ref_(0) + {} + + inline void rebase(data_ptr_t data) + { + data_ = data; + + if (!data_ref_.empty()) + { + for (std::size_t i = 0; i < data_ref_.size(); ++i) + { + (*data_ref_[i]) = data; + } + } + } + + inline data_ptr_t data() const + { + return data_; + } + + inline std::size_t size() const + { + return size_; + } + + inline const T& operator[](const std::size_t index) const + { + return data_[index]; + } + + inline T& operator[](const std::size_t index) + { + return data_[index]; + } + + void set_ref(data_ptr_t* data_ref) + { + data_ref_.push_back(data_ref); + } + + private: + + const std::size_t size_; + data_ptr_t data_; + std::vector data_ref_; + }; + + template + inline vector_view make_vector_view(T* data, + const std::size_t size, const std::size_t offset = 0) + { + return vector_view(data + offset,size); + } + + template + inline vector_view make_vector_view(std::vector& v, + const std::size_t size, const std::size_t offset = 0) + { + return vector_view(v.data() + offset,size); + } + + template class results_context; + + template + struct type_store + { + enum store_type + { + e_unknown, + e_scalar , + e_vector , + e_string + }; + + type_store() + : data(0), + size(0), + type(e_unknown) + {} + + union + { + void* data; + T* vec_data; + }; + + std::size_t size; + store_type type; + + class parameter_list + { + public: + + parameter_list(std::vector& pl) + : parameter_list_(pl) + {} + + inline bool empty() const + { + return parameter_list_.empty(); + } + + inline std::size_t size() const + { + return parameter_list_.size(); + } + + inline type_store& operator[](const std::size_t& index) + { + return parameter_list_[index]; + } + + inline const type_store& operator[](const std::size_t& index) const + { + return parameter_list_[index]; + } + + inline type_store& front() + { + return parameter_list_[0]; + } + + inline const type_store& front() const + { + return parameter_list_[0]; + } + + inline type_store& back() + { + return parameter_list_.back(); + } + + inline const type_store& back() const + { + return parameter_list_.back(); + } + + private: + + std::vector& parameter_list_; + + friend class results_context; + }; + + template + struct type_view + { + typedef type_store type_store_t; + typedef ViewType value_t; + + type_view(type_store_t& ts) + : ts_(ts), + data_(reinterpret_cast(ts_.data)) + {} + + type_view(const type_store_t& ts) + : ts_(const_cast(ts)), + data_(reinterpret_cast(ts_.data)) + {} + + inline std::size_t size() const + { + return ts_.size; + } + + inline value_t& operator[](const std::size_t& i) + { + return data_[i]; + } + + inline const value_t& operator[](const std::size_t& i) const + { + return data_[i]; + } + + inline const value_t* begin() const { return data_; } + inline value_t* begin() { return data_; } + + inline const value_t* end() const + { + return static_cast(data_ + ts_.size); + } + + inline value_t* end() + { + return static_cast(data_ + ts_.size); + } + + type_store_t& ts_; + value_t* data_; + }; + + typedef type_view vector_view; + typedef type_view string_view; + + struct scalar_view + { + typedef type_store type_store_t; + typedef T value_t; + + scalar_view(type_store_t& ts) + : v_(*reinterpret_cast(ts.data)) + {} + + scalar_view(const type_store_t& ts) + : v_(*reinterpret_cast(const_cast(ts).data)) + {} + + inline value_t& operator() () + { + return v_; + } + + inline const value_t& operator() () const + { + return v_; + } + + template + inline bool to_int(IntType& i) const + { + if (!exprtk::details::numeric::is_integer(v_)) + return false; + + i = static_cast(v_); + + return true; + } + + template + inline bool to_uint(UIntType& u) const + { + if (v_ < T(0)) + return false; + else if (!exprtk::details::numeric::is_integer(v_)) + return false; + + u = static_cast(v_); + + return true; + } + + T& v_; + }; + }; + + template + inline std::string to_str(const StringView& view) + { + return std::string(view.begin(),view.size()); + } + + #ifndef exprtk_disable_return_statement + namespace details + { + template class return_node; + template class return_envelope_node; + } + #endif + + template + class results_context + { + public: + + typedef type_store type_store_t; + + results_context() + : results_available_(false) + {} + + inline std::size_t count() const + { + if (results_available_) + return parameter_list_.size(); + else + return 0; + } + + inline type_store_t& operator[](const std::size_t& index) + { + return parameter_list_[index]; + } + + inline const type_store_t& operator[](const std::size_t& index) const + { + return parameter_list_[index]; + } + + private: + + inline void clear() + { + results_available_ = false; + } + + typedef std::vector ts_list_t; + typedef typename type_store_t::parameter_list parameter_list_t; + + inline void assign(const parameter_list_t& pl) + { + parameter_list_ = pl.parameter_list_; + results_available_ = true; + } + + bool results_available_; + ts_list_t parameter_list_; + + #ifndef exprtk_disable_return_statement + friend class details::return_node; + friend class details::return_envelope_node; + #endif + }; + + namespace details + { + enum operator_type + { + e_default , e_null , e_add , e_sub , + e_mul , e_div , e_mod , e_pow , + e_atan2 , e_min , e_max , e_avg , + e_sum , e_prod , e_lt , e_lte , + e_eq , e_equal , e_ne , e_nequal , + e_gte , e_gt , e_and , e_nand , + e_or , e_nor , e_xor , e_xnor , + e_mand , e_mor , e_scand , e_scor , + e_shr , e_shl , e_abs , e_acos , + e_acosh , e_asin , e_asinh , e_atan , + e_atanh , e_ceil , e_cos , e_cosh , + e_exp , e_expm1 , e_floor , e_log , + e_log10 , e_log2 , e_log1p , e_logn , + e_neg , e_pos , e_round , e_roundn , + e_root , e_sqrt , e_sin , e_sinc , + e_sinh , e_sec , e_csc , e_tan , + e_tanh , e_cot , e_clamp , e_iclamp , + e_inrange , e_sgn , e_r2d , e_d2r , + e_d2g , e_g2d , e_hypot , e_notl , + e_erf , e_erfc , e_ncdf , e_frac , + e_trunc , e_assign , e_addass , e_subass , + e_mulass , e_divass , e_modass , e_in , + e_like , e_ilike , e_multi , e_smulti , + e_swap , + + // Do not add new functions/operators after this point. + e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003, + e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007, + e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011, + e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015, + e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019, + e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023, + e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027, + e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031, + e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035, + e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039, + e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043, + e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047, + e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051, + e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055, + e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059, + e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063, + e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067, + e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071, + e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075, + e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079, + e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083, + e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087, + e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091, + e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095, + e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099, + e_sffinal = 1100, + e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003, + e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007, + e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011, + e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015, + e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019, + e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023, + e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027, + e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031, + e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035, + e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039, + e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043, + e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047, + e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051, + e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055, + e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059, + e_sf4ext60 = 2060, e_sf4ext61 = 2061 + }; + + inline std::string to_str(const operator_type opr) + { + switch (opr) + { + case e_add : return "+"; + case e_sub : return "-"; + case e_mul : return "*"; + case e_div : return "/"; + case e_mod : return "%"; + case e_pow : return "^"; + case e_assign : return ":="; + case e_addass : return "+="; + case e_subass : return "-="; + case e_mulass : return "*="; + case e_divass : return "/="; + case e_modass : return "%="; + case e_lt : return "<"; + case e_lte : return "<="; + case e_eq : return "=="; + case e_equal : return "="; + case e_ne : return "!="; + case e_nequal : return "<>"; + case e_gte : return ">="; + case e_gt : return ">"; + default : return"N/A"; + } + } + + struct base_operation_t + { + base_operation_t(const operator_type t, const unsigned int& np) + : type(t), + num_params(np) + {} + + operator_type type; + unsigned int num_params; + }; + + namespace loop_unroll + { + #ifndef exprtk_disable_superscalar_unroll + const unsigned int global_loop_batch_size = 16; + #else + const unsigned int global_loop_batch_size = 4; + #endif + + struct details + { + details(const std::size_t& vsize, + const unsigned int loop_batch_size = global_loop_batch_size) + : batch_size(loop_batch_size ), + remainder (vsize % batch_size), + upper_bound(static_cast(vsize - (remainder ? loop_batch_size : 0))) + {} + + unsigned int batch_size; + int remainder; + int upper_bound; + }; + } + + #ifdef exprtk_enable_debugging + inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0) + { + if (size) + exprtk_debug(("%s - addr: %p\n",s.c_str(),ptr)); + else + exprtk_debug(("%s - addr: %p size: %d\n", + s.c_str(), + ptr, + static_cast(size))); + } + #else + inline void dump_ptr(const std::string&, const void*) {} + inline void dump_ptr(const std::string&, const void*, const std::size_t) {} + #endif + + template + class vec_data_store + { + public: + + typedef vec_data_store type; + typedef T* data_t; + + private: + + struct control_block + { + control_block() + : ref_count(1), + size (0), + data (0), + destruct (true) + {} + + control_block(const std::size_t& dsize) + : ref_count(1 ), + size (dsize), + data (0 ), + destruct (true ) + { create_data(); } + + control_block(const std::size_t& dsize, data_t dptr, bool dstrct = false) + : ref_count(1 ), + size (dsize ), + data (dptr ), + destruct (dstrct) + {} + + ~control_block() + { + if (data && destruct && (0 == ref_count)) + { + dump_ptr("~control_block() data",data); + delete[] data; + data = reinterpret_cast(0); + } + } + + static inline control_block* create(const std::size_t& dsize, data_t data_ptr = data_t(0), bool dstrct = false) + { + if (dsize) + { + if (0 == data_ptr) + return (new control_block(dsize)); + else + return (new control_block(dsize, data_ptr, dstrct)); + } + else + return (new control_block); + } + + static inline void destroy(control_block*& cntrl_blck) + { + if (cntrl_blck) + { + if ( + (0 != cntrl_blck->ref_count) && + (0 == --cntrl_blck->ref_count) + ) + { + delete cntrl_blck; + } + + cntrl_blck = 0; + } + } + + std::size_t ref_count; + std::size_t size; + data_t data; + bool destruct; + + private: + + control_block(const control_block&); + control_block& operator=(const control_block&); + + inline void create_data() + { + destruct = true; + data = new T[size]; + std::fill_n(data,size,T(0)); + dump_ptr("control_block::create_data() - data",data,size); + } + }; + + public: + + vec_data_store() + : control_block_(control_block::create(0)) + {} + + vec_data_store(const std::size_t& size) + : control_block_(control_block::create(size,(data_t)(0),true)) + {} + + vec_data_store(const std::size_t& size, data_t data, bool dstrct = false) + : control_block_(control_block::create(size, data, dstrct)) + {} + + vec_data_store(const type& vds) + { + control_block_ = vds.control_block_; + control_block_->ref_count++; + } + + ~vec_data_store() + { + control_block::destroy(control_block_); + } + + type& operator=(const type& vds) + { + if (this != &vds) + { + std::size_t final_size = min_size(control_block_, vds.control_block_); + + vds.control_block_->size = final_size; + control_block_->size = final_size; + + if (control_block_->destruct || (0 == control_block_->data)) + { + control_block::destroy(control_block_); + + control_block_ = vds.control_block_; + control_block_->ref_count++; + } + } + + return (*this); + } + + inline data_t data() + { + return control_block_->data; + } + + inline data_t data() const + { + return control_block_->data; + } + + inline std::size_t size() + { + return control_block_->size; + } + + inline std::size_t size() const + { + return control_block_->size; + } + + inline data_t& ref() + { + return control_block_->data; + } + + inline void dump() const + { + #ifdef exprtk_enable_debugging + exprtk_debug(("size: %d\taddress:%p\tdestruct:%c\n", + size(), + data(), + (control_block_->destruct ? 'T' : 'F'))); + + for (std::size_t i = 0; i < size(); ++i) + { + if (5 == i) + exprtk_debug(("\n")); + + exprtk_debug(("%15.10f ",data()[i])); + } + exprtk_debug(("\n")); + #endif + } + + static inline void match_sizes(type& vds0, type& vds1) + { + std::size_t size = min_size(vds0.control_block_,vds1.control_block_); + vds0.control_block_->size = size; + vds1.control_block_->size = size; + } + + private: + + static inline std::size_t min_size(control_block* cb0, control_block* cb1) + { + const std::size_t size0 = cb0->size; + const std::size_t size1 = cb1->size; + + if (size0 && size1) + return std::min(size0,size1); + else + return (size0) ? size0 : size1; + } + + control_block* control_block_; + }; + + namespace numeric + { + namespace details + { + template + inline T process_impl(const operator_type operation, const T arg) + { + switch (operation) + { + case e_abs : return numeric::abs (arg); + case e_acos : return numeric::acos (arg); + case e_acosh : return numeric::acosh(arg); + case e_asin : return numeric::asin (arg); + case e_asinh : return numeric::asinh(arg); + case e_atan : return numeric::atan (arg); + case e_atanh : return numeric::atanh(arg); + case e_ceil : return numeric::ceil (arg); + case e_cos : return numeric::cos (arg); + case e_cosh : return numeric::cosh (arg); + case e_exp : return numeric::exp (arg); + case e_expm1 : return numeric::expm1(arg); + case e_floor : return numeric::floor(arg); + case e_log : return numeric::log (arg); + case e_log10 : return numeric::log10(arg); + case e_log2 : return numeric::log2 (arg); + case e_log1p : return numeric::log1p(arg); + case e_neg : return numeric::neg (arg); + case e_pos : return numeric::pos (arg); + case e_round : return numeric::round(arg); + case e_sin : return numeric::sin (arg); + case e_sinc : return numeric::sinc (arg); + case e_sinh : return numeric::sinh (arg); + case e_sqrt : return numeric::sqrt (arg); + case e_tan : return numeric::tan (arg); + case e_tanh : return numeric::tanh (arg); + case e_cot : return numeric::cot (arg); + case e_sec : return numeric::sec (arg); + case e_csc : return numeric::csc (arg); + case e_r2d : return numeric::r2d (arg); + case e_d2r : return numeric::d2r (arg); + case e_d2g : return numeric::d2g (arg); + case e_g2d : return numeric::g2d (arg); + case e_notl : return numeric::notl (arg); + case e_sgn : return numeric::sgn (arg); + case e_erf : return numeric::erf (arg); + case e_erfc : return numeric::erfc (arg); + case e_ncdf : return numeric::ncdf (arg); + case e_frac : return numeric::frac (arg); + case e_trunc : return numeric::trunc(arg); + + default : exprtk_debug(("numeric::details::process_impl - Invalid unary operation.\n")); + return std::numeric_limits::quiet_NaN(); + } + } + + template + inline T process_impl(const operator_type operation, const T arg0, const T arg1) + { + switch (operation) + { + case e_add : return (arg0 + arg1); + case e_sub : return (arg0 - arg1); + case e_mul : return (arg0 * arg1); + case e_div : return (arg0 / arg1); + case e_mod : return modulus(arg0,arg1); + case e_pow : return pow(arg0,arg1); + case e_atan2 : return atan2(arg0,arg1); + case e_min : return std::min(arg0,arg1); + case e_max : return std::max(arg0,arg1); + case e_logn : return logn(arg0,arg1); + case e_lt : return (arg0 < arg1) ? T(1) : T(0); + case e_lte : return (arg0 <= arg1) ? T(1) : T(0); + case e_eq : return std::equal_to()(arg0,arg1) ? T(1) : T(0); + case e_ne : return std::not_equal_to()(arg0,arg1) ? T(1) : T(0); + case e_gte : return (arg0 >= arg1) ? T(1) : T(0); + case e_gt : return (arg0 > arg1) ? T(1) : T(0); + case e_and : return and_opr (arg0,arg1); + case e_nand : return nand_opr(arg0,arg1); + case e_or : return or_opr (arg0,arg1); + case e_nor : return nor_opr (arg0,arg1); + case e_xor : return xor_opr (arg0,arg1); + case e_xnor : return xnor_opr(arg0,arg1); + case e_root : return root (arg0,arg1); + case e_roundn : return roundn (arg0,arg1); + case e_equal : return equal (arg0,arg1); + case e_nequal : return nequal (arg0,arg1); + case e_hypot : return hypot (arg0,arg1); + case e_shr : return shr (arg0,arg1); + case e_shl : return shl (arg0,arg1); + + default : exprtk_debug(("numeric::details::process_impl - Invalid binary operation.\n")); + return std::numeric_limits::quiet_NaN(); + } + } + + template + inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag) + { + switch (operation) + { + case e_add : return (arg0 + arg1); + case e_sub : return (arg0 - arg1); + case e_mul : return (arg0 * arg1); + case e_div : return (arg0 / arg1); + case e_mod : return arg0 % arg1; + case e_pow : return pow(arg0,arg1); + case e_min : return std::min(arg0,arg1); + case e_max : return std::max(arg0,arg1); + case e_logn : return logn(arg0,arg1); + case e_lt : return (arg0 < arg1) ? T(1) : T(0); + case e_lte : return (arg0 <= arg1) ? T(1) : T(0); + case e_eq : return (arg0 == arg1) ? T(1) : T(0); + case e_ne : return (arg0 != arg1) ? T(1) : T(0); + case e_gte : return (arg0 >= arg1) ? T(1) : T(0); + case e_gt : return (arg0 > arg1) ? T(1) : T(0); + case e_and : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0); + case e_nand : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1); + case e_or : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0); + case e_nor : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1); + case e_xor : return arg0 ^ arg1; + case e_xnor : return !(arg0 ^ arg1); + case e_root : return root(arg0,arg1); + case e_equal : return arg0 == arg1; + case e_nequal : return arg0 != arg1; + case e_hypot : return hypot(arg0,arg1); + case e_shr : return arg0 >> arg1; + case e_shl : return arg0 << arg1; + + default : exprtk_debug(("numeric::details::process_impl - Invalid binary operation.\n")); + return std::numeric_limits::quiet_NaN(); + } + } + } + + template + inline T process(const operator_type operation, const T arg) + { + return exprtk::details::numeric::details::process_impl(operation,arg); + } + + template + inline T process(const operator_type operation, const T arg0, const T arg1) + { + return exprtk::details::numeric::details::process_impl(operation, arg0, arg1); + } + } + + template + class expression_node + { + public: + + enum node_type + { + e_none , e_null , e_constant , e_unary , + e_binary , e_binary_ext , e_trinary , e_quaternary , + e_vararg , e_conditional , e_while , e_repeat , + e_for , e_switch , e_mswitch , e_return , + e_retenv , e_variable , e_stringvar , e_stringconst , + e_stringvarrng , e_cstringvarrng , e_strgenrange , e_strconcat , + e_stringvarsize , e_strswap , e_stringsize , e_stringvararg , + e_function , e_vafunction , e_genfunction , e_strfunction , + e_strcondition , e_strccondition , e_add , e_sub , + e_mul , e_div , e_mod , e_pow , + e_lt , e_lte , e_gt , e_gte , + e_eq , e_ne , e_and , e_nand , + e_or , e_nor , e_xor , e_xnor , + e_in , e_like , e_ilike , e_inranges , + e_ipow , e_ipowinv , e_abs , e_acos , + e_acosh , e_asin , e_asinh , e_atan , + e_atanh , e_ceil , e_cos , e_cosh , + e_exp , e_expm1 , e_floor , e_log , + e_log10 , e_log2 , e_log1p , e_neg , + e_pos , e_round , e_sin , e_sinc , + e_sinh , e_sqrt , e_tan , e_tanh , + e_cot , e_sec , e_csc , e_r2d , + e_d2r , e_d2g , e_g2d , e_notl , + e_sgn , e_erf , e_erfc , e_ncdf , + e_frac , e_trunc , e_uvouv , e_vov , + e_cov , e_voc , e_vob , e_bov , + e_cob , e_boc , e_vovov , e_vovoc , + e_vocov , e_covov , e_covoc , e_vovovov , + e_vovovoc , e_vovocov , e_vocovov , e_covovov , + e_covocov , e_vocovoc , e_covovoc , e_vococov , + e_sf3ext , e_sf4ext , e_nulleq , e_strass , + e_vector , e_vecelem , e_rbvecelem , e_rbveccelem , + e_vecdefass , e_vecvalass , e_vecvecass , e_vecopvalass , + e_vecopvecass , e_vecfunc , e_vecvecswap , e_vecvecineq , + e_vecvalineq , e_valvecineq , e_vecvecarith , e_vecvalarith , + e_valvecarith , e_vecunaryop , e_break , e_continue , + e_swap + }; + + typedef T value_type; + typedef expression_node* expression_ptr; + + virtual ~expression_node() + {} + + inline virtual T value() const + { + return std::numeric_limits::quiet_NaN(); + } + + inline virtual expression_node* branch(const std::size_t& index = 0) const + { + return reinterpret_cast(index * 0); + } + + inline virtual node_type type() const + { + return e_none; + } + }; + + template + inline bool is_generally_string_node(const expression_node* node); + + inline bool is_true(const double v) + { + return std::not_equal_to()(0.0,v); + } + + inline bool is_true(const long double v) + { + return std::not_equal_to()(0.0L,v); + } + + inline bool is_true(const float v) + { + return std::not_equal_to()(0.0f,v); + } + + template + inline bool is_true(const std::complex& v) + { + return std::not_equal_to >()(std::complex(0),v); + } + + template + inline bool is_true(const expression_node* node) + { + return std::not_equal_to()(T(0),node->value()); + } + + template + inline bool is_false(const expression_node* node) + { + return std::equal_to()(T(0),node->value()); + } + + template + inline bool is_unary_node(const expression_node* node) + { + return node && (details::expression_node::e_unary == node->type()); + } + + template + inline bool is_neg_unary_node(const expression_node* node) + { + return node && (details::expression_node::e_neg == node->type()); + } + + template + inline bool is_binary_node(const expression_node* node) + { + return node && (details::expression_node::e_binary == node->type()); + } + + template + inline bool is_variable_node(const expression_node* node) + { + return node && (details::expression_node::e_variable == node->type()); + } + + template + inline bool is_ivariable_node(const expression_node* node) + { + return node && + ( + details::expression_node::e_variable == node->type() || + details::expression_node::e_vecelem == node->type() || + details::expression_node::e_rbvecelem == node->type() || + details::expression_node::e_rbveccelem == node->type() + ); + } + + template + inline bool is_vector_elem_node(const expression_node* node) + { + return node && (details::expression_node::e_vecelem == node->type()); + } + + template + inline bool is_rebasevector_elem_node(const expression_node* node) + { + return node && (details::expression_node::e_rbvecelem == node->type()); + } + + template + inline bool is_rebasevector_celem_node(const expression_node* node) + { + return node && (details::expression_node::e_rbveccelem == node->type()); + } + + template + inline bool is_vector_node(const expression_node* node) + { + return node && (details::expression_node::e_vector == node->type()); + } + + template + inline bool is_ivector_node(const expression_node* node) + { + if (node) + { + switch (node->type()) + { + case details::expression_node::e_vector : + case details::expression_node::e_vecvalass : + case details::expression_node::e_vecvecass : + case details::expression_node::e_vecopvalass : + case details::expression_node::e_vecopvecass : + case details::expression_node::e_vecvecswap : + case details::expression_node::e_vecvecarith : + case details::expression_node::e_vecvalarith : + case details::expression_node::e_valvecarith : + case details::expression_node::e_vecunaryop : return true; + default : return false; + } + } + else + return false; + } + + template + inline bool is_constant_node(const expression_node* node) + { + return node && (details::expression_node::e_constant == node->type()); + } + + template + inline bool is_null_node(const expression_node* node) + { + return node && (details::expression_node::e_null == node->type()); + } + + template + inline bool is_break_node(const expression_node* node) + { + return node && (details::expression_node::e_break == node->type()); + } + + template + inline bool is_continue_node(const expression_node* node) + { + return node && (details::expression_node::e_continue == node->type()); + } + + template + inline bool is_swap_node(const expression_node* node) + { + return node && (details::expression_node::e_swap == node->type()); + } + + template + inline bool is_function(const expression_node* node) + { + return node && (details::expression_node::e_function == node->type()); + } + + template + inline bool is_return_node(const expression_node* node) + { + return node && (details::expression_node::e_return == node->type()); + } + + template class unary_node; + + template + inline bool is_negate_node(const expression_node* node) + { + if (node && is_unary_node(node)) + { + return (details::e_neg == static_cast*>(node)->operation()); + } + else + return false; + } + + template + inline bool branch_deletable(expression_node* node) + { + return !is_variable_node(node) && + !is_string_node (node) ; + } + + template + inline bool all_nodes_valid(expression_node* (&b)[N]) + { + for (std::size_t i = 0; i < N; ++i) + { + if (0 == b[i]) return false; + } + + return true; + } + + template class Sequence> + inline bool all_nodes_valid(const Sequence*,Allocator>& b) + { + for (std::size_t i = 0; i < b.size(); ++i) + { + if (0 == b[i]) return false; + } + + return true; + } + + template + inline bool all_nodes_variables(expression_node* (&b)[N]) + { + for (std::size_t i = 0; i < N; ++i) + { + if (0 == b[i]) + return false; + else if (!is_variable_node(b[i])) + return false; + } + + return true; + } + + template class Sequence> + inline bool all_nodes_variables(Sequence*,Allocator>& b) + { + for (std::size_t i = 0; i < b.size(); ++i) + { + if (0 == b[i]) + return false; + else if (!is_variable_node(b[i])) + return false; + } + + return true; + } + + template + inline void free_all_nodes(NodeAllocator& node_allocator, expression_node* (&b)[N]) + { + for (std::size_t i = 0; i < N; ++i) + { + free_node(node_allocator,b[i]); + } + } + + template class Sequence> + inline void free_all_nodes(NodeAllocator& node_allocator, Sequence*,Allocator>& b) + { + for (std::size_t i = 0; i < b.size(); ++i) + { + free_node(node_allocator,b[i]); + } + + b.clear(); + } + + template + inline void free_node(NodeAllocator& node_allocator, expression_node*& node, const bool force_delete = false) + { + if (0 != node) + { + if ( + (is_variable_node(node) || is_string_node(node)) || + force_delete + ) + return; + + node_allocator.free(node); + node = reinterpret_cast*>(0); + } + } + + template + inline void destroy_node(expression_node*& node) + { + delete node; + node = reinterpret_cast*>(0); + } + + template + class vector_holder + { + private: + + typedef Type value_type; + typedef value_type* value_ptr; + typedef const value_ptr const_value_ptr; + + class vector_holder_base + { + public: + + virtual ~vector_holder_base() {} + + inline value_ptr operator[](const std::size_t& index) const + { + return value_at(index); + } + + inline std::size_t size() const + { + return vector_size(); + } + + inline value_ptr data() const + { + return value_at(0); + } + + virtual inline bool rebaseable() const + { + return false; + } + + virtual void set_ref(value_ptr*) {} + + protected: + + virtual value_ptr value_at(const std::size_t&) const = 0; + virtual std::size_t vector_size() const = 0; + }; + + class array_vector_impl : public vector_holder_base + { + public: + + array_vector_impl(const Type* vec, const std::size_t& vec_size) + : vec_(vec), + size_(vec_size) + {} + + protected: + + value_ptr value_at(const std::size_t& index) const + { + if (index < size_) + return const_cast(vec_ + index); + else + return const_value_ptr(0); + } + + std::size_t vector_size() const + { + return size_; + } + + private: + + array_vector_impl operator=(const array_vector_impl&); + + const Type* vec_; + const std::size_t size_; + }; + + template class Sequence> + class sequence_vector_impl : public vector_holder_base + { + public: + + typedef Sequence sequence_t; + + sequence_vector_impl(sequence_t& seq) + : sequence_(seq) + {} + + protected: + + value_ptr value_at(const std::size_t& index) const + { + return (index < sequence_.size()) ? (&sequence_[index]) : const_value_ptr(0); + } + + std::size_t vector_size() const + { + return sequence_.size(); + } + + private: + + sequence_vector_impl operator=(const sequence_vector_impl&); + + sequence_t& sequence_; + }; + + class vector_view_impl : public vector_holder_base + { + public: + + typedef exprtk::vector_view vector_view_t; + + vector_view_impl(vector_view_t& vec_view) + : vec_view_(vec_view) + {} + + void set_ref(value_ptr* ref) + { + vec_view_.set_ref(ref); + } + + virtual inline bool rebaseable() const + { + return true; + } + + protected: + + value_ptr value_at(const std::size_t& index) const + { + return (index < vec_view_.size()) ? (&vec_view_[index]) : const_value_ptr(0); + } + + std::size_t vector_size() const + { + return vec_view_.size(); + } + + private: + + vector_view_impl operator=(const vector_view_impl&); + + vector_view_t& vec_view_; + }; + + public: + + typedef typename details::vec_data_store vds_t; + + vector_holder(Type* vec, const std::size_t& vec_size) + : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size)) + {} + + vector_holder(const vds_t& vds) + : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size())) + {} + + template + vector_holder(std::vector& vec) + : vector_holder_base_(new(buffer)sequence_vector_impl(vec)) + {} + + vector_holder(exprtk::vector_view& vec) + : vector_holder_base_(new(buffer)vector_view_impl(vec)) + {} + + inline value_ptr operator[](const std::size_t& index) const + { + return (*vector_holder_base_)[index]; + } + + inline std::size_t size() const + { + return vector_holder_base_->size(); + } + + inline value_ptr data() const + { + return vector_holder_base_->data(); + } + + void set_ref(value_ptr* ref) + { + vector_holder_base_->set_ref(ref); + } + + bool rebaseable() const + { + return vector_holder_base_->rebaseable(); + } + + private: + + mutable vector_holder_base* vector_holder_base_; + uchar_t buffer[64]; + }; + + template + class null_node : public expression_node + { + public: + + inline T value() const + { + return std::numeric_limits::quiet_NaN(); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_null; + } + }; + + template + class null_eq_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + null_eq_node(expression_ptr brnch, const bool equality = true) + : branch_(brnch), + branch_deletable_(branch_deletable(branch_)), + equality_(equality) + {} + + ~null_eq_node() + { + if (branch_ && branch_deletable_) + { + destroy_node(branch_); + } + } + + inline T value() const + { + const T v = branch_->value(); + const bool result = details::numeric::is_nan(v); + + if (result) + return (equality_) ? T(1) : T(0); + else + return (equality_) ? T(0) : T(1); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_nulleq; + } + + inline operator_type operation() const + { + return details::e_eq; + } + + inline expression_node* branch(const std::size_t&) const + { + return branch_; + } + + private: + + expression_ptr branch_; + const bool branch_deletable_; + bool equality_; + }; + + template + class literal_node : public expression_node + { + public: + + explicit literal_node(const T& v) + : value_(v) + {} + + inline T value() const + { + return value_; + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_constant; + } + + inline expression_node* branch(const std::size_t&) const + { + return reinterpret_cast*>(0); + } + + private: + + literal_node(literal_node&) {} + literal_node& operator=(literal_node&) { return (*this); } + + const T value_; + }; + + template + struct range_pack; + + template + struct range_data_type; + + template + class range_interface + { + public: + + typedef range_pack range_t; + + virtual ~range_interface() + {} + + virtual range_t& range_ref() = 0; + + virtual const range_t& range_ref() const = 0; + }; + + #ifndef exprtk_disable_string_capabilities + template + class string_base_node + { + public: + + typedef range_data_type range_data_type_t; + + virtual ~string_base_node() + {} + + virtual std::string str () const = 0; + + virtual char_cptr base() const = 0; + + virtual std::size_t size() const = 0; + }; + + template + class string_literal_node : public expression_node , + public string_base_node, + public range_interface + { + public: + + typedef range_pack range_t; + + explicit string_literal_node(const std::string& v) + : value_(v) + { + rp_.n0_c = std::make_pair(true,0); + rp_.n1_c = std::make_pair(true,v.size() - 1); + rp_.cache.first = rp_.n0_c.second; + rp_.cache.second = rp_.n1_c.second; + } + + inline T value() const + { + return std::numeric_limits::quiet_NaN(); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_stringconst; + } + + inline expression_node* branch(const std::size_t&) const + { + return reinterpret_cast*>(0); + } + + std::string str() const + { + return value_; + } + + char_cptr base() const + { + return value_.data(); + } + + std::size_t size() const + { + return value_.size(); + } + + range_t& range_ref() + { + return rp_; + } + + const range_t& range_ref() const + { + return rp_; + } + + private: + + string_literal_node(const string_literal_node&); + string_literal_node& operator=(const string_literal_node&); + + const std::string value_; + range_t rp_; + }; + #endif + + template + class unary_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + unary_node(const operator_type& opr, + expression_ptr brnch) + : operation_(opr), + branch_(brnch), + branch_deletable_(branch_deletable(branch_)) + {} + + ~unary_node() + { + if (branch_ && branch_deletable_) + { + destroy_node(branch_); + } + } + + inline T value() const + { + const T arg = branch_->value(); + + return numeric::process(operation_,arg); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_unary; + } + + inline operator_type operation() const + { + return operation_; + } + + inline expression_node* branch(const std::size_t&) const + { + return branch_; + } + + inline void release() + { + branch_deletable_ = false; + } + + protected: + + operator_type operation_; + expression_ptr branch_; + bool branch_deletable_; + }; + + template + struct construct_branch_pair + { + template + static inline void process(std::pair*,bool> (&)[N], expression_node*) + {} + }; + + template + struct construct_branch_pair + { + template + static inline void process(std::pair*,bool> (&branch)[N], expression_node* b) + { + if (b) + { + branch[D] = std::make_pair(b,branch_deletable(b)); + } + } + }; + + template + inline void init_branches(std::pair*,bool> (&branch)[N], + expression_node* b0, + expression_node* b1 = reinterpret_cast*>(0), + expression_node* b2 = reinterpret_cast*>(0), + expression_node* b3 = reinterpret_cast*>(0), + expression_node* b4 = reinterpret_cast*>(0), + expression_node* b5 = reinterpret_cast*>(0), + expression_node* b6 = reinterpret_cast*>(0), + expression_node* b7 = reinterpret_cast*>(0), + expression_node* b8 = reinterpret_cast*>(0), + expression_node* b9 = reinterpret_cast*>(0)) + { + construct_branch_pair 0)>::process(branch,b0); + construct_branch_pair 1)>::process(branch,b1); + construct_branch_pair 2)>::process(branch,b2); + construct_branch_pair 3)>::process(branch,b3); + construct_branch_pair 4)>::process(branch,b4); + construct_branch_pair 5)>::process(branch,b5); + construct_branch_pair 6)>::process(branch,b6); + construct_branch_pair 7)>::process(branch,b7); + construct_branch_pair 8)>::process(branch,b8); + construct_branch_pair 9)>::process(branch,b9); + } + + struct cleanup_branches + { + template + static inline void execute(std::pair*,bool> (&branch)[N]) + { + for (std::size_t i = 0; i < N; ++i) + { + if (branch[i].first && branch[i].second) + { + destroy_node(branch[i].first); + } + } + } + + template class Sequence> + static inline void execute(Sequence*,bool>,Allocator>& branch) + { + for (std::size_t i = 0; i < branch.size(); ++i) + { + if (branch[i].first && branch[i].second) + { + destroy_node(branch[i].first); + } + } + } + }; + + template + class binary_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + typedef std::pair branch_t; + + binary_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : operation_(opr) + { + init_branches<2>(branch_, branch0, branch1); + } + + ~binary_node() + { + cleanup_branches::execute(branch_); + } + + inline T value() const + { + const T arg0 = branch_[0].first->value(); + const T arg1 = branch_[1].first->value(); + + return numeric::process(operation_,arg0,arg1); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_binary; + } + + inline operator_type operation() + { + return operation_; + } + + inline expression_node* branch(const std::size_t& index = 0) const + { + if (0 == index) + return branch_[0].first; + else if (1 == index) + return branch_[1].first; + else + return reinterpret_cast(0); + } + + protected: + + operator_type operation_; + branch_t branch_[2]; + }; + + template + class binary_ext_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + typedef std::pair branch_t; + + binary_ext_node(expression_ptr branch0, expression_ptr branch1) + { + init_branches<2>(branch_, branch0, branch1); + } + + ~binary_ext_node() + { + cleanup_branches::execute(branch_); + } + + inline T value() const + { + const T arg0 = branch_[0].first->value(); + const T arg1 = branch_[1].first->value(); + + return Operation::process(arg0,arg1); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_binary_ext; + } + + inline operator_type operation() + { + return Operation::operation(); + } + + inline expression_node* branch(const std::size_t& index = 0) const + { + if (0 == index) + return branch_[0].first; + else if (1 == index) + return branch_[1].first; + else + return reinterpret_cast(0); + } + + protected: + + branch_t branch_[2]; + }; + + template + class trinary_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + typedef std::pair branch_t; + + trinary_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1, + expression_ptr branch2) + : operation_(opr) + { + init_branches<3>(branch_, branch0, branch1, branch2); + } + + ~trinary_node() + { + cleanup_branches::execute(branch_); + } + + inline T value() const + { + const T arg0 = branch_[0].first->value(); + const T arg1 = branch_[1].first->value(); + const T arg2 = branch_[2].first->value(); + + switch (operation_) + { + case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1)); + + case e_clamp : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1); + + case e_iclamp : if ((arg1 <= arg0) || (arg1 >= arg2)) + return arg1; + else + return ((T(2) * arg1 <= (arg2 + arg0)) ? arg0 : arg2); + + default : exprtk_debug(("trinary_node::value() - Error: Invalid operation\n")); + return std::numeric_limits::quiet_NaN(); + } + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_trinary; + } + + protected: + + operator_type operation_; + branch_t branch_[3]; + }; + + template + class quaternary_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + typedef std::pair branch_t; + + quaternary_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1, + expression_ptr branch2, + expression_ptr branch3) + : operation_(opr) + { + init_branches<4>(branch_, branch0, branch1, branch2, branch3); + } + + ~quaternary_node() + { + cleanup_branches::execute(branch_); + } + + inline T value() const + { + return std::numeric_limits::quiet_NaN(); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_quaternary; + } + + protected: + + operator_type operation_; + branch_t branch_[4]; + }; + + template + class conditional_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + conditional_node(expression_ptr test, + expression_ptr consequent, + expression_ptr alternative) + : test_(test), + consequent_(consequent), + alternative_(alternative), + test_deletable_(branch_deletable(test_)), + consequent_deletable_(branch_deletable(consequent_)), + alternative_deletable_(branch_deletable(alternative_)) + {} + + ~conditional_node() + { + if (test_ && test_deletable_) + { + destroy_node(test_); + } + + if (consequent_ && consequent_deletable_ ) + { + destroy_node(consequent_); + } + + if (alternative_ && alternative_deletable_) + { + destroy_node(alternative_); + } + } + + inline T value() const + { + if (is_true(test_)) + return consequent_->value(); + else + return alternative_->value(); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_conditional; + } + + private: + + expression_ptr test_; + expression_ptr consequent_; + expression_ptr alternative_; + const bool test_deletable_; + const bool consequent_deletable_; + const bool alternative_deletable_; + }; + + template + class cons_conditional_node : public expression_node + { + public: + + // Consequent only conditional statement node + typedef expression_node* expression_ptr; + + cons_conditional_node(expression_ptr test, + expression_ptr consequent) + : test_(test), + consequent_(consequent), + test_deletable_(branch_deletable(test_)), + consequent_deletable_(branch_deletable(consequent_)) + {} + + ~cons_conditional_node() + { + if (test_ && test_deletable_) + { + destroy_node(test_); + } + + if (consequent_ && consequent_deletable_) + { + destroy_node(consequent_); + } + } + + inline T value() const + { + if (is_true(test_)) + return consequent_->value(); + else + return std::numeric_limits::quiet_NaN(); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_conditional; + } + + private: + + expression_ptr test_; + expression_ptr consequent_; + const bool test_deletable_; + const bool consequent_deletable_; + }; + + #ifndef exprtk_disable_break_continue + template + class break_exception + { + public: + + break_exception(const T& v) + : value(v) + {} + + T value; + }; + + class continue_exception + {}; + + template + class break_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + break_node(expression_ptr ret = expression_ptr(0)) + : return_(ret), + return_deletable_(branch_deletable(return_)) + {} + + ~break_node() + { + if (return_deletable_) + { + destroy_node(return_); + } + } + + inline T value() const + { + throw break_exception(return_ ? return_->value() : std::numeric_limits::quiet_NaN()); + #ifndef _MSC_VER + return std::numeric_limits::quiet_NaN(); + #endif + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_break; + } + + private: + + expression_ptr return_; + const bool return_deletable_; + }; + + template + class continue_node : public expression_node + { + public: + + inline T value() const + { + throw continue_exception(); + #ifndef _MSC_VER + return std::numeric_limits::quiet_NaN(); + #endif + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_break; + } + }; + #endif + + template + class while_loop_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + while_loop_node(expression_ptr condition, expression_ptr loop_body) + : condition_(condition), + loop_body_(loop_body), + condition_deletable_(branch_deletable(condition_)), + loop_body_deletable_(branch_deletable(loop_body_)) + {} + + ~while_loop_node() + { + if (condition_ && condition_deletable_) + { + destroy_node(condition_); + } + + if (loop_body_ && loop_body_deletable_) + { + destroy_node(loop_body_); + } + } + + inline T value() const + { + T result = T(0); + + while (is_true(condition_)) + { + result = loop_body_->value(); + } + + return result; + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_while; + } + + private: + + expression_ptr condition_; + expression_ptr loop_body_; + const bool condition_deletable_; + const bool loop_body_deletable_; + }; + + template + class repeat_until_loop_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + repeat_until_loop_node(expression_ptr condition, expression_ptr loop_body) + : condition_(condition), + loop_body_(loop_body), + condition_deletable_(branch_deletable(condition_)), + loop_body_deletable_(branch_deletable(loop_body_)) + {} + + ~repeat_until_loop_node() + { + if (condition_ && condition_deletable_) + { + destroy_node(condition_); + } + + if (loop_body_ && loop_body_deletable_) + { + destroy_node(loop_body_); + } + } + + inline T value() const + { + T result = T(0); + + do + { + result = loop_body_->value(); + } + while (is_false(condition_)); + + return result; + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_repeat; + } + + private: + + expression_ptr condition_; + expression_ptr loop_body_; + const bool condition_deletable_; + const bool loop_body_deletable_; + }; + + template + class for_loop_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + for_loop_node(expression_ptr initialiser, + expression_ptr condition, + expression_ptr incrementor, + expression_ptr loop_body) + : initialiser_(initialiser), + condition_ (condition ), + incrementor_(incrementor), + loop_body_ (loop_body ), + initialiser_deletable_(branch_deletable(initialiser_)), + condition_deletable_ (branch_deletable(condition_ )), + incrementor_deletable_(branch_deletable(incrementor_)), + loop_body_deletable_ (branch_deletable(loop_body_ )) + {} + + ~for_loop_node() + { + if (initialiser_ && initialiser_deletable_) + { + destroy_node(initialiser_); + } + + if (condition_ && condition_deletable_) + { + destroy_node(condition_); + } + + if (incrementor_ && incrementor_deletable_) + { + destroy_node(incrementor_); + } + + if (loop_body_ && loop_body_deletable_) + { + destroy_node(loop_body_); + } + } + + inline T value() const + { + T result = T(0); + + if (initialiser_) + initialiser_->value(); + + if (incrementor_) + { + while (is_true(condition_)) + { + result = loop_body_->value(); + incrementor_->value(); + } + } + else + { + while (is_true(condition_)) + { + result = loop_body_->value(); + } + } + + return result; + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_for; + } + + private: + + expression_ptr initialiser_ ; + expression_ptr condition_ ; + expression_ptr incrementor_ ; + expression_ptr loop_body_ ; + const bool initialiser_deletable_; + const bool condition_deletable_ ; + const bool incrementor_deletable_; + const bool loop_body_deletable_ ; + }; + + #ifndef exprtk_disable_break_continue + template + class while_loop_bc_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + while_loop_bc_node(expression_ptr condition, expression_ptr loop_body) + : condition_(condition), + loop_body_(loop_body), + condition_deletable_(branch_deletable(condition_)), + loop_body_deletable_(branch_deletable(loop_body_)) + {} + + ~while_loop_bc_node() + { + if (condition_ && condition_deletable_) + { + destroy_node(condition_); + } + + if (loop_body_ && loop_body_deletable_) + { + destroy_node(loop_body_); + } + } + + inline T value() const + { + T result = T(0); + + while (is_true(condition_)) + { + try + { + result = loop_body_->value(); + } + catch(const break_exception& e) + { + return e.value; + } + catch(const continue_exception&) + {} + } + + return result; + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_while; + } + + private: + + expression_ptr condition_; + expression_ptr loop_body_; + const bool condition_deletable_; + const bool loop_body_deletable_; + }; + + template + class repeat_until_loop_bc_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + repeat_until_loop_bc_node(expression_ptr condition, expression_ptr loop_body) + : condition_(condition), + loop_body_(loop_body), + condition_deletable_(branch_deletable(condition_)), + loop_body_deletable_(branch_deletable(loop_body_)) + {} + + ~repeat_until_loop_bc_node() + { + if (condition_ && condition_deletable_) + { + destroy_node(condition_); + } + + if (loop_body_ && loop_body_deletable_) + { + destroy_node(loop_body_); + } + } + + inline T value() const + { + T result = T(0); + + do + { + try + { + result = loop_body_->value(); + } + catch(const break_exception& e) + { + return e.value; + } + catch(const continue_exception&) + {} + } + while (is_false(condition_)); + + return result; + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_repeat; + } + + private: + + expression_ptr condition_; + expression_ptr loop_body_; + const bool condition_deletable_; + const bool loop_body_deletable_; + }; + + template + class for_loop_bc_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + for_loop_bc_node(expression_ptr initialiser, + expression_ptr condition, + expression_ptr incrementor, + expression_ptr loop_body) + : initialiser_(initialiser), + condition_ (condition ), + incrementor_(incrementor), + loop_body_ (loop_body ), + initialiser_deletable_(branch_deletable(initialiser_)), + condition_deletable_ (branch_deletable(condition_ )), + incrementor_deletable_(branch_deletable(incrementor_)), + loop_body_deletable_ (branch_deletable(loop_body_ )) + {} + + ~for_loop_bc_node() + { + if (initialiser_ && initialiser_deletable_) + { + destroy_node(initialiser_); + } + + if (condition_ && condition_deletable_) + { + destroy_node(condition_); + } + + if (incrementor_ && incrementor_deletable_) + { + destroy_node(incrementor_); + } + + if (loop_body_ && loop_body_deletable_) + { + destroy_node(loop_body_); + } + } + + inline T value() const + { + T result = T(0); + + if (initialiser_) + initialiser_->value(); + + if (incrementor_) + { + while (is_true(condition_)) + { + try + { + result = loop_body_->value(); + } + catch(const break_exception& e) + { + return e.value; + } + catch(const continue_exception&) + {} + + incrementor_->value(); + } + } + else + { + while (is_true(condition_)) + { + try + { + result = loop_body_->value(); + } + catch(const break_exception& e) + { + return e.value; + } + catch(const continue_exception&) + {} + } + } + + return result; + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_for; + } + + private: + + expression_ptr initialiser_; + expression_ptr condition_ ; + expression_ptr incrementor_; + expression_ptr loop_body_ ; + const bool initialiser_deletable_; + const bool condition_deletable_ ; + const bool incrementor_deletable_; + const bool loop_body_deletable_ ; + }; + #endif + + template + class switch_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + template class Sequence> + explicit switch_node(const Sequence& arg_list) + { + if (1 != (arg_list.size() & 1)) + return; + + arg_list_.resize(arg_list.size()); + delete_branch_.resize(arg_list.size()); + + for (std::size_t i = 0; i < arg_list.size(); ++i) + { + if (arg_list[i]) + { + arg_list_[i] = arg_list[i]; + delete_branch_[i] = static_cast(branch_deletable(arg_list_[i]) ? 1 : 0); + } + else + { + arg_list_.clear(); + delete_branch_.clear(); + return; + } + } + } + + ~switch_node() + { + for (std::size_t i = 0; i < arg_list_.size(); ++i) + { + if (arg_list_[i] && delete_branch_[i]) + { + destroy_node(arg_list_[i]); + } + } + } + + inline T value() const + { + if (!arg_list_.empty()) + { + const std::size_t upper_bound = (arg_list_.size() - 1); + + for (std::size_t i = 0; i < upper_bound; i += 2) + { + expression_ptr condition = arg_list_[i ]; + expression_ptr consequent = arg_list_[i + 1]; + + if (is_true(condition)) + { + return consequent->value(); + } + } + + return arg_list_[upper_bound]->value(); + } + else + return std::numeric_limits::quiet_NaN(); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_switch; + } + + protected: + + std::vector arg_list_; + std::vector delete_branch_; + }; + + template + class switch_n_node : public switch_node + { + public: + + typedef expression_node* expression_ptr; + + template class Sequence> + explicit switch_n_node(const Sequence& arg_list) + : switch_node(arg_list) + {} + + inline T value() const + { + return Switch_N::process(switch_node::arg_list_); + } + }; + + template + class multi_switch_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + template class Sequence> + explicit multi_switch_node(const Sequence& arg_list) + { + if (0 != (arg_list.size() & 1)) + return; + + arg_list_.resize(arg_list.size()); + delete_branch_.resize(arg_list.size()); + + for (std::size_t i = 0; i < arg_list.size(); ++i) + { + if (arg_list[i]) + { + arg_list_[i] = arg_list[i]; + delete_branch_[i] = static_cast(branch_deletable(arg_list_[i]) ? 1 : 0); + } + else + { + arg_list_.clear(); + delete_branch_.clear(); + return; + } + } + } + + ~multi_switch_node() + { + for (std::size_t i = 0; i < arg_list_.size(); ++i) + { + if (arg_list_[i] && delete_branch_[i]) + { + destroy_node(arg_list_[i]); + } + } + } + + inline T value() const + { + T result = T(0); + + if (arg_list_.empty()) + { + return std::numeric_limits::quiet_NaN(); + } + + const std::size_t upper_bound = (arg_list_.size() - 1); + + for (std::size_t i = 0; i < upper_bound; i += 2) + { + expression_ptr condition = arg_list_[i ]; + expression_ptr consequent = arg_list_[i + 1]; + + if (is_true(condition)) + { + result = consequent->value(); + } + } + + return result; + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_mswitch; + } + + private: + + std::vector arg_list_; + std::vector delete_branch_; + }; + + template + class ivariable + { + public: + + virtual ~ivariable() + {} + + virtual T& ref() = 0; + virtual const T& ref() const = 0; + }; + + template + class variable_node : public expression_node, + public ivariable + { + public: + + static T null_value; + + explicit variable_node() + : value_(&null_value) + {} + + explicit variable_node(T& v) + : value_(&v) + {} + + inline bool operator <(const variable_node& v) const + { + return this < (&v); + } + + inline T value() const + { + return (*value_); + } + + inline T& ref() + { + return (*value_); + } + + inline const T& ref() const + { + return (*value_); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_variable; + } + + private: + + T* value_; + }; + + template + T variable_node::null_value = T(std::numeric_limits::quiet_NaN()); + + template + struct range_pack + { + typedef expression_node* expression_node_ptr; + typedef std::pair cached_range_t; + + range_pack() + : n0_e (std::make_pair(false,expression_node_ptr(0))), + n1_e (std::make_pair(false,expression_node_ptr(0))), + n0_c (std::make_pair(false,0)), + n1_c (std::make_pair(false,0)), + cache(std::make_pair(0,0)) + {} + + void clear() + { + n0_e = std::make_pair(false,expression_node_ptr(0)); + n1_e = std::make_pair(false,expression_node_ptr(0)); + n0_c = std::make_pair(false,0); + n1_c = std::make_pair(false,0); + cache = std::make_pair(0,0); + } + + void free() + { + if (n0_e.first && n0_e.second) + { + n0_e.first = false; + + if ( + !is_variable_node(n0_e.second) && + !is_string_node (n0_e.second) + ) + { + destroy_node(n0_e.second); + } + } + + if (n1_e.first && n1_e.second) + { + n1_e.first = false; + + if ( + !is_variable_node(n1_e.second) && + !is_string_node (n1_e.second) + ) + { + destroy_node(n1_e.second); + } + } + } + + bool const_range() + { + return ( n0_c.first && n1_c.first) && + (!n0_e.first && !n1_e.first); + } + + bool var_range() + { + return ( n0_e.first && n1_e.first) && + (!n0_c.first && !n1_c.first); + } + + bool operator() (std::size_t& r0, std::size_t& r1, const std::size_t& size = std::numeric_limits::max()) const + { + if (n0_c.first) + r0 = n0_c.second; + else if (n0_e.first) + { + const T r0_value = n0_e.second->value(); + + if (r0_value < 0) + return false; + else + r0 = static_cast(details::numeric::to_int64(r0_value)); + } + else + return false; + + if (n1_c.first) + r1 = n1_c.second; + else if (n1_e.first) + { + const T r1_value = n1_e.second->value(); + + if (r1_value < 0) + return false; + else + r1 = static_cast(details::numeric::to_int64(r1_value)); + } + else + return false; + + if ( + (std::numeric_limits::max() != size) && + (std::numeric_limits::max() == r1 ) + ) + { + r1 = size - 1; + } + + cache.first = r0; + cache.second = r1; + + return (r0 <= r1); + } + + inline std::size_t const_size() const + { + return (n1_c.second - n0_c.second + 1); + } + + inline std::size_t cache_size() const + { + return (cache.second - cache.first + 1); + } + + std::pair n0_e; + std::pair n1_e; + std::pair n0_c; + std::pair n1_c; + mutable cached_range_t cache; + }; + + template + class string_base_node; + + template + struct range_data_type + { + typedef range_pack range_t; + typedef string_base_node* strbase_ptr_t; + + range_data_type() + : range(0), + data (0), + size (0), + type_size(0), + str_node (0) + {} + + range_t* range; + void* data; + std::size_t size; + std::size_t type_size; + strbase_ptr_t str_node; + }; + + template class vector_node; + + template + class vector_interface + { + public: + + typedef vector_node* vector_node_ptr; + typedef vec_data_store vds_t; + + virtual ~vector_interface() + {} + + virtual std::size_t size () const = 0; + + virtual vector_node_ptr vec() const = 0; + + virtual vector_node_ptr vec() = 0; + + virtual vds_t& vds () = 0; + + virtual const vds_t& vds () const = 0; + + virtual bool side_effect () const { return false; } + }; + + template + class vector_node : public expression_node , + public vector_interface + { + public: + + typedef expression_node* expression_ptr; + typedef vector_holder vector_holder_t; + typedef vector_node* vector_node_ptr; + typedef vec_data_store vds_t; + + explicit vector_node(vector_holder_t* vh) + : vector_holder_(vh), + vds_((*vector_holder_).size(),(*vector_holder_)[0]) + { + vector_holder_->set_ref(&vds_.ref()); + } + + vector_node(const vds_t& vds, vector_holder_t* vh) + : vector_holder_(vh), + vds_(vds) + {} + + inline T value() const + { + return vds().data()[0]; + } + + vector_node_ptr vec() const + { + return const_cast(this); + } + + vector_node_ptr vec() + { + return this; + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_vector; + } + + std::size_t size() const + { + return vds().size(); + } + + vds_t& vds() + { + return vds_; + } + + const vds_t& vds() const + { + return vds_; + } + + inline vector_holder_t& vec_holder() + { + return (*vector_holder_); + } + + private: + + vector_holder_t* vector_holder_; + vds_t vds_; + }; + + template + class vector_elem_node : public expression_node, + public ivariable + { + public: + + typedef expression_node* expression_ptr; + typedef vector_holder vector_holder_t; + typedef vector_holder_t* vector_holder_ptr; + + vector_elem_node(expression_ptr index, vector_holder_ptr vec_holder) + : index_(index), + vec_holder_(vec_holder), + vector_base_((*vec_holder)[0]), + index_deletable_(branch_deletable(index_)) + {} + + ~vector_elem_node() + { + if (index_ && index_deletable_) + { + destroy_node(index_); + } + } + + inline T value() const + { + return *(vector_base_ + static_cast(details::numeric::to_int64(index_->value()))); + } + + inline T& ref() + { + return *(vector_base_ + static_cast(details::numeric::to_int64(index_->value()))); + } + + inline const T& ref() const + { + return *(vector_base_ + static_cast(details::numeric::to_int64(index_->value()))); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_vecelem; + } + + inline vector_holder_t& vec_holder() + { + return (*vec_holder_); + } + + private: + + expression_ptr index_; + vector_holder_ptr vec_holder_; + T* vector_base_; + const bool index_deletable_; + }; + + template + class rebasevector_elem_node : public expression_node, + public ivariable + { + public: + + typedef expression_node* expression_ptr; + typedef vector_holder vector_holder_t; + typedef vector_holder_t* vector_holder_ptr; + typedef vec_data_store vds_t; + + rebasevector_elem_node(expression_ptr index, vector_holder_ptr vec_holder) + : index_(index), + index_deletable_(branch_deletable(index_)), + vector_holder_(vec_holder), + vds_((*vector_holder_).size(),(*vector_holder_)[0]) + { + vector_holder_->set_ref(&vds_.ref()); + } + + ~rebasevector_elem_node() + { + if (index_ && index_deletable_) + { + destroy_node(index_); + } + } + + inline T value() const + { + return *(vds_.data() + static_cast(details::numeric::to_int64(index_->value()))); + } + + inline T& ref() + { + return *(vds_.data() + static_cast(details::numeric::to_int64(index_->value()))); + } + + inline const T& ref() const + { + return *(vds_.data() + static_cast(details::numeric::to_int64(index_->value()))); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_rbvecelem; + } + + inline vector_holder_t& vec_holder() + { + return (*vector_holder_); + } + + private: + + expression_ptr index_; + const bool index_deletable_; + vector_holder_ptr vector_holder_; + vds_t vds_; + }; + + template + class rebasevector_celem_node : public expression_node, + public ivariable + { + public: + + typedef expression_node* expression_ptr; + typedef vector_holder vector_holder_t; + typedef vector_holder_t* vector_holder_ptr; + typedef vec_data_store vds_t; + + rebasevector_celem_node(const std::size_t index, vector_holder_ptr vec_holder) + : index_(index), + vector_holder_(vec_holder), + vds_((*vector_holder_).size(),(*vector_holder_)[0]) + { + vector_holder_->set_ref(&vds_.ref()); + } + + inline T value() const + { + return *(vds_.data() + index_); + } + + inline T& ref() + { + return *(vds_.data() + index_); + } + + inline const T& ref() const + { + return *(vds_.data() + index_); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_rbveccelem; + } + + inline vector_holder_t& vec_holder() + { + return (*vector_holder_); + } + + private: + + const std::size_t index_; + vector_holder_ptr vector_holder_; + vds_t vds_; + }; + + template + class vector_assignment_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + vector_assignment_node(T* vector_base, + const std::size_t& size, + const std::vector& initialiser_list, + const bool single_value_initialse) + : vector_base_(vector_base), + initialiser_list_(initialiser_list), + size_(size), + single_value_initialse_(single_value_initialse) + {} + + ~vector_assignment_node() + { + for (std::size_t i = 0; i < initialiser_list_.size(); ++i) + { + if (branch_deletable(initialiser_list_[i])) + { + destroy_node(initialiser_list_[i]); + } + } + } + + inline T value() const + { + if (single_value_initialse_) + { + for (std::size_t i = 0; i < size_; ++i) + { + *(vector_base_ + i) = initialiser_list_[0]->value(); + } + } + else + { + std::size_t il_size = initialiser_list_.size(); + + for (std::size_t i = 0; i < il_size; ++i) + { + *(vector_base_ + i) = initialiser_list_[i]->value(); + } + + if (il_size < size_) + { + for (std::size_t i = il_size; i < size_; ++i) + { + *(vector_base_ + i) = T(0); + } + } + } + + return *(vector_base_); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_vecdefass; + } + + private: + + vector_assignment_node& operator=(const vector_assignment_node&); + + mutable T* vector_base_; + std::vector initialiser_list_; + const std::size_t size_; + const bool single_value_initialse_; + }; + + template + class swap_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + typedef variable_node* variable_node_ptr; + + swap_node(variable_node_ptr var0, variable_node_ptr var1) + : var0_(var0), + var1_(var1) + {} + + inline T value() const + { + std::swap(var0_->ref(),var1_->ref()); + return var1_->ref(); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_swap; + } + + private: + + variable_node_ptr var0_; + variable_node_ptr var1_; + }; + + template + class swap_generic_node : public binary_node + { + public: + + typedef expression_node* expression_ptr; + typedef ivariable* ivariable_ptr; + + swap_generic_node(expression_ptr var0, expression_ptr var1) + : binary_node(details::e_swap, var0, var1), + var0_(dynamic_cast(var0)), + var1_(dynamic_cast(var1)) + {} + + inline T value() const + { + std::swap(var0_->ref(),var1_->ref()); + return var1_->ref(); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_swap; + } + + private: + + ivariable_ptr var0_; + ivariable_ptr var1_; + }; + + template + class swap_vecvec_node : public binary_node , + public vector_interface + { + public: + + typedef expression_node* expression_ptr; + typedef vector_node* vector_node_ptr; + typedef vec_data_store vds_t; + + swap_vecvec_node(expression_ptr branch0, + expression_ptr branch1) + : binary_node(details::e_swap, branch0, branch1), + vec0_node_ptr_(0), + vec1_node_ptr_(0), + vec_size_ (0), + initialised_ (false) + { + if (is_ivector_node(binary_node::branch_[0].first)) + { + vector_interface* vi = reinterpret_cast*>(0); + + if (0 != (vi = dynamic_cast*>(binary_node::branch_[0].first))) + { + vec0_node_ptr_ = vi->vec(); + vds() = vi->vds(); + } + } + + if (is_ivector_node(binary_node::branch_[1].first)) + { + vector_interface* vi = reinterpret_cast*>(0); + + if (0 != (vi = dynamic_cast*>(binary_node::branch_[1].first))) + { + vec1_node_ptr_ = vi->vec(); + } + } + + if (vec0_node_ptr_ && vec1_node_ptr_) + { + vec_size_ = std::min(vec0_node_ptr_->vds().size(), + vec1_node_ptr_->vds().size()); + + initialised_ = true; + } + } + + inline T value() const + { + if (initialised_) + { + binary_node::branch_[0].first->value(); + binary_node::branch_[1].first->value(); + + T* vec0 = vec0_node_ptr_->vds().data(); + T* vec1 = vec1_node_ptr_->vds().data(); + + for (std::size_t i = 0; i < vec_size_; ++i) + { + std::swap(vec0[i],vec1[i]); + } + + return vec1_node_ptr_->value(); + } + else + return std::numeric_limits::quiet_NaN(); + } + + vector_node_ptr vec() const + { + return vec0_node_ptr_; + } + + vector_node_ptr vec() + { + return vec0_node_ptr_; + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_vecvecswap; + } + + std::size_t size() const + { + return vec_size_; + } + + vds_t& vds() + { + return vds_; + } + + const vds_t& vds() const + { + return vds_; + } + + private: + + vector_node* vec0_node_ptr_; + vector_node* vec1_node_ptr_; + std::size_t vec_size_; + bool initialised_; + vds_t vds_; + }; + + #ifndef exprtk_disable_string_capabilities + template + class stringvar_node : public expression_node , + public string_base_node, + public range_interface + { + public: + + typedef range_pack range_t; + + static std::string null_value; + + explicit stringvar_node() + : value_(&null_value) + {} + + explicit stringvar_node(std::string& v) + : value_(&v) + { + rp_.n0_c = std::make_pair(true,0); + rp_.n1_c = std::make_pair(true,v.size() - 1); + rp_.cache.first = rp_.n0_c.second; + rp_.cache.second = rp_.n1_c.second; + } + + inline bool operator <(const stringvar_node& v) const + { + return this < (&v); + } + + inline T value() const + { + rp_.n1_c.second = (*value_).size() - 1; + rp_.cache.second = rp_.n1_c.second; + + return std::numeric_limits::quiet_NaN(); + } + + std::string str() const + { + return ref(); + } + + char_cptr base() const + { + return &(*value_)[0]; + } + + std::size_t size() const + { + return ref().size(); + } + + std::string& ref() + { + return (*value_); + } + + const std::string& ref() const + { + return (*value_); + } + + range_t& range_ref() + { + return rp_; + } + + const range_t& range_ref() const + { + return rp_; + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_stringvar; + } + + private: + + std::string* value_; + mutable range_t rp_; + }; + + template + std::string stringvar_node::null_value = std::string(""); + + template + class string_range_node : public expression_node , + public string_base_node, + public range_interface + { + public: + + typedef range_pack range_t; + + static std::string null_value; + + explicit string_range_node(std::string& v, const range_t& rp) + : value_(&v), + rp_(rp) + {} + + virtual ~string_range_node() + { + rp_.free(); + } + + inline bool operator <(const string_range_node& v) const + { + return this < (&v); + } + + inline T value() const + { + return std::numeric_limits::quiet_NaN(); + } + + inline std::string str() const + { + return (*value_); + } + + char_cptr base() const + { + return &(*value_)[0]; + } + + std::size_t size() const + { + return ref().size(); + } + + inline range_t range() const + { + return rp_; + } + + inline virtual std::string& ref() + { + return (*value_); + } + + inline virtual const std::string& ref() const + { + return (*value_); + } + + inline range_t& range_ref() + { + return rp_; + } + + inline const range_t& range_ref() const + { + return rp_; + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_stringvarrng; + } + + private: + + std::string* value_; + range_t rp_; + }; + + template + std::string string_range_node::null_value = std::string(""); + + template + class const_string_range_node : public expression_node , + public string_base_node, + public range_interface + { + public: + + typedef range_pack range_t; + + explicit const_string_range_node(const std::string& v, const range_t& rp) + : value_(v), + rp_(rp) + {} + + ~const_string_range_node() + { + rp_.free(); + } + + inline T value() const + { + return std::numeric_limits::quiet_NaN(); + } + + std::string str() const + { + return value_; + } + + char_cptr base() const + { + return value_.data(); + } + + std::size_t size() const + { + return value_.size(); + } + + range_t range() const + { + return rp_; + } + + range_t& range_ref() + { + return rp_; + } + + const range_t& range_ref() const + { + return rp_; + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_cstringvarrng; + } + + private: + + const_string_range_node& operator=(const const_string_range_node&); + + const std::string value_; + range_t rp_; + }; + + template + class generic_string_range_node : public expression_node , + public string_base_node, + public range_interface + { + public: + + typedef expression_node * expression_ptr; + typedef stringvar_node * strvar_node_ptr; + typedef string_base_node* str_base_ptr; + typedef range_pack range_t; + typedef range_t* range_ptr; + typedef range_interface irange_t; + typedef irange_t* irange_ptr; + + generic_string_range_node(expression_ptr str_branch, const range_t& brange) + : initialised_(false), + branch_(str_branch), + branch_deletable_(branch_deletable(branch_)), + str_base_ptr_ (0), + str_range_ptr_(0), + base_range_(brange) + { + range_.n0_c = std::make_pair(true,0); + range_.n1_c = std::make_pair(true,0); + range_.cache.first = range_.n0_c.second; + range_.cache.second = range_.n1_c.second; + + if (is_generally_string_node(branch_)) + { + str_base_ptr_ = dynamic_cast(branch_); + + if (0 == str_base_ptr_) + return; + + str_range_ptr_ = dynamic_cast(branch_); + + if (0 == str_range_ptr_) + return; + } + + initialised_ = (str_base_ptr_ && str_range_ptr_); + } + + ~generic_string_range_node() + { + base_range_.free(); + + if (branch_ && branch_deletable_) + { + destroy_node(branch_); + } + } + + inline T value() const + { + if (initialised_) + { + branch_->value(); + + std::size_t str_r0 = 0; + std::size_t str_r1 = 0; + + std::size_t r0 = 0; + std::size_t r1 = 0; + + range_t& range = str_range_ptr_->range_ref(); + + const std::size_t base_str_size = str_base_ptr_->size(); + + if ( + range (str_r0,str_r1,base_str_size) && + base_range_( r0, r1,base_str_size) + ) + { + const std::size_t size = (r1 - r0) + 1; + + range_.n1_c.second = size - 1; + range_.cache.second = range_.n1_c.second; + + value_.assign(str_base_ptr_->base() + str_r0 + r0, size); + } + } + + return std::numeric_limits::quiet_NaN(); + } + + std::string str() const + { + return value_; + } + + char_cptr base() const + { + return &value_[0]; + } + + std::size_t size() const + { + return value_.size(); + } + + range_t& range_ref() + { + return range_; + } + + const range_t& range_ref() const + { + return range_; + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_strgenrange; + } + + private: + + bool initialised_; + expression_ptr branch_; + const bool branch_deletable_; + str_base_ptr str_base_ptr_; + irange_ptr str_range_ptr_; + mutable range_t base_range_; + mutable range_t range_; + mutable std::string value_; + }; + + template + class string_concat_node : public binary_node , + public string_base_node, + public range_interface + { + public: + + typedef expression_node * expression_ptr; + typedef string_base_node* str_base_ptr; + typedef range_pack range_t; + typedef range_t* range_ptr; + typedef range_interface irange_t; + typedef irange_t* irange_ptr; + + string_concat_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1), + initialised_(false), + str0_base_ptr_ (0), + str1_base_ptr_ (0), + str0_range_ptr_(0), + str1_range_ptr_(0) + { + range_.n0_c = std::make_pair(true,0); + range_.n1_c = std::make_pair(true,0); + + range_.cache.first = range_.n0_c.second; + range_.cache.second = range_.n1_c.second; + + if (is_generally_string_node(binary_node::branch_[0].first)) + { + str0_base_ptr_ = dynamic_cast(binary_node::branch_[0].first); + + if (0 == str0_base_ptr_) + return; + + str0_range_ptr_ = dynamic_cast(binary_node::branch_[0].first); + + if (0 == str0_range_ptr_) + return; + } + + if (is_generally_string_node(binary_node::branch_[1].first)) + { + str1_base_ptr_ = dynamic_cast(binary_node::branch_[1].first); + + if (0 == str1_base_ptr_) + return; + + str1_range_ptr_ = dynamic_cast(binary_node::branch_[1].first); + + if (0 == str1_range_ptr_) + return; + } + + initialised_ = str0_base_ptr_ && + str1_base_ptr_ && + str0_range_ptr_ && + str1_range_ptr_ ; + } + + inline T value() const + { + if (initialised_) + { + binary_node::branch_[0].first->value(); + binary_node::branch_[1].first->value(); + + std::size_t str0_r0 = 0; + std::size_t str0_r1 = 0; + + std::size_t str1_r0 = 0; + std::size_t str1_r1 = 0; + + range_t& range0 = str0_range_ptr_->range_ref(); + range_t& range1 = str1_range_ptr_->range_ref(); + + if ( + range0(str0_r0, str0_r1, str0_base_ptr_->size()) && + range1(str1_r0, str1_r1, str1_base_ptr_->size()) + ) + { + const std::size_t size0 = (str0_r1 - str0_r0) + 1; + const std::size_t size1 = (str1_r1 - str1_r0) + 1; + + value_.assign(str0_base_ptr_->base() + str0_r0, size0); + value_.append(str1_base_ptr_->base() + str1_r0, size1); + + range_.n1_c.second = value_.size() - 1; + range_.cache.second = range_.n1_c.second; + } + } + + return std::numeric_limits::quiet_NaN(); + } + + std::string str() const + { + return value_; + } + + char_cptr base() const + { + return &value_[0]; + } + + std::size_t size() const + { + return value_.size(); + } + + range_t& range_ref() + { + return range_; + } + + const range_t& range_ref() const + { + return range_; + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_strconcat; + } + + private: + + bool initialised_; + str_base_ptr str0_base_ptr_; + str_base_ptr str1_base_ptr_; + irange_ptr str0_range_ptr_; + irange_ptr str1_range_ptr_; + mutable range_t range_; + mutable std::string value_; + }; + + template + class swap_string_node : public binary_node , + public string_base_node, + public range_interface + { + public: + + typedef expression_node * expression_ptr; + typedef stringvar_node * strvar_node_ptr; + typedef string_base_node* str_base_ptr; + typedef range_pack range_t; + typedef range_t* range_ptr; + typedef range_interface irange_t; + typedef irange_t* irange_ptr; + + swap_string_node(expression_ptr branch0, expression_ptr branch1) + : binary_node(details::e_swap, branch0, branch1), + initialised_(false), + str0_node_ptr_(0), + str1_node_ptr_(0) + { + if (is_string_node(binary_node::branch_[0].first)) + { + str0_node_ptr_ = static_cast(binary_node::branch_[0].first); + } + + if (is_string_node(binary_node::branch_[1].first)) + { + str1_node_ptr_ = static_cast(binary_node::branch_[1].first); + } + + initialised_ = (str0_node_ptr_ && str1_node_ptr_); + } + + inline T value() const + { + if (initialised_) + { + binary_node::branch_[0].first->value(); + binary_node::branch_[1].first->value(); + + std::swap(str0_node_ptr_->ref(),str1_node_ptr_->ref()); + } + + return std::numeric_limits::quiet_NaN(); + } + + std::string str() const + { + return str0_node_ptr_->str(); + } + + char_cptr base() const + { + return str0_node_ptr_->base(); + } + + std::size_t size() const + { + return str0_node_ptr_->size(); + } + + range_t& range_ref() + { + return str0_node_ptr_->range_ref(); + } + + const range_t& range_ref() const + { + return str0_node_ptr_->range_ref(); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_strswap; + } + + private: + + bool initialised_; + strvar_node_ptr str0_node_ptr_; + strvar_node_ptr str1_node_ptr_; + }; + + template + class swap_genstrings_node : public binary_node + { + public: + + typedef expression_node * expression_ptr; + typedef string_base_node* str_base_ptr; + typedef range_pack range_t; + typedef range_t* range_ptr; + typedef range_interface irange_t; + typedef irange_t* irange_ptr; + + swap_genstrings_node(expression_ptr branch0, + expression_ptr branch1) + : binary_node(details::e_default, branch0, branch1), + str0_base_ptr_ (0), + str1_base_ptr_ (0), + str0_range_ptr_(0), + str1_range_ptr_(0), + initialised_(false) + { + if (is_generally_string_node(binary_node::branch_[0].first)) + { + str0_base_ptr_ = dynamic_cast(binary_node::branch_[0].first); + + if (0 == str0_base_ptr_) + return; + + irange_ptr range = dynamic_cast(binary_node::branch_[0].first); + + if (0 == range) + return; + + str0_range_ptr_ = &(range->range_ref()); + } + + if (is_generally_string_node(binary_node::branch_[1].first)) + { + str1_base_ptr_ = dynamic_cast(binary_node::branch_[1].first); + + if (0 == str1_base_ptr_) + return; + + irange_ptr range = dynamic_cast(binary_node::branch_[1].first); + + if (0 == range) + return; + + str1_range_ptr_ = &(range->range_ref()); + } + + initialised_ = str0_base_ptr_ && + str1_base_ptr_ && + str0_range_ptr_ && + str1_range_ptr_ ; + } + + inline T value() const + { + if (initialised_) + { + binary_node::branch_[0].first->value(); + binary_node::branch_[1].first->value(); + + std::size_t str0_r0 = 0; + std::size_t str0_r1 = 0; + + std::size_t str1_r0 = 0; + std::size_t str1_r1 = 0; + + range_t& range0 = (*str0_range_ptr_); + range_t& range1 = (*str1_range_ptr_); + + if ( + range0(str0_r0, str0_r1, str0_base_ptr_->size()) && + range1(str1_r0, str1_r1, str1_base_ptr_->size()) + ) + { + const std::size_t size0 = range0.cache_size(); + const std::size_t size1 = range1.cache_size(); + const std::size_t max_size = std::min(size0,size1); + + char_ptr s0 = const_cast(str0_base_ptr_->base() + str0_r0); + char_ptr s1 = const_cast(str1_base_ptr_->base() + str1_r0); + + loop_unroll::details lud(max_size); + char_cptr upper_bound = s0 + lud.upper_bound; + + while (s0 < upper_bound) + { + #define exprtk_loop(N) \ + std::swap(s0[N], s1[N]); \ + + exprtk_loop( 0) exprtk_loop( 1) + exprtk_loop( 2) exprtk_loop( 3) + #ifndef exprtk_disable_superscalar_unroll + exprtk_loop( 4) exprtk_loop( 5) + exprtk_loop( 6) exprtk_loop( 7) + exprtk_loop( 8) exprtk_loop( 9) + exprtk_loop(10) exprtk_loop(11) + exprtk_loop(12) exprtk_loop(13) + exprtk_loop(14) exprtk_loop(15) + #endif + + s0 += lud.batch_size; + s1 += lud.batch_size; + } + + int i = 0; + + exprtk_disable_fallthrough_begin + switch (lud.remainder) + { + #define case_stmt(N) \ + case N : { std::swap(s0[i],s1[i]); ++i; } \ + + #ifndef exprtk_disable_superscalar_unroll + case_stmt(15) case_stmt(14) + case_stmt(13) case_stmt(12) + case_stmt(11) case_stmt(10) + case_stmt( 9) case_stmt( 8) + case_stmt( 7) case_stmt( 6) + case_stmt( 5) case_stmt( 4) + #endif + case_stmt( 3) case_stmt( 2) + case_stmt( 1) + } + exprtk_disable_fallthrough_end + + #undef exprtk_loop + #undef case_stmt + } + } + + return std::numeric_limits::quiet_NaN(); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_strswap; + } + + private: + + swap_genstrings_node(swap_genstrings_node&); + swap_genstrings_node& operator=(swap_genstrings_node&); + + str_base_ptr str0_base_ptr_; + str_base_ptr str1_base_ptr_; + range_ptr str0_range_ptr_; + range_ptr str1_range_ptr_; + bool initialised_; + }; + + template + class stringvar_size_node : public expression_node + { + public: + + static std::string null_value; + + explicit stringvar_size_node() + : value_(&null_value) + {} + + explicit stringvar_size_node(std::string& v) + : value_(&v) + {} + + inline T value() const + { + return T((*value_).size()); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_stringvarsize; + } + + private: + + std::string* value_; + }; + + template + std::string stringvar_size_node::null_value = std::string(""); + + template + class string_size_node : public expression_node + { + public: + + typedef expression_node * expression_ptr; + typedef string_base_node* str_base_ptr; + + explicit string_size_node(expression_ptr brnch) + : branch_(brnch), + branch_deletable_(branch_deletable(branch_)), + str_base_ptr_(0) + { + if (is_generally_string_node(branch_)) + { + str_base_ptr_ = dynamic_cast(branch_); + + if (0 == str_base_ptr_) + return; + } + } + + ~string_size_node() + { + if (branch_ && branch_deletable_) + { + destroy_node(branch_); + } + } + + inline T value() const + { + T result = std::numeric_limits::quiet_NaN(); + + if (str_base_ptr_) + { + branch_->value(); + result = T(str_base_ptr_->size()); + } + + return result; + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_stringsize; + } + + private: + + expression_ptr branch_; + const bool branch_deletable_; + str_base_ptr str_base_ptr_; + }; + + struct asn_assignment + { + static inline void execute(std::string& s, char_cptr data, const std::size_t size) + { s.assign(data,size); } + }; + + struct asn_addassignment + { + static inline void execute(std::string& s, char_cptr data, const std::size_t size) + { s.append(data,size); } + }; + + template + class assignment_string_node : public binary_node , + public string_base_node, + public range_interface + { + public: + + typedef expression_node * expression_ptr; + typedef stringvar_node * strvar_node_ptr; + typedef string_base_node* str_base_ptr; + typedef range_pack range_t; + typedef range_t* range_ptr; + typedef range_interface irange_t; + typedef irange_t* irange_ptr; + + assignment_string_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1), + initialised_(false), + str0_base_ptr_ (0), + str1_base_ptr_ (0), + str0_node_ptr_ (0), + str1_range_ptr_(0) + { + if (is_string_node(binary_node::branch_[0].first)) + { + str0_node_ptr_ = static_cast(binary_node::branch_[0].first); + + str0_base_ptr_ = dynamic_cast(binary_node::branch_[0].first); + } + + if (is_generally_string_node(binary_node::branch_[1].first)) + { + str1_base_ptr_ = dynamic_cast(binary_node::branch_[1].first); + + if (0 == str1_base_ptr_) + return; + + irange_ptr range = dynamic_cast(binary_node::branch_[1].first); + + if (0 == range) + return; + + str1_range_ptr_ = &(range->range_ref()); + } + + initialised_ = str0_base_ptr_ && + str1_base_ptr_ && + str0_node_ptr_ && + str1_range_ptr_ ; + } + + inline T value() const + { + if (initialised_) + { + binary_node::branch_[1].first->value(); + + std::size_t r0 = 0; + std::size_t r1 = 0; + + range_t& range = (*str1_range_ptr_); + + if (range(r0, r1, str1_base_ptr_->size())) + { + AssignmentProcess::execute(str0_node_ptr_->ref(), + str1_base_ptr_->base() + r0, + (r1 - r0) + 1); + + binary_node::branch_[0].first->value(); + } + } + + return std::numeric_limits::quiet_NaN(); + } + + std::string str() const + { + return str0_node_ptr_->str(); + } + + char_cptr base() const + { + return str0_node_ptr_->base(); + } + + std::size_t size() const + { + return str0_node_ptr_->size(); + } + + range_t& range_ref() + { + return str0_node_ptr_->range_ref(); + } + + const range_t& range_ref() const + { + return str0_node_ptr_->range_ref(); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_strass; + } + + private: + + bool initialised_; + str_base_ptr str0_base_ptr_; + str_base_ptr str1_base_ptr_; + strvar_node_ptr str0_node_ptr_; + range_ptr str1_range_ptr_; + }; + + template + class assignment_string_range_node : public binary_node , + public string_base_node, + public range_interface + { + public: + + typedef expression_node * expression_ptr; + typedef stringvar_node * strvar_node_ptr; + typedef string_base_node* str_base_ptr; + typedef range_pack range_t; + typedef range_t* range_ptr; + typedef range_interface irange_t; + typedef irange_t* irange_ptr; + + assignment_string_range_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1), + initialised_(false), + str0_base_ptr_ (0), + str1_base_ptr_ (0), + str0_node_ptr_ (0), + str0_range_ptr_(0), + str1_range_ptr_(0) + { + if (is_string_range_node(binary_node::branch_[0].first)) + { + str0_node_ptr_ = static_cast(binary_node::branch_[0].first); + + str0_base_ptr_ = dynamic_cast(binary_node::branch_[0].first); + + irange_ptr range = dynamic_cast(binary_node::branch_[0].first); + + if (0 == range) + return; + + str0_range_ptr_ = &(range->range_ref()); + } + + if (is_generally_string_node(binary_node::branch_[1].first)) + { + str1_base_ptr_ = dynamic_cast(binary_node::branch_[1].first); + + if (0 == str1_base_ptr_) + return; + + irange_ptr range = dynamic_cast(binary_node::branch_[1].first); + + if (0 == range) + return; + + str1_range_ptr_ = &(range->range_ref()); + } + + initialised_ = str0_base_ptr_ && + str1_base_ptr_ && + str0_node_ptr_ && + str0_range_ptr_ && + str1_range_ptr_ ; + } + + inline T value() const + { + if (initialised_) + { + binary_node::branch_[0].first->value(); + binary_node::branch_[1].first->value(); + + std::size_t s0_r0 = 0; + std::size_t s0_r1 = 0; + + std::size_t s1_r0 = 0; + std::size_t s1_r1 = 0; + + range_t& range0 = (*str0_range_ptr_); + range_t& range1 = (*str1_range_ptr_); + + if ( + range0(s0_r0, s0_r1, str0_base_ptr_->size()) && + range1(s1_r0, s1_r1, str1_base_ptr_->size()) + ) + { + std::size_t size = std::min((s0_r1 - s0_r0),(s1_r1 - s1_r0)) + 1; + + std::copy(str1_base_ptr_->base() + s1_r0, + str1_base_ptr_->base() + s1_r0 + size, + const_cast(base() + s0_r0)); + } + } + + return std::numeric_limits::quiet_NaN(); + } + + std::string str() const + { + return str0_node_ptr_->str(); + } + + char_cptr base() const + { + return str0_node_ptr_->base(); + } + + std::size_t size() const + { + return str0_node_ptr_->size(); + } + + range_t& range_ref() + { + return str0_node_ptr_->range_ref(); + } + + const range_t& range_ref() const + { + return str0_node_ptr_->range_ref(); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_strass; + } + + private: + + bool initialised_; + str_base_ptr str0_base_ptr_; + str_base_ptr str1_base_ptr_; + strvar_node_ptr str0_node_ptr_; + range_ptr str0_range_ptr_; + range_ptr str1_range_ptr_; + }; + + template + class conditional_string_node : public trinary_node , + public string_base_node, + public range_interface + { + public: + + typedef expression_node * expression_ptr; + typedef string_base_node* str_base_ptr; + typedef range_pack range_t; + typedef range_t* range_ptr; + typedef range_interface irange_t; + typedef irange_t* irange_ptr; + + conditional_string_node(expression_ptr test, + expression_ptr consequent, + expression_ptr alternative) + : trinary_node(details::e_default,consequent,alternative,test), + initialised_(false), + str0_base_ptr_ (0), + str1_base_ptr_ (0), + str0_range_ptr_(0), + str1_range_ptr_(0), + test_ (test), + consequent_ (consequent), + alternative_(alternative) + { + range_.n0_c = std::make_pair(true,0); + range_.n1_c = std::make_pair(true,0); + + range_.cache.first = range_.n0_c.second; + range_.cache.second = range_.n1_c.second; + + if (is_generally_string_node(trinary_node::branch_[0].first)) + { + str0_base_ptr_ = dynamic_cast(trinary_node::branch_[0].first); + + if (0 == str0_base_ptr_) + return; + + str0_range_ptr_ = dynamic_cast(trinary_node::branch_[0].first); + + if (0 == str0_range_ptr_) + return; + } + + if (is_generally_string_node(trinary_node::branch_[1].first)) + { + str1_base_ptr_ = dynamic_cast(trinary_node::branch_[1].first); + + if (0 == str1_base_ptr_) + return; + + str1_range_ptr_ = dynamic_cast(trinary_node::branch_[1].first); + + if (0 == str1_range_ptr_) + return; + } + + initialised_ = str0_base_ptr_ && + str1_base_ptr_ && + str0_range_ptr_ && + str1_range_ptr_ ; + + } + + inline T value() const + { + if (initialised_) + { + std::size_t r0 = 0; + std::size_t r1 = 0; + + if (is_true(test_)) + { + consequent_->value(); + + range_t& range = str0_range_ptr_->range_ref(); + + if (range(r0, r1, str0_base_ptr_->size())) + { + const std::size_t size = (r1 - r0) + 1; + + value_.assign(str0_base_ptr_->base() + r0, size); + + range_.n1_c.second = value_.size() - 1; + range_.cache.second = range_.n1_c.second; + + return T(1); + } + } + else + { + alternative_->value(); + + range_t& range = str1_range_ptr_->range_ref(); + + if (range(r0, r1, str1_base_ptr_->size())) + { + const std::size_t size = (r1 - r0) + 1; + + value_.assign(str1_base_ptr_->base() + r0, size); + + range_.n1_c.second = value_.size() - 1; + range_.cache.second = range_.n1_c.second; + + return T(0); + } + } + } + + return std::numeric_limits::quiet_NaN(); + } + + std::string str() const + { + return value_; + } + + char_cptr base() const + { + return &value_[0]; + } + + std::size_t size() const + { + return value_.size(); + } + + range_t& range_ref() + { + return range_; + } + + const range_t& range_ref() const + { + return range_; + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_strcondition; + } + + private: + + bool initialised_; + str_base_ptr str0_base_ptr_; + str_base_ptr str1_base_ptr_; + irange_ptr str0_range_ptr_; + irange_ptr str1_range_ptr_; + mutable range_t range_; + mutable std::string value_; + + expression_ptr test_; + expression_ptr consequent_; + expression_ptr alternative_; + }; + + template + class cons_conditional_str_node : public binary_node , + public string_base_node, + public range_interface + { + public: + + typedef expression_node * expression_ptr; + typedef string_base_node* str_base_ptr; + typedef range_pack range_t; + typedef range_t* range_ptr; + typedef range_interface irange_t; + typedef irange_t* irange_ptr; + + cons_conditional_str_node(expression_ptr test, + expression_ptr consequent) + : binary_node(details::e_default, consequent, test), + initialised_(false), + str0_base_ptr_ (0), + str0_range_ptr_(0), + test_ (test), + consequent_(consequent) + { + range_.n0_c = std::make_pair(true,0); + range_.n1_c = std::make_pair(true,0); + + range_.cache.first = range_.n0_c.second; + range_.cache.second = range_.n1_c.second; + + if (is_generally_string_node(binary_node::branch_[0].first)) + { + str0_base_ptr_ = dynamic_cast(binary_node::branch_[0].first); + + if (0 == str0_base_ptr_) + return; + + str0_range_ptr_ = dynamic_cast(binary_node::branch_[0].first); + + if (0 == str0_range_ptr_) + return; + } + + initialised_ = str0_base_ptr_ && str0_range_ptr_ ; + } + + inline T value() const + { + if (initialised_) + { + if (is_true(test_)) + { + consequent_->value(); + + range_t& range = str0_range_ptr_->range_ref(); + + std::size_t r0 = 0; + std::size_t r1 = 0; + + if (range(r0, r1, str0_base_ptr_->size())) + { + const std::size_t size = (r1 - r0) + 1; + + value_.assign(str0_base_ptr_->base() + r0, size); + + range_.n1_c.second = value_.size() - 1; + range_.cache.second = range_.n1_c.second; + + return T(1); + } + } + } + + return std::numeric_limits::quiet_NaN(); + } + + std::string str() const + { + return value_; + } + + char_cptr base() const + { + return &value_[0]; + } + + std::size_t size() const + { + return value_.size(); + } + + range_t& range_ref() + { + return range_; + } + + const range_t& range_ref() const + { + return range_; + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_strccondition; + } + + private: + + bool initialised_; + str_base_ptr str0_base_ptr_; + irange_ptr str0_range_ptr_; + mutable range_t range_; + mutable std::string value_; + + expression_ptr test_; + expression_ptr consequent_; + }; + + template + class str_vararg_node : public expression_node , + public string_base_node, + public range_interface + { + public: + + typedef expression_node * expression_ptr; + typedef string_base_node* str_base_ptr; + typedef range_pack range_t; + typedef range_t* range_ptr; + typedef range_interface irange_t; + typedef irange_t* irange_ptr; + + template class Sequence> + explicit str_vararg_node(const Sequence& arg_list) + : final_node_(arg_list.back()), + final_deletable_(branch_deletable(final_node_)), + initialised_(false), + str_base_ptr_ (0), + str_range_ptr_(0) + { + if (0 == final_node_) + return; + else if (!is_generally_string_node(final_node_)) + return; + + str_base_ptr_ = dynamic_cast(final_node_); + + if (0 == str_base_ptr_) + return; + + str_range_ptr_ = dynamic_cast(final_node_); + + if (0 == str_range_ptr_) + return; + + initialised_ = str_base_ptr_ && str_range_ptr_; + + if (arg_list.size() > 1) + { + const std::size_t arg_list_size = arg_list.size() - 1; + + arg_list_.resize(arg_list_size); + delete_branch_.resize(arg_list_size); + + for (std::size_t i = 0; i < arg_list_size; ++i) + { + if (arg_list[i]) + { + arg_list_[i] = arg_list[i]; + delete_branch_[i] = static_cast(branch_deletable(arg_list_[i]) ? 1 : 0); + } + else + { + arg_list_ .clear(); + delete_branch_.clear(); + return; + } + } + } + } + + ~str_vararg_node() + { + if (final_node_ && final_deletable_) + { + destroy_node(final_node_); + } + + for (std::size_t i = 0; i < arg_list_.size(); ++i) + { + if (arg_list_[i] && delete_branch_[i]) + { + destroy_node(arg_list_[i]); + } + } + } + + inline T value() const + { + if (!arg_list_.empty()) + { + VarArgFunction::process(arg_list_); + } + + final_node_->value(); + + return std::numeric_limits::quiet_NaN(); + } + + std::string str() const + { + return str_base_ptr_->str(); + } + + char_cptr base() const + { + return str_base_ptr_->base(); + } + + std::size_t size() const + { + return str_base_ptr_->size(); + } + + range_t& range_ref() + { + return str_range_ptr_->range_ref(); + } + + const range_t& range_ref() const + { + return str_range_ptr_->range_ref(); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_stringvararg; + } + + private: + + expression_ptr final_node_; + bool final_deletable_; + bool initialised_; + str_base_ptr str_base_ptr_; + irange_ptr str_range_ptr_; + std::vector arg_list_; + std::vector delete_branch_; + }; + #endif + + template + inline T axn(T a, T x) + { + // a*x^n + return a * exprtk::details::numeric::fast_exp::result(x); + } + + template + inline T axnb(T a, T x, T b) + { + // a*x^n+b + return a * exprtk::details::numeric::fast_exp::result(x) + b; + } + + template + struct sf_base + { + typedef typename details::functor_t::Type Type; + typedef typename details::functor_t functor_t; + typedef typename functor_t::qfunc_t quaternary_functor_t; + typedef typename functor_t::tfunc_t trinary_functor_t; + typedef typename functor_t::bfunc_t binary_functor_t; + typedef typename functor_t::ufunc_t unary_functor_t; + }; + + #define define_sfop3(NN,OP0,OP1) \ + template \ + struct sf##NN##_op : public sf_base \ + { \ + typedef typename sf_base::Type Type; \ + static inline T process(Type x, Type y, Type z) \ + { \ + return (OP0); \ + } \ + static inline std::string id() \ + { \ + return OP1; \ + } \ + }; \ + + define_sfop3(00,(x + y) / z ,"(t+t)/t") + define_sfop3(01,(x + y) * z ,"(t+t)*t") + define_sfop3(02,(x + y) - z ,"(t+t)-t") + define_sfop3(03,(x + y) + z ,"(t+t)+t") + define_sfop3(04,(x - y) + z ,"(t-t)+t") + define_sfop3(05,(x - y) / z ,"(t-t)/t") + define_sfop3(06,(x - y) * z ,"(t-t)*t") + define_sfop3(07,(x * y) + z ,"(t*t)+t") + define_sfop3(08,(x * y) - z ,"(t*t)-t") + define_sfop3(09,(x * y) / z ,"(t*t)/t") + define_sfop3(10,(x * y) * z ,"(t*t)*t") + define_sfop3(11,(x / y) + z ,"(t/t)+t") + define_sfop3(12,(x / y) - z ,"(t/t)-t") + define_sfop3(13,(x / y) / z ,"(t/t)/t") + define_sfop3(14,(x / y) * z ,"(t/t)*t") + define_sfop3(15,x / (y + z) ,"t/(t+t)") + define_sfop3(16,x / (y - z) ,"t/(t-t)") + define_sfop3(17,x / (y * z) ,"t/(t*t)") + define_sfop3(18,x / (y / z) ,"t/(t/t)") + define_sfop3(19,x * (y + z) ,"t*(t+t)") + define_sfop3(20,x * (y - z) ,"t*(t-t)") + define_sfop3(21,x * (y * z) ,"t*(t*t)") + define_sfop3(22,x * (y / z) ,"t*(t/t)") + define_sfop3(23,x - (y + z) ,"t-(t+t)") + define_sfop3(24,x - (y - z) ,"t-(t-t)") + define_sfop3(25,x - (y / z) ,"t-(t/t)") + define_sfop3(26,x - (y * z) ,"t-(t*t)") + define_sfop3(27,x + (y * z) ,"t+(t*t)") + define_sfop3(28,x + (y / z) ,"t+(t/t)") + define_sfop3(29,x + (y + z) ,"t+(t+t)") + define_sfop3(30,x + (y - z) ,"t+(t-t)") + define_sfop3(31,(axnb(x,y,z))," ") + define_sfop3(32,(axnb(x,y,z))," ") + define_sfop3(33,(axnb(x,y,z))," ") + define_sfop3(34,(axnb(x,y,z))," ") + define_sfop3(35,(axnb(x,y,z))," ") + define_sfop3(36,(axnb(x,y,z))," ") + define_sfop3(37,(axnb(x,y,z))," ") + define_sfop3(38,(axnb(x,y,z))," ") + define_sfop3(39,x * numeric::log(y) + z,"") + define_sfop3(40,x * numeric::log(y) - z,"") + define_sfop3(41,x * numeric::log10(y) + z,"") + define_sfop3(42,x * numeric::log10(y) - z,"") + define_sfop3(43,x * numeric::sin(y) + z ,"") + define_sfop3(44,x * numeric::sin(y) - z ,"") + define_sfop3(45,x * numeric::cos(y) + z ,"") + define_sfop3(46,x * numeric::cos(y) - z ,"") + define_sfop3(47,details::is_true(x) ? y : z,"") + + #define define_sfop4(NN,OP0,OP1) \ + template \ + struct sf##NN##_op : public sf_base \ + { \ + typedef typename sf_base::Type Type; \ + static inline T process(Type x, Type y, Type z, Type w) \ + { \ + return (OP0); \ + } \ + static inline std::string id() { return OP1; } \ + }; \ + + define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)") + define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)") + define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)") + define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)") + define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)") + define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)") + define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)") + define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)") + define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)") + define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)") + define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)") + define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)") + define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)") + define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)") + define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)") + define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)") + define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)") + define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t") + define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t") + define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t") + define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t") + define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t") + define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t") + define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t") + define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t") + define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)") + define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)") + define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)") + define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)") + define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)") + define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)") + define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)") + define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))") + define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))") + define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))") + define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))") + + define_sfop4(84,(axn(x,y) + axn(z,w)),"") + define_sfop4(85,(axn(x,y) + axn(z,w)),"") + define_sfop4(86,(axn(x,y) + axn(z,w)),"") + define_sfop4(87,(axn(x,y) + axn(z,w)),"") + define_sfop4(88,(axn(x,y) + axn(z,w)),"") + define_sfop4(89,(axn(x,y) + axn(z,w)),"") + define_sfop4(90,(axn(x,y) + axn(z,w)),"") + define_sfop4(91,(axn(x,y) + axn(z,w)),"") + define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"") + define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"") + define_sfop4(94,((x < y) ? z : w),"") + define_sfop4(95,((x <= y) ? z : w),"") + define_sfop4(96,((x > y) ? z : w),"") + define_sfop4(97,((x >= y) ? z : w),"") + define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"") + define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"") + + define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)") + define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)") + define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)") + define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)") + define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)") + define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)") + define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)") + define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)") + define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)") + define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)") + define_sfop4(ext10,((x + y) + (z + w)),"(t+t)+(t+t)") + define_sfop4(ext11,((x + y) * (z - w)),"(t+t)*(t-t)") + define_sfop4(ext12,((x + y) / (z - w)),"(t+t)/(t-t)") + define_sfop4(ext13,((x - y) - (z + w)),"(t-t)-(t+t)") + define_sfop4(ext14,((x - y) + (z + w)),"(t-t)+(t+t)") + define_sfop4(ext15,((x - y) * (z + w)),"(t-t)*(t+t)") + define_sfop4(ext16,((x - y) / (z + w)),"(t-t)/(t+t)") + define_sfop4(ext17,((x * y) - (z + w)),"(t*t)-(t+t)") + define_sfop4(ext18,((x / y) - (z + w)),"(t/t)-(t+t)") + define_sfop4(ext19,((x * y) + (z + w)),"(t*t)+(t+t)") + define_sfop4(ext20,((x / y) + (z + w)),"(t/t)+(t+t)") + define_sfop4(ext21,((x * y) + (z - w)),"(t*t)+(t-t)") + define_sfop4(ext22,((x / y) + (z - w)),"(t/t)+(t-t)") + define_sfop4(ext23,((x * y) - (z - w)),"(t*t)-(t-t)") + define_sfop4(ext24,((x / y) - (z - w)),"(t/t)-(t-t)") + define_sfop4(ext25,((x + y) * (z * w)),"(t+t)*(t*t)") + define_sfop4(ext26,((x + y) * (z / w)),"(t+t)*(t/t)") + define_sfop4(ext27,((x + y) / (z * w)),"(t+t)/(t*t)") + define_sfop4(ext28,((x + y) / (z / w)),"(t+t)/(t/t)") + define_sfop4(ext29,((x - y) / (z * w)),"(t-t)/(t*t)") + define_sfop4(ext30,((x - y) / (z / w)),"(t-t)/(t/t)") + define_sfop4(ext31,((x - y) * (z * w)),"(t-t)*(t*t)") + define_sfop4(ext32,((x - y) * (z / w)),"(t-t)*(t/t)") + define_sfop4(ext33,((x * y) * (z + w)),"(t*t)*(t+t)") + define_sfop4(ext34,((x / y) * (z + w)),"(t/t)*(t+t)") + define_sfop4(ext35,((x * y) / (z + w)),"(t*t)/(t+t)") + define_sfop4(ext36,((x / y) / (z + w)),"(t/t)/(t+t)") + define_sfop4(ext37,((x * y) / (z - w)),"(t*t)/(t-t)") + define_sfop4(ext38,((x / y) / (z - w)),"(t/t)/(t-t)") + define_sfop4(ext39,((x * y) * (z - w)),"(t*t)*(t-t)") + define_sfop4(ext40,((x * y) / (z * w)),"(t*t)/(t*t)") + define_sfop4(ext41,((x / y) * (z / w)),"(t/t)*(t/t)") + define_sfop4(ext42,((x / y) * (z - w)),"(t/t)*(t-t)") + define_sfop4(ext43,((x * y) * (z * w)),"(t*t)*(t*t)") + define_sfop4(ext44,(x + (y * (z / w))),"t+(t*(t/t))") + define_sfop4(ext45,(x - (y * (z / w))),"t-(t*(t/t))") + define_sfop4(ext46,(x + (y / (z * w))),"t+(t/(t*t))") + define_sfop4(ext47,(x - (y / (z * w))),"t-(t/(t*t))") + define_sfop4(ext48,(((x - y) - z) * w),"((t-t)-t)*t") + define_sfop4(ext49,(((x - y) - z) / w),"((t-t)-t)/t") + define_sfop4(ext50,(((x - y) + z) * w),"((t-t)+t)*t") + define_sfop4(ext51,(((x - y) + z) / w),"((t-t)+t)/t") + define_sfop4(ext52,((x + (y - z)) * w),"(t+(t-t))*t") + define_sfop4(ext53,((x + (y - z)) / w),"(t+(t-t))/t") + define_sfop4(ext54,((x + y) / (z + w)),"(t+t)/(t+t)") + define_sfop4(ext55,((x - y) / (z - w)),"(t-t)/(t-t)") + define_sfop4(ext56,((x + y) * (z + w)),"(t+t)*(t+t)") + define_sfop4(ext57,((x - y) * (z - w)),"(t-t)*(t-t)") + define_sfop4(ext58,((x - y) + (z - w)),"(t-t)+(t-t)") + define_sfop4(ext59,((x - y) - (z - w)),"(t-t)-(t-t)") + define_sfop4(ext60,((x / y) + (z * w)),"(t/t)+(t*t)") + define_sfop4(ext61,(((x * y) * z) / w),"((t*t)*t)/t") + + #undef define_sfop3 + #undef define_sfop4 + + template + class sf3_node : public trinary_node + { + public: + + typedef expression_node* expression_ptr; + + sf3_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1, + expression_ptr branch2) + : trinary_node(opr, branch0, branch1, branch2) + {} + + inline T value() const + { + const T x = trinary_node::branch_[0].first->value(); + const T y = trinary_node::branch_[1].first->value(); + const T z = trinary_node::branch_[2].first->value(); + + return SpecialFunction::process(x, y, z); + } + }; + + template + class sf4_node : public quaternary_node + { + public: + + typedef expression_node* expression_ptr; + + sf4_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1, + expression_ptr branch2, + expression_ptr branch3) + : quaternary_node(opr, branch0, branch1, branch2, branch3) + {} + + inline T value() const + { + const T x = quaternary_node::branch_[0].first->value(); + const T y = quaternary_node::branch_[1].first->value(); + const T z = quaternary_node::branch_[2].first->value(); + const T w = quaternary_node::branch_[3].first->value(); + + return SpecialFunction::process(x, y, z, w); + } + }; + + template + class sf3_var_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + sf3_var_node(const T& v0, const T& v1, const T& v2) + : v0_(v0), + v1_(v1), + v2_(v2) + {} + + inline T value() const + { + return SpecialFunction::process(v0_, v1_, v2_); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_trinary; + } + + private: + + sf3_var_node(sf3_var_node&); + sf3_var_node& operator=(sf3_var_node&); + + const T& v0_; + const T& v1_; + const T& v2_; + }; + + template + class sf4_var_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3) + : v0_(v0), + v1_(v1), + v2_(v2), + v3_(v3) + {} + + inline T value() const + { + return SpecialFunction::process(v0_, v1_, v2_, v3_); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_trinary; + } + + private: + + sf4_var_node(sf4_var_node&); + sf4_var_node& operator=(sf4_var_node&); + + const T& v0_; + const T& v1_; + const T& v2_; + const T& v3_; + }; + + template + class vararg_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + template class Sequence> + explicit vararg_node(const Sequence& arg_list) + { + arg_list_ .resize(arg_list.size()); + delete_branch_.resize(arg_list.size()); + + for (std::size_t i = 0; i < arg_list.size(); ++i) + { + if (arg_list[i]) + { + arg_list_[i] = arg_list[i]; + delete_branch_[i] = static_cast(branch_deletable(arg_list_[i]) ? 1 : 0); + } + else + { + arg_list_.clear(); + delete_branch_.clear(); + return; + } + } + } + + ~vararg_node() + { + for (std::size_t i = 0; i < arg_list_.size(); ++i) + { + if (arg_list_[i] && delete_branch_[i]) + { + destroy_node(arg_list_[i]); + } + } + } + + inline T value() const + { + return VarArgFunction::process(arg_list_); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_vararg; + } + + private: + + std::vector arg_list_; + std::vector delete_branch_; + }; + + template + class vararg_varnode : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + template class Sequence> + explicit vararg_varnode(const Sequence& arg_list) + { + arg_list_.resize(arg_list.size()); + + for (std::size_t i = 0; i < arg_list.size(); ++i) + { + if (arg_list[i] && is_variable_node(arg_list[i])) + { + variable_node* var_node_ptr = static_cast*>(arg_list[i]); + arg_list_[i] = (&var_node_ptr->ref()); + } + else + { + arg_list_.clear(); + return; + } + } + } + + inline T value() const + { + if (!arg_list_.empty()) + return VarArgFunction::process(arg_list_); + else + return std::numeric_limits::quiet_NaN(); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_vararg; + } + + private: + + std::vector arg_list_; + }; + + template + class vectorize_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + explicit vectorize_node(const expression_ptr v) + : ivec_ptr_(0), + v_(v), + v_deletable_(branch_deletable(v_)) + { + if (is_ivector_node(v)) + { + ivec_ptr_ = dynamic_cast*>(v); + } + else + ivec_ptr_ = 0; + } + + ~vectorize_node() + { + if (v_ && v_deletable_) + { + destroy_node(v_); + } + } + + inline T value() const + { + if (ivec_ptr_) + { + v_->value(); + return VecFunction::process(ivec_ptr_); + } + else + return std::numeric_limits::quiet_NaN(); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_vecfunc; + } + + private: + + vector_interface* ivec_ptr_; + expression_ptr v_; + const bool v_deletable_; + }; + + template + class assignment_node : public binary_node + { + public: + + typedef expression_node* expression_ptr; + + assignment_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1), + var_node_ptr_(0) + { + if (is_variable_node(binary_node::branch_[0].first)) + { + var_node_ptr_ = static_cast*>(binary_node::branch_[0].first); + } + } + + inline T value() const + { + if (var_node_ptr_) + { + T& result = var_node_ptr_->ref(); + + result = binary_node::branch_[1].first->value(); + + return result; + } + else + return std::numeric_limits::quiet_NaN(); + } + + private: + + variable_node* var_node_ptr_; + }; + + template + class assignment_vec_elem_node : public binary_node + { + public: + + typedef expression_node* expression_ptr; + + assignment_vec_elem_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1), + vec_node_ptr_(0) + { + if (is_vector_elem_node(binary_node::branch_[0].first)) + { + vec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); + } + } + + inline T value() const + { + if (vec_node_ptr_) + { + T& result = vec_node_ptr_->ref(); + + result = binary_node::branch_[1].first->value(); + + return result; + } + else + return std::numeric_limits::quiet_NaN(); + } + + private: + + vector_elem_node* vec_node_ptr_; + }; + + template + class assignment_rebasevec_elem_node : public binary_node + { + public: + + typedef expression_node* expression_ptr; + + assignment_rebasevec_elem_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1), + rbvec_node_ptr_(0) + { + if (is_rebasevector_elem_node(binary_node::branch_[0].first)) + { + rbvec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); + } + } + + inline T value() const + { + if (rbvec_node_ptr_) + { + T& result = rbvec_node_ptr_->ref(); + + result = binary_node::branch_[1].first->value(); + + return result; + } + else + return std::numeric_limits::quiet_NaN(); + } + + private: + + rebasevector_elem_node* rbvec_node_ptr_; + }; + + template + class assignment_rebasevec_celem_node : public binary_node + { + public: + + typedef expression_node* expression_ptr; + + assignment_rebasevec_celem_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1), + rbvec_node_ptr_(0) + { + if (is_rebasevector_celem_node(binary_node::branch_[0].first)) + { + rbvec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); + } + } + + inline T value() const + { + if (rbvec_node_ptr_) + { + T& result = rbvec_node_ptr_->ref(); + + result = binary_node::branch_[1].first->value(); + + return result; + } + else + return std::numeric_limits::quiet_NaN(); + } + + private: + + rebasevector_celem_node* rbvec_node_ptr_; + }; + + template + class assignment_vec_node : public binary_node , + public vector_interface + { + public: + + typedef expression_node* expression_ptr; + typedef vector_node* vector_node_ptr; + typedef vec_data_store vds_t; + + assignment_vec_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1), + vec_node_ptr_(0) + { + if (is_vector_node(binary_node::branch_[0].first)) + { + vec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); + vds() = vec_node_ptr_->vds(); + } + } + + inline T value() const + { + if (vec_node_ptr_) + { + const T v = binary_node::branch_[1].first->value(); + + T* vec = vds().data(); + + loop_unroll::details lud(size()); + const T* upper_bound = vec + lud.upper_bound; + + while (vec < upper_bound) + { + #define exprtk_loop(N) \ + vec[N] = v; \ + + exprtk_loop( 0) exprtk_loop( 1) + exprtk_loop( 2) exprtk_loop( 3) + #ifndef exprtk_disable_superscalar_unroll + exprtk_loop( 4) exprtk_loop( 5) + exprtk_loop( 6) exprtk_loop( 7) + exprtk_loop( 8) exprtk_loop( 9) + exprtk_loop(10) exprtk_loop(11) + exprtk_loop(12) exprtk_loop(13) + exprtk_loop(14) exprtk_loop(15) + #endif + + vec += lud.batch_size; + } + + exprtk_disable_fallthrough_begin + switch (lud.remainder) + { + #define case_stmt(N) \ + case N : *vec++ = v; \ + + #ifndef exprtk_disable_superscalar_unroll + case_stmt(15) case_stmt(14) + case_stmt(13) case_stmt(12) + case_stmt(11) case_stmt(10) + case_stmt( 9) case_stmt( 8) + case_stmt( 7) case_stmt( 6) + case_stmt( 5) case_stmt( 4) + #endif + case_stmt( 3) case_stmt( 2) + case_stmt( 1) + } + exprtk_disable_fallthrough_end + + #undef exprtk_loop + #undef case_stmt + + return vec_node_ptr_->value(); + } + else + return std::numeric_limits::quiet_NaN(); + } + + vector_node_ptr vec() const + { + return vec_node_ptr_; + } + + vector_node_ptr vec() + { + return vec_node_ptr_; + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_vecvalass; + } + + std::size_t size() const + { + return vds().size(); + } + + vds_t& vds() + { + return vds_; + } + + const vds_t& vds() const + { + return vds_; + } + + private: + + vector_node* vec_node_ptr_; + vds_t vds_; + }; + + template + class assignment_vecvec_node : public binary_node , + public vector_interface + { + public: + + typedef expression_node* expression_ptr; + typedef vector_node* vector_node_ptr; + typedef vec_data_store vds_t; + + assignment_vecvec_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1), + vec0_node_ptr_(0), + vec1_node_ptr_(0), + initialised_(false), + src_is_ivec_(false) + { + if (is_vector_node(binary_node::branch_[0].first)) + { + vec0_node_ptr_ = static_cast*>(binary_node::branch_[0].first); + vds() = vec0_node_ptr_->vds(); + } + + if (is_vector_node(binary_node::branch_[1].first)) + { + vec1_node_ptr_ = static_cast*>(binary_node::branch_[1].first); + vds_t::match_sizes(vds(),vec1_node_ptr_->vds()); + } + else if (is_ivector_node(binary_node::branch_[1].first)) + { + vector_interface* vi = reinterpret_cast*>(0); + + if (0 != (vi = dynamic_cast*>(binary_node::branch_[1].first))) + { + vec1_node_ptr_ = vi->vec(); + + if (!vi->side_effect()) + { + vi->vds() = vds(); + src_is_ivec_ = true; + } + else + vds_t::match_sizes(vds(),vi->vds()); + } + } + + initialised_ = (vec0_node_ptr_ && vec1_node_ptr_); + } + + inline T value() const + { + if (initialised_) + { + binary_node::branch_[1].first->value(); + + if (src_is_ivec_) + return vec0_node_ptr_->value(); + + T* vec0 = vec0_node_ptr_->vds().data(); + T* vec1 = vec1_node_ptr_->vds().data(); + + loop_unroll::details lud(size()); + const T* upper_bound = vec0 + lud.upper_bound; + + while (vec0 < upper_bound) + { + #define exprtk_loop(N) \ + vec0[N] = vec1[N]; \ + + exprtk_loop( 0) exprtk_loop( 1) + exprtk_loop( 2) exprtk_loop( 3) + #ifndef exprtk_disable_superscalar_unroll + exprtk_loop( 4) exprtk_loop( 5) + exprtk_loop( 6) exprtk_loop( 7) + exprtk_loop( 8) exprtk_loop( 9) + exprtk_loop(10) exprtk_loop(11) + exprtk_loop(12) exprtk_loop(13) + exprtk_loop(14) exprtk_loop(15) + #endif + + vec0 += lud.batch_size; + vec1 += lud.batch_size; + } + + exprtk_disable_fallthrough_begin + switch (lud.remainder) + { + #define case_stmt(N) \ + case N : *vec0++ = *vec1++; \ + + #ifndef exprtk_disable_superscalar_unroll + case_stmt(15) case_stmt(14) + case_stmt(13) case_stmt(12) + case_stmt(11) case_stmt(10) + case_stmt( 9) case_stmt( 8) + case_stmt( 7) case_stmt( 6) + case_stmt( 5) case_stmt( 4) + #endif + case_stmt( 3) case_stmt( 2) + case_stmt( 1) + } + exprtk_disable_fallthrough_end + + #undef exprtk_loop + #undef case_stmt + + return vec0_node_ptr_->value(); + } + else + return std::numeric_limits::quiet_NaN(); + } + + vector_node_ptr vec() const + { + return vec0_node_ptr_; + } + + vector_node_ptr vec() + { + return vec0_node_ptr_; + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_vecvecass; + } + + std::size_t size() const + { + return vds().size(); + } + + vds_t& vds() + { + return vds_; + } + + const vds_t& vds() const + { + return vds_; + } + + private: + + vector_node* vec0_node_ptr_; + vector_node* vec1_node_ptr_; + bool initialised_; + bool src_is_ivec_; + vds_t vds_; + }; + + template + class assignment_op_node : public binary_node + { + public: + + typedef expression_node* expression_ptr; + + assignment_op_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1), + var_node_ptr_(0) + { + if (is_variable_node(binary_node::branch_[0].first)) + { + var_node_ptr_ = static_cast*>(binary_node::branch_[0].first); + } + } + + inline T value() const + { + if (var_node_ptr_) + { + T& v = var_node_ptr_->ref(); + v = Operation::process(v,binary_node::branch_[1].first->value()); + + return v; + } + else + return std::numeric_limits::quiet_NaN(); + } + + private: + + variable_node* var_node_ptr_; + }; + + template + class assignment_vec_elem_op_node : public binary_node + { + public: + + typedef expression_node* expression_ptr; + + assignment_vec_elem_op_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1), + vec_node_ptr_(0) + { + if (is_vector_elem_node(binary_node::branch_[0].first)) + { + vec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); + } + } + + inline T value() const + { + if (vec_node_ptr_) + { + T& v = vec_node_ptr_->ref(); + v = Operation::process(v,binary_node::branch_[1].first->value()); + + return v; + } + else + return std::numeric_limits::quiet_NaN(); + } + + private: + + vector_elem_node* vec_node_ptr_; + }; + + template + class assignment_rebasevec_elem_op_node : public binary_node + { + public: + + typedef expression_node* expression_ptr; + + assignment_rebasevec_elem_op_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1), + rbvec_node_ptr_(0) + { + if (is_rebasevector_elem_node(binary_node::branch_[0].first)) + { + rbvec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); + } + } + + inline T value() const + { + if (rbvec_node_ptr_) + { + T& v = rbvec_node_ptr_->ref(); + v = Operation::process(v,binary_node::branch_[1].first->value()); + + return v; + } + else + return std::numeric_limits::quiet_NaN(); + } + + private: + + rebasevector_elem_node* rbvec_node_ptr_; + }; + + template + class assignment_rebasevec_celem_op_node : public binary_node + { + public: + + typedef expression_node* expression_ptr; + + assignment_rebasevec_celem_op_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1), + rbvec_node_ptr_(0) + { + if (is_rebasevector_celem_node(binary_node::branch_[0].first)) + { + rbvec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); + } + } + + inline T value() const + { + if (rbvec_node_ptr_) + { + T& v = rbvec_node_ptr_->ref(); + v = Operation::process(v,binary_node::branch_[1].first->value()); + + return v; + } + else + return std::numeric_limits::quiet_NaN(); + } + + private: + + rebasevector_celem_node* rbvec_node_ptr_; + }; + + template + class assignment_vec_op_node : public binary_node , + public vector_interface + { + public: + + typedef expression_node* expression_ptr; + typedef vector_node* vector_node_ptr; + typedef vec_data_store vds_t; + + assignment_vec_op_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1), + vec_node_ptr_(0) + { + if (is_vector_node(binary_node::branch_[0].first)) + { + vec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); + vds() = vec_node_ptr_->vds(); + } + } + + inline T value() const + { + if (vec_node_ptr_) + { + const T v = binary_node::branch_[1].first->value(); + + T* vec = vds().data(); + + loop_unroll::details lud(size()); + const T* upper_bound = vec + lud.upper_bound; + + while (vec < upper_bound) + { + #define exprtk_loop(N) \ + Operation::assign(vec[N],v); \ + + exprtk_loop( 0) exprtk_loop( 1) + exprtk_loop( 2) exprtk_loop( 3) + #ifndef exprtk_disable_superscalar_unroll + exprtk_loop( 4) exprtk_loop( 5) + exprtk_loop( 6) exprtk_loop( 7) + exprtk_loop( 8) exprtk_loop( 9) + exprtk_loop(10) exprtk_loop(11) + exprtk_loop(12) exprtk_loop(13) + exprtk_loop(14) exprtk_loop(15) + #endif + + vec += lud.batch_size; + } + + exprtk_disable_fallthrough_begin + switch (lud.remainder) + { + #define case_stmt(N) \ + case N : Operation::assign(*vec++,v); \ + + #ifndef exprtk_disable_superscalar_unroll + case_stmt(15) case_stmt(14) + case_stmt(13) case_stmt(12) + case_stmt(11) case_stmt(10) + case_stmt( 9) case_stmt( 8) + case_stmt( 7) case_stmt( 6) + case_stmt( 5) case_stmt( 4) + #endif + case_stmt( 3) case_stmt( 2) + case_stmt( 1) + } + exprtk_disable_fallthrough_end + + + #undef exprtk_loop + #undef case_stmt + + return vec_node_ptr_->value(); + } + else + return std::numeric_limits::quiet_NaN(); + } + + vector_node_ptr vec() const + { + return vec_node_ptr_; + } + + vector_node_ptr vec() + { + return vec_node_ptr_; + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_vecopvalass; + } + + std::size_t size() const + { + return vds().size(); + } + + vds_t& vds() + { + return vds_; + } + + const vds_t& vds() const + { + return vds_; + } + + bool side_effect() const + { + return true; + } + + private: + + vector_node* vec_node_ptr_; + vds_t vds_; + }; + + template + class assignment_vecvec_op_node : public binary_node , + public vector_interface + { + public: + + typedef expression_node* expression_ptr; + typedef vector_node* vector_node_ptr; + typedef vec_data_store vds_t; + + assignment_vecvec_op_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1), + vec0_node_ptr_(0), + vec1_node_ptr_(0), + initialised_(false) + { + if (is_vector_node(binary_node::branch_[0].first)) + { + vec0_node_ptr_ = static_cast*>(binary_node::branch_[0].first); + vds() = vec0_node_ptr_->vds(); + } + + if (is_vector_node(binary_node::branch_[1].first)) + { + vec1_node_ptr_ = static_cast*>(binary_node::branch_[1].first); + vec1_node_ptr_->vds() = vds(); + } + else if (is_ivector_node(binary_node::branch_[1].first)) + { + vector_interface* vi = reinterpret_cast*>(0); + + if (0 != (vi = dynamic_cast*>(binary_node::branch_[1].first))) + { + vec1_node_ptr_ = vi->vec(); + vec1_node_ptr_->vds() = vds(); + } + else + vds_t::match_sizes(vds(),vec1_node_ptr_->vds()); + } + + initialised_ = (vec0_node_ptr_ && vec1_node_ptr_); + } + + inline T value() const + { + if (initialised_) + { + binary_node::branch_[0].first->value(); + binary_node::branch_[1].first->value(); + + T* vec0 = vec0_node_ptr_->vds().data(); + const T* vec1 = vec1_node_ptr_->vds().data(); + + loop_unroll::details lud(size()); + const T* upper_bound = vec0 + lud.upper_bound; + + while (vec0 < upper_bound) + { + #define exprtk_loop(N) \ + vec0[N] = Operation::process(vec0[N], vec1[N]); \ + + exprtk_loop( 0) exprtk_loop( 1) + exprtk_loop( 2) exprtk_loop( 3) + #ifndef exprtk_disable_superscalar_unroll + exprtk_loop( 4) exprtk_loop( 5) + exprtk_loop( 6) exprtk_loop( 7) + exprtk_loop( 8) exprtk_loop( 9) + exprtk_loop(10) exprtk_loop(11) + exprtk_loop(12) exprtk_loop(13) + exprtk_loop(14) exprtk_loop(15) + #endif + + vec0 += lud.batch_size; + vec1 += lud.batch_size; + } + + int i = 0; + + exprtk_disable_fallthrough_begin + switch (lud.remainder) + { + #define case_stmt(N) \ + case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ + + #ifndef exprtk_disable_superscalar_unroll + case_stmt(15) case_stmt(14) + case_stmt(13) case_stmt(12) + case_stmt(11) case_stmt(10) + case_stmt( 9) case_stmt( 8) + case_stmt( 7) case_stmt( 6) + case_stmt( 5) case_stmt( 4) + #endif + case_stmt( 3) case_stmt( 2) + case_stmt( 1) + } + exprtk_disable_fallthrough_end + + #undef exprtk_loop + #undef case_stmt + + return vec0_node_ptr_->value(); + } + else + return std::numeric_limits::quiet_NaN(); + } + + vector_node_ptr vec() const + { + return vec0_node_ptr_; + } + + vector_node_ptr vec() + { + return vec0_node_ptr_; + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_vecopvecass; + } + + std::size_t size() const + { + return vds().size(); + } + + vds_t& vds() + { + return vds_; + } + + const vds_t& vds() const + { + return vds_; + } + + bool side_effect() const + { + return true; + } + + private: + + vector_node* vec0_node_ptr_; + vector_node* vec1_node_ptr_; + bool initialised_; + vds_t vds_; + }; + + template + class vec_binop_vecvec_node : public binary_node , + public vector_interface + { + public: + + typedef expression_node* expression_ptr; + typedef vector_node* vector_node_ptr; + typedef vector_holder* vector_holder_ptr; + typedef vec_data_store vds_t; + + vec_binop_vecvec_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1), + vec0_node_ptr_(0), + vec1_node_ptr_(0), + temp_ (0), + temp_vec_node_(0), + initialised_(false) + { + bool v0_is_ivec = false; + bool v1_is_ivec = false; + + if (is_vector_node(binary_node::branch_[0].first)) + { + vec0_node_ptr_ = static_cast(binary_node::branch_[0].first); + } + else if (is_ivector_node(binary_node::branch_[0].first)) + { + vector_interface* vi = reinterpret_cast*>(0); + + if (0 != (vi = dynamic_cast*>(binary_node::branch_[0].first))) + { + vec0_node_ptr_ = vi->vec(); + v0_is_ivec = true; + } + } + + if (is_vector_node(binary_node::branch_[1].first)) + { + vec1_node_ptr_ = static_cast(binary_node::branch_[1].first); + } + else if (is_ivector_node(binary_node::branch_[1].first)) + { + vector_interface* vi = reinterpret_cast*>(0); + + if (0 != (vi = dynamic_cast*>(binary_node::branch_[1].first))) + { + vec1_node_ptr_ = vi->vec(); + v1_is_ivec = true; + } + } + + if (vec0_node_ptr_ && vec1_node_ptr_) + { + vector_holder& vec0 = vec0_node_ptr_->vec_holder(); + vector_holder& vec1 = vec1_node_ptr_->vec_holder(); + + if (v0_is_ivec && (vec0.size() <= vec1.size())) + vds_ = vds_t(vec0_node_ptr_->vds()); + else if (v1_is_ivec && (vec1.size() <= vec0.size())) + vds_ = vds_t(vec1_node_ptr_->vds()); + else + vds_ = vds_t(std::min(vec0.size(),vec1.size())); + + temp_ = new vector_holder(vds().data(),vds().size()); + temp_vec_node_ = new vector_node (vds(),temp_); + + initialised_ = true; + } + } + + ~vec_binop_vecvec_node() + { + delete temp_; + delete temp_vec_node_; + } + + inline T value() const + { + if (initialised_) + { + binary_node::branch_[0].first->value(); + binary_node::branch_[1].first->value(); + + const T* vec0 = vec0_node_ptr_->vds().data(); + const T* vec1 = vec1_node_ptr_->vds().data(); + T* vec2 = vds().data(); + + loop_unroll::details lud(size()); + const T* upper_bound = vec2 + lud.upper_bound; + + while (vec2 < upper_bound) + { + #define exprtk_loop(N) \ + vec2[N] = Operation::process(vec0[N], vec1[N]); \ + + exprtk_loop( 0) exprtk_loop( 1) + exprtk_loop( 2) exprtk_loop( 3) + #ifndef exprtk_disable_superscalar_unroll + exprtk_loop( 4) exprtk_loop( 5) + exprtk_loop( 6) exprtk_loop( 7) + exprtk_loop( 8) exprtk_loop( 9) + exprtk_loop(10) exprtk_loop(11) + exprtk_loop(12) exprtk_loop(13) + exprtk_loop(14) exprtk_loop(15) + #endif + + vec0 += lud.batch_size; + vec1 += lud.batch_size; + vec2 += lud.batch_size; + } + + int i = 0; + + exprtk_disable_fallthrough_begin + switch (lud.remainder) + { + #define case_stmt(N) \ + case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ + + #ifndef exprtk_disable_superscalar_unroll + case_stmt(15) case_stmt(14) + case_stmt(13) case_stmt(12) + case_stmt(11) case_stmt(10) + case_stmt( 9) case_stmt( 8) + case_stmt( 7) case_stmt( 6) + case_stmt( 5) case_stmt( 4) + #endif + case_stmt( 3) case_stmt( 2) + case_stmt( 1) + } + exprtk_disable_fallthrough_end + + #undef exprtk_loop + #undef case_stmt + + return (vds().data())[0]; + } + else + return std::numeric_limits::quiet_NaN(); + } + + vector_node_ptr vec() const + { + return temp_vec_node_; + } + + vector_node_ptr vec() + { + return temp_vec_node_; + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_vecvecarith; + } + + std::size_t size() const + { + return vds_.size(); + } + + vds_t& vds() + { + return vds_; + } + + const vds_t& vds() const + { + return vds_; + } + + private: + + vector_node_ptr vec0_node_ptr_; + vector_node_ptr vec1_node_ptr_; + vector_holder_ptr temp_; + vector_node_ptr temp_vec_node_; + bool initialised_; + vds_t vds_; + }; + + template + class vec_binop_vecval_node : public binary_node , + public vector_interface + { + public: + + typedef expression_node* expression_ptr; + typedef vector_node* vector_node_ptr; + typedef vector_holder* vector_holder_ptr; + typedef vec_data_store vds_t; + + vec_binop_vecval_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1), + vec0_node_ptr_(0), + temp_ (0), + temp_vec_node_(0) + { + bool v0_is_ivec = false; + + if (is_vector_node(binary_node::branch_[0].first)) + { + vec0_node_ptr_ = static_cast(binary_node::branch_[0].first); + } + else if (is_ivector_node(binary_node::branch_[0].first)) + { + vector_interface* vi = reinterpret_cast*>(0); + + if (0 != (vi = dynamic_cast*>(binary_node::branch_[0].first))) + { + vec0_node_ptr_ = vi->vec(); + v0_is_ivec = true; + } + } + + if (vec0_node_ptr_) + { + if (v0_is_ivec) + vds() = vec0_node_ptr_->vds(); + else + vds() = vds_t(vec0_node_ptr_->size()); + + temp_ = new vector_holder(vds()); + temp_vec_node_ = new vector_node (vds(),temp_); + } + } + + ~vec_binop_vecval_node() + { + delete temp_; + delete temp_vec_node_; + } + + inline T value() const + { + if (vec0_node_ptr_) + { + binary_node::branch_[0].first->value(); + const T v = binary_node::branch_[1].first->value(); + + const T* vec0 = vec0_node_ptr_->vds().data(); + T* vec1 = vds().data(); + + loop_unroll::details lud(size()); + const T* upper_bound = vec0 + lud.upper_bound; + + while (vec0 < upper_bound) + { + #define exprtk_loop(N) \ + vec1[N] = Operation::process(vec0[N], v); \ + + exprtk_loop( 0) exprtk_loop( 1) + exprtk_loop( 2) exprtk_loop( 3) + #ifndef exprtk_disable_superscalar_unroll + exprtk_loop( 4) exprtk_loop( 5) + exprtk_loop( 6) exprtk_loop( 7) + exprtk_loop( 8) exprtk_loop( 9) + exprtk_loop(10) exprtk_loop(11) + exprtk_loop(12) exprtk_loop(13) + exprtk_loop(14) exprtk_loop(15) + #endif + + vec0 += lud.batch_size; + vec1 += lud.batch_size; + } + + int i = 0; + + exprtk_disable_fallthrough_begin + switch (lud.remainder) + { + #define case_stmt(N) \ + case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \ + + #ifndef exprtk_disable_superscalar_unroll + case_stmt(15) case_stmt(14) + case_stmt(13) case_stmt(12) + case_stmt(11) case_stmt(10) + case_stmt( 9) case_stmt( 8) + case_stmt( 7) case_stmt( 6) + case_stmt( 5) case_stmt( 4) + #endif + case_stmt( 3) case_stmt( 2) + case_stmt( 1) + } + exprtk_disable_fallthrough_end + + #undef exprtk_loop + #undef case_stmt + + return (vds().data())[0]; + } + else + return std::numeric_limits::quiet_NaN(); + } + + vector_node_ptr vec() const + { + return temp_vec_node_; + } + + vector_node_ptr vec() + { + return temp_vec_node_; + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_vecvalarith; + } + + std::size_t size() const + { + return vds().size(); + } + + vds_t& vds() + { + return vds_; + } + + const vds_t& vds() const + { + return vds_; + } + + private: + + vector_node_ptr vec0_node_ptr_; + vector_holder_ptr temp_; + vector_node_ptr temp_vec_node_; + vds_t vds_; + }; + + template + class vec_binop_valvec_node : public binary_node , + public vector_interface + { + public: + + typedef expression_node* expression_ptr; + typedef vector_node* vector_node_ptr; + typedef vector_holder* vector_holder_ptr; + typedef vec_data_store vds_t; + + vec_binop_valvec_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1), + vec1_node_ptr_(0), + temp_ (0), + temp_vec_node_(0) + { + bool v1_is_ivec = false; + + if (is_vector_node(binary_node::branch_[1].first)) + { + vec1_node_ptr_ = static_cast(binary_node::branch_[1].first); + } + else if (is_ivector_node(binary_node::branch_[1].first)) + { + vector_interface* vi = reinterpret_cast*>(0); + + if (0 != (vi = dynamic_cast*>(binary_node::branch_[1].first))) + { + vec1_node_ptr_ = vi->vec(); + v1_is_ivec = true; + } + } + + if (vec1_node_ptr_) + { + if (v1_is_ivec) + vds() = vec1_node_ptr_->vds(); + else + vds() = vds_t(vec1_node_ptr_->size()); + + temp_ = new vector_holder(vds()); + temp_vec_node_ = new vector_node (vds(),temp_); + } + } + + ~vec_binop_valvec_node() + { + delete temp_; + delete temp_vec_node_; + } + + inline T value() const + { + if (vec1_node_ptr_) + { + const T v = binary_node::branch_[0].first->value(); + binary_node::branch_[1].first->value(); + + T* vec0 = vds().data(); + const T* vec1 = vec1_node_ptr_->vds().data(); + + loop_unroll::details lud(size()); + const T* upper_bound = vec0 + lud.upper_bound; + + while (vec0 < upper_bound) + { + #define exprtk_loop(N) \ + vec0[N] = Operation::process(v, vec1[N]); \ + + exprtk_loop( 0) exprtk_loop( 1) + exprtk_loop( 2) exprtk_loop( 3) + #ifndef exprtk_disable_superscalar_unroll + exprtk_loop( 4) exprtk_loop( 5) + exprtk_loop( 6) exprtk_loop( 7) + exprtk_loop( 8) exprtk_loop( 9) + exprtk_loop(10) exprtk_loop(11) + exprtk_loop(12) exprtk_loop(13) + exprtk_loop(14) exprtk_loop(15) + #endif + + vec0 += lud.batch_size; + vec1 += lud.batch_size; + } + + int i = 0; + + exprtk_disable_fallthrough_begin + switch (lud.remainder) + { + #define case_stmt(N) \ + case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \ + + #ifndef exprtk_disable_superscalar_unroll + case_stmt(15) case_stmt(14) + case_stmt(13) case_stmt(12) + case_stmt(11) case_stmt(10) + case_stmt( 9) case_stmt( 8) + case_stmt( 7) case_stmt( 6) + case_stmt( 5) case_stmt( 4) + #endif + case_stmt( 3) case_stmt( 2) + case_stmt( 1) + } + exprtk_disable_fallthrough_end + + #undef exprtk_loop + #undef case_stmt + + return (vds().data())[0]; + } + else + return std::numeric_limits::quiet_NaN(); + } + + vector_node_ptr vec() const + { + return temp_vec_node_; + } + + vector_node_ptr vec() + { + return temp_vec_node_; + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_vecvalarith; + } + + std::size_t size() const + { + return vds().size(); + } + + vds_t& vds() + { + return vds_; + } + + const vds_t& vds() const + { + return vds_; + } + + private: + + vector_node_ptr vec1_node_ptr_; + vector_holder_ptr temp_; + vector_node_ptr temp_vec_node_; + vds_t vds_; + }; + + template + class unary_vector_node : public unary_node , + public vector_interface + { + public: + + typedef expression_node* expression_ptr; + typedef vector_node* vector_node_ptr; + typedef vector_holder* vector_holder_ptr; + typedef vec_data_store vds_t; + + unary_vector_node(const operator_type& opr, expression_ptr branch0) + : unary_node(opr, branch0), + vec0_node_ptr_(0), + temp_ (0), + temp_vec_node_(0) + { + bool vec0_is_ivec = false; + + if (is_vector_node(unary_node::branch_)) + { + vec0_node_ptr_ = static_cast(unary_node::branch_); + } + else if (is_ivector_node(unary_node::branch_)) + { + vector_interface* vi = reinterpret_cast*>(0); + + if (0 != (vi = dynamic_cast*>(unary_node::branch_))) + { + vec0_node_ptr_ = vi->vec(); + vec0_is_ivec = true; + } + } + + if (vec0_node_ptr_) + { + if (vec0_is_ivec) + vds_ = vec0_node_ptr_->vds(); + else + vds_ = vds_t(vec0_node_ptr_->size()); + + temp_ = new vector_holder(vds()); + temp_vec_node_ = new vector_node (vds(),temp_); + } + } + + ~unary_vector_node() + { + delete temp_; + delete temp_vec_node_; + } + + inline T value() const + { + unary_node::branch_->value(); + + if (vec0_node_ptr_) + { + const T* vec0 = vec0_node_ptr_->vds().data(); + T* vec1 = vds().data(); + + loop_unroll::details lud(size()); + const T* upper_bound = vec0 + lud.upper_bound; + + while (vec0 < upper_bound) + { + #define exprtk_loop(N) \ + vec1[N] = Operation::process(vec0[N]); \ + + exprtk_loop( 0) exprtk_loop( 1) + exprtk_loop( 2) exprtk_loop( 3) + #ifndef exprtk_disable_superscalar_unroll + exprtk_loop( 4) exprtk_loop( 5) + exprtk_loop( 6) exprtk_loop( 7) + exprtk_loop( 8) exprtk_loop( 9) + exprtk_loop(10) exprtk_loop(11) + exprtk_loop(12) exprtk_loop(13) + exprtk_loop(14) exprtk_loop(15) + #endif + + vec0 += lud.batch_size; + vec1 += lud.batch_size; + } + + int i = 0; + + exprtk_disable_fallthrough_begin + switch (lud.remainder) + { + #define case_stmt(N) \ + case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \ + + #ifndef exprtk_disable_superscalar_unroll + case_stmt(15) case_stmt(14) + case_stmt(13) case_stmt(12) + case_stmt(11) case_stmt(10) + case_stmt( 9) case_stmt( 8) + case_stmt( 7) case_stmt( 6) + case_stmt( 5) case_stmt( 4) + #endif + case_stmt( 3) case_stmt( 2) + case_stmt( 1) + } + exprtk_disable_fallthrough_end + + #undef exprtk_loop + #undef case_stmt + + return (vds().data())[0]; + } + else + return std::numeric_limits::quiet_NaN(); + } + + vector_node_ptr vec() const + { + return temp_vec_node_; + } + + vector_node_ptr vec() + { + return temp_vec_node_; + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_vecunaryop; + } + + std::size_t size() const + { + return vds().size(); + } + + vds_t& vds() + { + return vds_; + } + + const vds_t& vds() const + { + return vds_; + } + + private: + + vector_node_ptr vec0_node_ptr_; + vector_holder_ptr temp_; + vector_node_ptr temp_vec_node_; + vds_t vds_; + }; + + template + class scand_node : public binary_node + { + public: + + typedef expression_node* expression_ptr; + + scand_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1) + {} + + inline T value() const + { + return ( + std::not_equal_to() + (T(0),binary_node::branch_[0].first->value()) && + std::not_equal_to() + (T(0),binary_node::branch_[1].first->value()) + ) ? T(1) : T(0); + } + }; + + template + class scor_node : public binary_node + { + public: + + typedef expression_node* expression_ptr; + + scor_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1) + {} + + inline T value() const + { + return ( + std::not_equal_to() + (T(0),binary_node::branch_[0].first->value()) || + std::not_equal_to() + (T(0),binary_node::branch_[1].first->value()) + ) ? T(1) : T(0); + } + }; + + template + class function_N_node : public expression_node + { + public: + + // Function of N paramters. + typedef expression_node* expression_ptr; + typedef std::pair branch_t; + typedef IFunction ifunction; + + explicit function_N_node(ifunction* func) + : function_((N == func->param_count) ? func : reinterpret_cast(0)), + parameter_count_(func->param_count) + {} + + ~function_N_node() + { + cleanup_branches::execute(branch_); + } + + template + bool init_branches(expression_ptr (&b)[NumBranches]) + { + // Needed for incompetent and broken msvc compiler versions + #ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable: 4127) + #endif + if (N != NumBranches) + return false; + else + { + for (std::size_t i = 0; i < NumBranches; ++i) + { + if (b[i]) + branch_[i] = std::make_pair(b[i],branch_deletable(b[i])); + else + return false; + } + return true; + } + #ifdef _MSC_VER + #pragma warning(pop) + #endif + } + + inline bool operator <(const function_N_node& fn) const + { + return this < (&fn); + } + + inline T value() const + { + // Needed for incompetent and broken msvc compiler versions + #ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable: 4127) + #endif + if ((0 == function_) || (0 == N)) + return std::numeric_limits::quiet_NaN(); + else + { + T v[N]; + evaluate_branches::execute(v,branch_); + return invoke::execute(*function_,v); + } + #ifdef _MSC_VER + #pragma warning(pop) + #endif + } + + template + struct evaluate_branches + { + static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount]) + { + for (std::size_t i = 0; i < BranchCount; ++i) + { + v[i] = b[i].first->value(); + } + } + }; + + template + struct evaluate_branches + { + static inline void execute(T_ (&v)[5], const branch_t (&b)[5]) + { + v[0] = b[0].first->value(); + v[1] = b[1].first->value(); + v[2] = b[2].first->value(); + v[3] = b[3].first->value(); + v[4] = b[4].first->value(); + } + }; + + template + struct evaluate_branches + { + static inline void execute(T_ (&v)[4], const branch_t (&b)[4]) + { + v[0] = b[0].first->value(); + v[1] = b[1].first->value(); + v[2] = b[2].first->value(); + v[3] = b[3].first->value(); + } + }; + + template + struct evaluate_branches + { + static inline void execute(T_ (&v)[3], const branch_t (&b)[3]) + { + v[0] = b[0].first->value(); + v[1] = b[1].first->value(); + v[2] = b[2].first->value(); + } + }; + + template + struct evaluate_branches + { + static inline void execute(T_ (&v)[2], const branch_t (&b)[2]) + { + v[0] = b[0].first->value(); + v[1] = b[1].first->value(); + } + }; + + template + struct evaluate_branches + { + static inline void execute(T_ (&v)[1], const branch_t (&b)[1]) + { + v[0] = b[0].first->value(); + } + }; + + template + struct invoke { static inline T execute(ifunction&, branch_t (&)[ParamCount]) { return std::numeric_limits::quiet_NaN(); } }; + + template + struct invoke + { + static inline T_ execute(ifunction& f, T_ (&v)[20]) + { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18],v[19]); } + }; + + template + struct invoke + { + static inline T_ execute(ifunction& f, T_ (&v)[19]) + { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18]); } + }; + + template + struct invoke + { + static inline T_ execute(ifunction& f, T_ (&v)[18]) + { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17]); } + }; + + template + struct invoke + { + static inline T_ execute(ifunction& f, T_ (&v)[17]) + { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16]); } + }; + + template + struct invoke + { + static inline T_ execute(ifunction& f, T_ (&v)[16]) + { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15]); } + }; + + template + struct invoke + { + static inline T_ execute(ifunction& f, T_ (&v)[15]) + { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14]); } + }; + + template + struct invoke + { + static inline T_ execute(ifunction& f, T_ (&v)[14]) + { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13]); } + }; + + template + struct invoke + { + static inline T_ execute(ifunction& f, T_ (&v)[13]) + { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12]); } + }; + + template + struct invoke + { + static inline T_ execute(ifunction& f, T_ (&v)[12]) + { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11]); } + }; + + template + struct invoke + { + static inline T_ execute(ifunction& f, T_ (&v)[11]) + { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10]); } + }; + + template + struct invoke + { + static inline T_ execute(ifunction& f, T_ (&v)[10]) + { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]); } + }; + + template + struct invoke + { + static inline T_ execute(ifunction& f, T_ (&v)[9]) + { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]); } + }; + + template + struct invoke + { + static inline T_ execute(ifunction& f, T_ (&v)[8]) + { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]); } + }; + + template + struct invoke + { + static inline T_ execute(ifunction& f, T_ (&v)[7]) + { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6]); } + }; + + template + struct invoke + { + static inline T_ execute(ifunction& f, T_ (&v)[6]) + { return f(v[0],v[1],v[2],v[3],v[4],v[5]); } + }; + + template + struct invoke + { + static inline T_ execute(ifunction& f, T_ (&v)[5]) + { return f(v[0],v[1],v[2],v[3],v[4]); } + }; + + template + struct invoke + { + static inline T_ execute(ifunction& f, T_ (&v)[4]) + { return f(v[0],v[1],v[2],v[3]); } + }; + + template + struct invoke + { + static inline T_ execute(ifunction& f, T_ (&v)[3]) + { return f(v[0],v[1],v[2]); } + }; + + template + struct invoke + { + static inline T_ execute(ifunction& f, T_ (&v)[2]) + { return f(v[0],v[1]); } + }; + + template + struct invoke + { + static inline T_ execute(ifunction& f, T_ (&v)[1]) + { return f(v[0]); } + }; + + inline typename expression_node::node_type type() const + { + return expression_node::e_function; + } + + private: + + ifunction* function_; + std::size_t parameter_count_; + branch_t branch_[N]; + }; + + template + class function_N_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + typedef IFunction ifunction; + + explicit function_N_node(ifunction* func) + : function_((0 == func->param_count) ? func : reinterpret_cast(0)) + {} + + inline bool operator <(const function_N_node& fn) const + { + return this < (&fn); + } + + inline T value() const + { + if (function_) + return (*function_)(); + else + return std::numeric_limits::quiet_NaN(); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_function; + } + + private: + + ifunction* function_; + }; + + template + class vararg_function_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + vararg_function_node(VarArgFunction* func, + const std::vector& arg_list) + : function_(func), + arg_list_(arg_list) + { + value_list_.resize(arg_list.size(),std::numeric_limits::quiet_NaN()); + } + + ~vararg_function_node() + { + for (std::size_t i = 0; i < arg_list_.size(); ++i) + { + if (arg_list_[i] && !details::is_variable_node(arg_list_[i])) + { + destroy_node(arg_list_[i]); + } + } + } + + inline bool operator <(const vararg_function_node& fn) const + { + return this < (&fn); + } + + inline T value() const + { + if (function_) + { + populate_value_list(); + return (*function_)(value_list_); + } + else + return std::numeric_limits::quiet_NaN(); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_vafunction; + } + + private: + + inline void populate_value_list() const + { + for (std::size_t i = 0; i < arg_list_.size(); ++i) + { + value_list_[i] = arg_list_[i]->value(); + } + } + + VarArgFunction* function_; + std::vector arg_list_; + mutable std::vector value_list_; + }; + + template + class generic_function_node : public expression_node + { + public: + + typedef type_store type_store_t; + typedef expression_node* expression_ptr; + typedef variable_node variable_node_t; + typedef vector_node vector_node_t; + typedef variable_node_t* variable_node_ptr_t; + typedef vector_node_t* vector_node_ptr_t; + typedef range_interface range_interface_t; + typedef range_data_type range_data_type_t; + typedef range_pack range_t; + typedef std::pair branch_t; + typedef std::pair void_t; + typedef std::vector tmp_vs_t; + typedef std::vector typestore_list_t; + typedef std::vector range_list_t; + + generic_function_node(const std::vector& arg_list, + GenericFunction* func = (GenericFunction*)(0)) + : function_(func), + arg_list_(arg_list) + {} + + virtual ~generic_function_node() + { + cleanup_branches::execute(branch_); + } + + virtual bool init_branches() + { + expr_as_vec1_store_.resize(arg_list_.size(),T(0) ); + typestore_list_ .resize(arg_list_.size(),type_store_t() ); + range_list_ .resize(arg_list_.size(),range_data_type_t()); + branch_ .resize(arg_list_.size(),branch_t((expression_ptr)0,false)); + + for (std::size_t i = 0; i < arg_list_.size(); ++i) + { + type_store_t& ts = typestore_list_[i]; + + if (0 == arg_list_[i]) + return false; + else if (is_ivector_node(arg_list_[i])) + { + vector_interface* vi = reinterpret_cast*>(0); + + if (0 == (vi = dynamic_cast*>(arg_list_[i]))) + return false; + + ts.size = vi->size(); + ts.data = vi->vds().data(); + ts.type = type_store_t::e_vector; + vi->vec()->vec_holder().set_ref(&ts.vec_data); + } + #ifndef exprtk_disable_string_capabilities + else if (is_generally_string_node(arg_list_[i])) + { + string_base_node* sbn = reinterpret_cast*>(0); + + if (0 == (sbn = dynamic_cast*>(arg_list_[i]))) + return false; + + ts.size = sbn->size(); + ts.data = reinterpret_cast(const_cast(sbn->base())); + ts.type = type_store_t::e_string; + + range_list_[i].data = ts.data; + range_list_[i].size = ts.size; + range_list_[i].type_size = sizeof(char); + range_list_[i].str_node = sbn; + + range_interface_t* ri = reinterpret_cast(0); + + if (0 == (ri = dynamic_cast(arg_list_[i]))) + return false; + + range_t& rp = ri->range_ref(); + + if ( + rp.const_range() && + is_const_string_range_node(arg_list_[i]) + ) + { + ts.size = rp.const_size(); + ts.data = static_cast(ts.data) + rp.n0_c.second; + range_list_[i].range = reinterpret_cast(0); + } + else + range_list_[i].range = &(ri->range_ref()); + } + #endif + else if (is_variable_node(arg_list_[i])) + { + variable_node_ptr_t var = variable_node_ptr_t(0); + + if (0 == (var = dynamic_cast(arg_list_[i]))) + return false; + + ts.size = 1; + ts.data = &var->ref(); + ts.type = type_store_t::e_scalar; + } + else + { + ts.size = 1; + ts.data = reinterpret_cast(&expr_as_vec1_store_[i]); + ts.type = type_store_t::e_scalar; + } + + branch_[i] = std::make_pair(arg_list_[i],branch_deletable(arg_list_[i])); + } + + return true; + } + + inline bool operator <(const generic_function_node& fn) const + { + return this < (&fn); + } + + inline T value() const + { + if (function_) + { + if (populate_value_list()) + { + typedef typename GenericFunction::parameter_list_t parameter_list_t; + + return (*function_)(parameter_list_t(typestore_list_)); + } + } + + return std::numeric_limits::quiet_NaN(); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_genfunction; + } + + protected: + + inline virtual bool populate_value_list() const + { + for (std::size_t i = 0; i < branch_.size(); ++i) + { + expr_as_vec1_store_[i] = branch_[i].first->value(); + } + + for (std::size_t i = 0; i < branch_.size(); ++i) + { + range_data_type_t& rdt = range_list_[i]; + + if (rdt.range) + { + range_t& rp = (*rdt.range); + std::size_t r0 = 0; + std::size_t r1 = 0; + + if (rp(r0,r1,rdt.size)) + { + type_store_t& ts = typestore_list_[i]; + + ts.size = rp.cache_size(); + #ifndef exprtk_disable_string_capabilities + if (ts.type == type_store_t::e_string) + ts.data = const_cast(rdt.str_node->base()) + rp.cache.first; + else + #endif + ts.data = static_cast(rdt.data) + (rp.cache.first * rdt.type_size); + } + else + return false; + } + } + + return true; + } + + GenericFunction* function_; + mutable typestore_list_t typestore_list_; + + private: + + std::vector arg_list_; + std::vector branch_; + mutable tmp_vs_t expr_as_vec1_store_; + mutable range_list_t range_list_; + }; + + #ifndef exprtk_disable_string_capabilities + template + class string_function_node : public generic_function_node, + public string_base_node, + public range_interface + { + public: + + typedef generic_function_node gen_function_t; + typedef range_pack range_t; + + string_function_node(StringFunction* func, + const std::vector& arg_list) + : gen_function_t(arg_list,func) + { + range_.n0_c = std::make_pair(true,0); + range_.n1_c = std::make_pair(true,0); + range_.cache.first = range_.n0_c.second; + range_.cache.second = range_.n1_c.second; + } + + inline bool operator <(const string_function_node& fn) const + { + return this < (&fn); + } + + inline T value() const + { + if (gen_function_t::function_) + { + if (gen_function_t::populate_value_list()) + { + typedef typename StringFunction::parameter_list_t parameter_list_t; + + const T result = (*gen_function_t::function_) + (ret_string_, parameter_list_t(gen_function_t::typestore_list_)); + + range_.n1_c.second = ret_string_.size() - 1; + range_.cache.second = range_.n1_c.second; + + return result; + } + } + + return std::numeric_limits::quiet_NaN(); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_strfunction; + } + + std::string str() const + { + return ret_string_; + } + + char_cptr base() const + { + return &ret_string_[0]; + } + + std::size_t size() const + { + return ret_string_.size(); + } + + range_t& range_ref() + { + return range_; + } + + const range_t& range_ref() const + { + return range_; + } + + protected: + + mutable range_t range_; + mutable std::string ret_string_; + }; + #endif + + template + class multimode_genfunction_node : public generic_function_node + { + public: + + typedef generic_function_node gen_function_t; + typedef range_pack range_t; + + multimode_genfunction_node(GenericFunction* func, + const std::size_t& param_seq_index, + const std::vector& arg_list) + : gen_function_t(arg_list,func), + param_seq_index_(param_seq_index) + {} + + inline T value() const + { + if (gen_function_t::function_) + { + if (gen_function_t::populate_value_list()) + { + typedef typename GenericFunction::parameter_list_t parameter_list_t; + + return (*gen_function_t::function_)(param_seq_index_, + parameter_list_t(gen_function_t::typestore_list_)); + } + } + + return std::numeric_limits::quiet_NaN(); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_genfunction; + } + + private: + + std::size_t param_seq_index_; + }; + + #ifndef exprtk_disable_string_capabilities + template + class multimode_strfunction_node : public string_function_node + { + public: + + typedef string_function_node str_function_t; + typedef range_pack range_t; + + multimode_strfunction_node(StringFunction* func, + const std::size_t& param_seq_index, + const std::vector& arg_list) + : str_function_t(func,arg_list), + param_seq_index_(param_seq_index) + {} + + inline T value() const + { + if (str_function_t::function_) + { + if (str_function_t::populate_value_list()) + { + typedef typename StringFunction::parameter_list_t parameter_list_t; + + const T result = (*str_function_t::function_)(param_seq_index_, + str_function_t::ret_string_, + parameter_list_t(str_function_t::typestore_list_)); + + str_function_t::range_.n1_c.second = str_function_t::ret_string_.size() - 1; + str_function_t::range_.cache.second = str_function_t::range_.n1_c.second; + + return result; + } + } + + return std::numeric_limits::quiet_NaN(); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_strfunction; + } + + private: + + const std::size_t param_seq_index_; + }; + #endif + + class return_exception + {}; + + template + class null_igenfunc + { + public: + + virtual ~null_igenfunc() + {} + + typedef type_store generic_type; + typedef typename generic_type::parameter_list parameter_list_t; + + inline virtual T operator() (parameter_list_t) + { + return std::numeric_limits::quiet_NaN(); + } + }; + + #ifndef exprtk_disable_return_statement + template + class return_node : public generic_function_node > + { + public: + + typedef null_igenfunc igeneric_function_t; + typedef igeneric_function_t* igeneric_function_ptr; + typedef generic_function_node gen_function_t; + typedef results_context results_context_t; + + return_node(const std::vector& arg_list, + results_context_t& rc) + : gen_function_t (arg_list), + results_context_(&rc) + {} + + inline T value() const + { + if ( + (0 != results_context_) && + gen_function_t::populate_value_list() + ) + { + typedef typename type_store::parameter_list parameter_list_t; + + results_context_-> + assign(parameter_list_t(gen_function_t::typestore_list_)); + + throw return_exception(); + } + + return std::numeric_limits::quiet_NaN(); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_return; + } + + private: + + results_context_t* results_context_; + }; + + template + class return_envelope_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + typedef results_context results_context_t; + + return_envelope_node(expression_ptr body, results_context_t& rc) + : results_context_(&rc ), + return_invoked_ (false), + body_ (body ), + body_deletable_ (branch_deletable(body_)) + {} + + ~return_envelope_node() + { + if (body_ && body_deletable_) + { + destroy_node(body_); + } + } + + inline T value() const + { + try + { + return_invoked_ = false; + results_context_->clear(); + + return body_->value(); + } + catch(const return_exception&) + { + return_invoked_ = true; + return std::numeric_limits::quiet_NaN(); + } + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_retenv; + } + + inline bool* retinvk_ptr() + { + return &return_invoked_; + } + + private: + + results_context_t* results_context_; + mutable bool return_invoked_; + expression_ptr body_; + const bool body_deletable_; + }; + #endif + + #define exprtk_define_unary_op(OpName) \ + template \ + struct OpName##_op \ + { \ + typedef typename functor_t::Type Type; \ + typedef typename expression_node::node_type node_t; \ + \ + static inline T process(Type v) \ + { \ + return numeric:: OpName (v); \ + } \ + \ + static inline node_t type() \ + { \ + return expression_node::e_##OpName; \ + } \ + \ + static inline details::operator_type operation() \ + { \ + return details::e_##OpName; \ + } \ + }; \ + + exprtk_define_unary_op(abs ) + exprtk_define_unary_op(acos ) + exprtk_define_unary_op(acosh) + exprtk_define_unary_op(asin ) + exprtk_define_unary_op(asinh) + exprtk_define_unary_op(atan ) + exprtk_define_unary_op(atanh) + exprtk_define_unary_op(ceil ) + exprtk_define_unary_op(cos ) + exprtk_define_unary_op(cosh ) + exprtk_define_unary_op(cot ) + exprtk_define_unary_op(csc ) + exprtk_define_unary_op(d2g ) + exprtk_define_unary_op(d2r ) + exprtk_define_unary_op(erf ) + exprtk_define_unary_op(erfc ) + exprtk_define_unary_op(exp ) + exprtk_define_unary_op(expm1) + exprtk_define_unary_op(floor) + exprtk_define_unary_op(frac ) + exprtk_define_unary_op(g2d ) + exprtk_define_unary_op(log ) + exprtk_define_unary_op(log10) + exprtk_define_unary_op(log2 ) + exprtk_define_unary_op(log1p) + exprtk_define_unary_op(ncdf ) + exprtk_define_unary_op(neg ) + exprtk_define_unary_op(notl ) + exprtk_define_unary_op(pos ) + exprtk_define_unary_op(r2d ) + exprtk_define_unary_op(round) + exprtk_define_unary_op(sec ) + exprtk_define_unary_op(sgn ) + exprtk_define_unary_op(sin ) + exprtk_define_unary_op(sinc ) + exprtk_define_unary_op(sinh ) + exprtk_define_unary_op(sqrt ) + exprtk_define_unary_op(tan ) + exprtk_define_unary_op(tanh ) + exprtk_define_unary_op(trunc) + #undef exprtk_define_unary_op + + template + struct opr_base + { + typedef typename details::functor_t::Type Type; + typedef typename details::functor_t::RefType RefType; + typedef typename details::functor_t functor_t; + typedef typename functor_t::qfunc_t quaternary_functor_t; + typedef typename functor_t::tfunc_t trinary_functor_t; + typedef typename functor_t::bfunc_t binary_functor_t; + typedef typename functor_t::ufunc_t unary_functor_t; + }; + + template + struct add_op : public opr_base + { + typedef typename opr_base::Type Type; + typedef typename opr_base::RefType RefType; + + static inline T process(Type t1, Type t2) { return t1 + t2; } + static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; } + static inline void assign(RefType t1, Type t2) { t1 += t2; } + static inline typename expression_node::node_type type() { return expression_node::e_add; } + static inline details::operator_type operation() { return details::e_add; } + }; + + template + struct mul_op : public opr_base + { + typedef typename opr_base::Type Type; + typedef typename opr_base::RefType RefType; + + static inline T process(Type t1, Type t2) { return t1 * t2; } + static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; } + static inline void assign(RefType t1, Type t2) { t1 *= t2; } + static inline typename expression_node::node_type type() { return expression_node::e_mul; } + static inline details::operator_type operation() { return details::e_mul; } + }; + + template + struct sub_op : public opr_base + { + typedef typename opr_base::Type Type; + typedef typename opr_base::RefType RefType; + + static inline T process(Type t1, Type t2) { return t1 - t2; } + static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; } + static inline void assign(RefType t1, Type t2) { t1 -= t2; } + static inline typename expression_node::node_type type() { return expression_node::e_sub; } + static inline details::operator_type operation() { return details::e_sub; } + }; + + template + struct div_op : public opr_base + { + typedef typename opr_base::Type Type; + typedef typename opr_base::RefType RefType; + + static inline T process(Type t1, Type t2) { return t1 / t2; } + static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; } + static inline void assign(RefType t1, Type t2) { t1 /= t2; } + static inline typename expression_node::node_type type() { return expression_node::e_div; } + static inline details::operator_type operation() { return details::e_div; } + }; + + template + struct mod_op : public opr_base + { + typedef typename opr_base::Type Type; + typedef typename opr_base::RefType RefType; + + static inline T process(Type t1, Type t2) { return numeric::modulus(t1,t2); } + static inline void assign(RefType t1, Type t2) { t1 = numeric::modulus(t1,t2); } + static inline typename expression_node::node_type type() { return expression_node::e_mod; } + static inline details::operator_type operation() { return details::e_mod; } + }; + + template + struct pow_op : public opr_base + { + typedef typename opr_base::Type Type; + typedef typename opr_base::RefType RefType; + + static inline T process(Type t1, Type t2) { return numeric::pow(t1,t2); } + static inline void assign(RefType t1, Type t2) { t1 = numeric::pow(t1,t2); } + static inline typename expression_node::node_type type() { return expression_node::e_pow; } + static inline details::operator_type operation() { return details::e_pow; } + }; + + template + struct lt_op : public opr_base + { + typedef typename opr_base::Type Type; + + static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); } + static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); } + static inline typename expression_node::node_type type() { return expression_node::e_lt; } + static inline details::operator_type operation() { return details::e_lt; } + }; + + template + struct lte_op : public opr_base + { + typedef typename opr_base::Type Type; + + static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); } + static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); } + static inline typename expression_node::node_type type() { return expression_node::e_lte; } + static inline details::operator_type operation() { return details::e_lte; } + }; + + template + struct gt_op : public opr_base + { + typedef typename opr_base::Type Type; + + static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); } + static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); } + static inline typename expression_node::node_type type() { return expression_node::e_gt; } + static inline details::operator_type operation() { return details::e_gt; } + }; + + template + struct gte_op : public opr_base + { + typedef typename opr_base::Type Type; + + static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); } + static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); } + static inline typename expression_node::node_type type() { return expression_node::e_gte; } + static inline details::operator_type operation() { return details::e_gte; } + }; + + template + struct eq_op : public opr_base + { + typedef typename opr_base::Type Type; + static inline T process(Type t1, Type t2) { return (std::equal_to()(t1,t2) ? T(1) : T(0)); } + static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); } + static inline typename expression_node::node_type type() { return expression_node::e_eq; } + static inline details::operator_type operation() { return details::e_eq; } + }; + + template + struct equal_op : public opr_base + { + typedef typename opr_base::Type Type; + + static inline T process(Type t1, Type t2) { return numeric::equal(t1,t2); } + static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); } + static inline typename expression_node::node_type type() { return expression_node::e_eq; } + static inline details::operator_type operation() { return details::e_equal; } + }; + + template + struct ne_op : public opr_base + { + typedef typename opr_base::Type Type; + + static inline T process(Type t1, Type t2) { return (std::not_equal_to()(t1,t2) ? T(1) : T(0)); } + static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); } + static inline typename expression_node::node_type type() { return expression_node::e_ne; } + static inline details::operator_type operation() { return details::e_ne; } + }; + + template + struct and_op : public opr_base + { + typedef typename opr_base::Type Type; + + static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); } + static inline typename expression_node::node_type type() { return expression_node::e_and; } + static inline details::operator_type operation() { return details::e_and; } + }; + + template + struct nand_op : public opr_base + { + typedef typename opr_base::Type Type; + + static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); } + static inline typename expression_node::node_type type() { return expression_node::e_nand; } + static inline details::operator_type operation() { return details::e_nand; } + }; + + template + struct or_op : public opr_base + { + typedef typename opr_base::Type Type; + + static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); } + static inline typename expression_node::node_type type() { return expression_node::e_or; } + static inline details::operator_type operation() { return details::e_or; } + }; + + template + struct nor_op : public opr_base + { + typedef typename opr_base::Type Type; + + static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); } + static inline typename expression_node::node_type type() { return expression_node::e_nor; } + static inline details::operator_type operation() { return details::e_nor; } + }; + + template + struct xor_op : public opr_base + { + typedef typename opr_base::Type Type; + + static inline T process(Type t1, Type t2) { return numeric::xor_opr(t1,t2); } + static inline typename expression_node::node_type type() { return expression_node::e_nor; } + static inline details::operator_type operation() { return details::e_xor; } + }; + + template + struct xnor_op : public opr_base + { + typedef typename opr_base::Type Type; + + static inline T process(Type t1, Type t2) { return numeric::xnor_opr(t1,t2); } + static inline typename expression_node::node_type type() { return expression_node::e_nor; } + static inline details::operator_type operation() { return details::e_xnor; } + }; + + template + struct in_op : public opr_base + { + typedef typename opr_base::Type Type; + + static inline T process(const T&, const T&) { return std::numeric_limits::quiet_NaN(); } + static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); } + static inline typename expression_node::node_type type() { return expression_node::e_in; } + static inline details::operator_type operation() { return details::e_in; } + }; + + template + struct like_op : public opr_base + { + typedef typename opr_base::Type Type; + + static inline T process(const T&, const T&) { return std::numeric_limits::quiet_NaN(); } + static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); } + static inline typename expression_node::node_type type() { return expression_node::e_like; } + static inline details::operator_type operation() { return details::e_like; } + }; + + template + struct ilike_op : public opr_base + { + typedef typename opr_base::Type Type; + + static inline T process(const T&, const T&) { return std::numeric_limits::quiet_NaN(); } + static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); } + static inline typename expression_node::node_type type() { return expression_node::e_ilike; } + static inline details::operator_type operation() { return details::e_ilike; } + }; + + template + struct inrange_op : public opr_base + { + typedef typename opr_base::Type Type; + + static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); } + static inline T process(const std::string& t0, const std::string& t1, const std::string& t2) + { + return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); + } + static inline typename expression_node::node_type type() { return expression_node::e_inranges; } + static inline details::operator_type operation() { return details::e_inrange; } + }; + + template + inline T value(details::expression_node* n) + { + return n->value(); + } + + template + inline T value(T* t) + { + return (*t); + } + + template + struct vararg_add_op : public opr_base + { + typedef typename opr_base::Type Type; + + template class Sequence> + static inline T process(const Sequence& arg_list) + { + switch (arg_list.size()) + { + case 0 : return T(0); + case 1 : return process_1(arg_list); + case 2 : return process_2(arg_list); + case 3 : return process_3(arg_list); + case 4 : return process_4(arg_list); + case 5 : return process_5(arg_list); + default : + { + T result = T(0); + + for (std::size_t i = 0; i < arg_list.size(); ++i) + { + result += value(arg_list[i]); + } + + return result; + } + } + } + + template + static inline T process_1(const Sequence& arg_list) + { + return value(arg_list[0]); + } + + template + static inline T process_2(const Sequence& arg_list) + { + return value(arg_list[0]) + value(arg_list[1]); + } + + template + static inline T process_3(const Sequence& arg_list) + { + return value(arg_list[0]) + value(arg_list[1]) + + value(arg_list[2]) ; + } + + template + static inline T process_4(const Sequence& arg_list) + { + return value(arg_list[0]) + value(arg_list[1]) + + value(arg_list[2]) + value(arg_list[3]) ; + } + + template + static inline T process_5(const Sequence& arg_list) + { + return value(arg_list[0]) + value(arg_list[1]) + + value(arg_list[2]) + value(arg_list[3]) + + value(arg_list[4]) ; + } + }; + + template + struct vararg_mul_op : public opr_base + { + typedef typename opr_base::Type Type; + + template class Sequence> + static inline T process(const Sequence& arg_list) + { + switch (arg_list.size()) + { + case 0 : return T(0); + case 1 : return process_1(arg_list); + case 2 : return process_2(arg_list); + case 3 : return process_3(arg_list); + case 4 : return process_4(arg_list); + case 5 : return process_5(arg_list); + default : + { + T result = T(value(arg_list[0])); + + for (std::size_t i = 1; i < arg_list.size(); ++i) + { + result *= value(arg_list[i]); + } + + return result; + } + } + } + + template + static inline T process_1(const Sequence& arg_list) + { + return value(arg_list[0]); + } + + template + static inline T process_2(const Sequence& arg_list) + { + return value(arg_list[0]) * value(arg_list[1]); + } + + template + static inline T process_3(const Sequence& arg_list) + { + return value(arg_list[0]) * value(arg_list[1]) * + value(arg_list[2]) ; + } + + template + static inline T process_4(const Sequence& arg_list) + { + return value(arg_list[0]) * value(arg_list[1]) * + value(arg_list[2]) * value(arg_list[3]) ; + } + + template + static inline T process_5(const Sequence& arg_list) + { + return value(arg_list[0]) * value(arg_list[1]) * + value(arg_list[2]) * value(arg_list[3]) * + value(arg_list[4]) ; + } + }; + + template + struct vararg_avg_op : public opr_base + { + typedef typename opr_base::Type Type; + + template class Sequence> + static inline T process(const Sequence& arg_list) + { + switch (arg_list.size()) + { + case 0 : return T(0); + case 1 : return process_1(arg_list); + case 2 : return process_2(arg_list); + case 3 : return process_3(arg_list); + case 4 : return process_4(arg_list); + case 5 : return process_5(arg_list); + default : return vararg_add_op::process(arg_list) / arg_list.size(); + } + } + + template + static inline T process_1(const Sequence& arg_list) + { + return value(arg_list[0]); + } + + template + static inline T process_2(const Sequence& arg_list) + { + return (value(arg_list[0]) + value(arg_list[1])) / T(2); + } + + template + static inline T process_3(const Sequence& arg_list) + { + return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3); + } + + template + static inline T process_4(const Sequence& arg_list) + { + return (value(arg_list[0]) + value(arg_list[1]) + + value(arg_list[2]) + value(arg_list[3])) / T(4); + } + + template + static inline T process_5(const Sequence& arg_list) + { + return (value(arg_list[0]) + value(arg_list[1]) + + value(arg_list[2]) + value(arg_list[3]) + + value(arg_list[4])) / T(5); + } + }; + + template + struct vararg_min_op : public opr_base + { + typedef typename opr_base::Type Type; + + template class Sequence> + static inline T process(const Sequence& arg_list) + { + switch (arg_list.size()) + { + case 0 : return T(0); + case 1 : return process_1(arg_list); + case 2 : return process_2(arg_list); + case 3 : return process_3(arg_list); + case 4 : return process_4(arg_list); + case 5 : return process_5(arg_list); + default : + { + T result = T(value(arg_list[0])); + + for (std::size_t i = 1; i < arg_list.size(); ++i) + { + const T v = value(arg_list[i]); + + if (v < result) + result = v; + } + + return result; + } + } + } + + template + static inline T process_1(const Sequence& arg_list) + { + return value(arg_list[0]); + } + + template + static inline T process_2(const Sequence& arg_list) + { + return std::min(value(arg_list[0]),value(arg_list[1])); + } + + template + static inline T process_3(const Sequence& arg_list) + { + return std::min(std::min(value(arg_list[0]),value(arg_list[1])),value(arg_list[2])); + } + + template + static inline T process_4(const Sequence& arg_list) + { + return std::min( + std::min(value(arg_list[0]),value(arg_list[1])), + std::min(value(arg_list[2]),value(arg_list[3]))); + } + + template + static inline T process_5(const Sequence& arg_list) + { + return std::min( + std::min(std::min(value(arg_list[0]),value(arg_list[1])), + std::min(value(arg_list[2]),value(arg_list[3]))), + value(arg_list[4])); + } + }; + + template + struct vararg_max_op : public opr_base + { + typedef typename opr_base::Type Type; + + template class Sequence> + static inline T process(const Sequence& arg_list) + { + switch (arg_list.size()) + { + case 0 : return T(0); + case 1 : return process_1(arg_list); + case 2 : return process_2(arg_list); + case 3 : return process_3(arg_list); + case 4 : return process_4(arg_list); + case 5 : return process_5(arg_list); + default : + { + T result = T(value(arg_list[0])); + + for (std::size_t i = 1; i < arg_list.size(); ++i) + { + const T v = value(arg_list[i]); + + if (v > result) + result = v; + } + + return result; + } + } + } + + template + static inline T process_1(const Sequence& arg_list) + { + return value(arg_list[0]); + } + + template + static inline T process_2(const Sequence& arg_list) + { + return std::max(value(arg_list[0]),value(arg_list[1])); + } + + template + static inline T process_3(const Sequence& arg_list) + { + return std::max(std::max(value(arg_list[0]),value(arg_list[1])),value(arg_list[2])); + } + + template + static inline T process_4(const Sequence& arg_list) + { + return std::max( + std::max(value(arg_list[0]),value(arg_list[1])), + std::max(value(arg_list[2]),value(arg_list[3]))); + } + + template + static inline T process_5(const Sequence& arg_list) + { + return std::max( + std::max(std::max(value(arg_list[0]),value(arg_list[1])), + std::max(value(arg_list[2]),value(arg_list[3]))), + value(arg_list[4])); + } + }; + + template + struct vararg_mand_op : public opr_base + { + typedef typename opr_base::Type Type; + + template class Sequence> + static inline T process(const Sequence& arg_list) + { + switch (arg_list.size()) + { + case 1 : return process_1(arg_list); + case 2 : return process_2(arg_list); + case 3 : return process_3(arg_list); + case 4 : return process_4(arg_list); + case 5 : return process_5(arg_list); + default : + { + for (std::size_t i = 0; i < arg_list.size(); ++i) + { + if (std::equal_to()(T(0), value(arg_list[i]))) + return T(0); + } + + return T(1); + } + } + } + + template + static inline T process_1(const Sequence& arg_list) + { + return std::not_equal_to() + (T(0), value(arg_list[0])) ? T(1) : T(0); + } + + template + static inline T process_2(const Sequence& arg_list) + { + return ( + std::not_equal_to()(T(0), value(arg_list[0])) && + std::not_equal_to()(T(0), value(arg_list[1])) + ) ? T(1) : T(0); + } + + template + static inline T process_3(const Sequence& arg_list) + { + return ( + std::not_equal_to()(T(0), value(arg_list[0])) && + std::not_equal_to()(T(0), value(arg_list[1])) && + std::not_equal_to()(T(0), value(arg_list[2])) + ) ? T(1) : T(0); + } + + template + static inline T process_4(const Sequence& arg_list) + { + return ( + std::not_equal_to()(T(0), value(arg_list[0])) && + std::not_equal_to()(T(0), value(arg_list[1])) && + std::not_equal_to()(T(0), value(arg_list[2])) && + std::not_equal_to()(T(0), value(arg_list[3])) + ) ? T(1) : T(0); + } + + template + static inline T process_5(const Sequence& arg_list) + { + return ( + std::not_equal_to()(T(0), value(arg_list[0])) && + std::not_equal_to()(T(0), value(arg_list[1])) && + std::not_equal_to()(T(0), value(arg_list[2])) && + std::not_equal_to()(T(0), value(arg_list[3])) && + std::not_equal_to()(T(0), value(arg_list[4])) + ) ? T(1) : T(0); + } + }; + + template + struct vararg_mor_op : public opr_base + { + typedef typename opr_base::Type Type; + + template class Sequence> + static inline T process(const Sequence& arg_list) + { + switch (arg_list.size()) + { + case 1 : return process_1(arg_list); + case 2 : return process_2(arg_list); + case 3 : return process_3(arg_list); + case 4 : return process_4(arg_list); + case 5 : return process_5(arg_list); + default : + { + for (std::size_t i = 0; i < arg_list.size(); ++i) + { + if (std::not_equal_to()(T(0), value(arg_list[i]))) + return T(1); + } + + return T(0); + } + } + } + + template + static inline T process_1(const Sequence& arg_list) + { + return std::not_equal_to() + (T(0), value(arg_list[0])) ? T(1) : T(0); + } + + template + static inline T process_2(const Sequence& arg_list) + { + return ( + std::not_equal_to()(T(0), value(arg_list[0])) || + std::not_equal_to()(T(0), value(arg_list[1])) + ) ? T(1) : T(0); + } + + template + static inline T process_3(const Sequence& arg_list) + { + return ( + std::not_equal_to()(T(0), value(arg_list[0])) || + std::not_equal_to()(T(0), value(arg_list[1])) || + std::not_equal_to()(T(0), value(arg_list[2])) + ) ? T(1) : T(0); + } + + template + static inline T process_4(const Sequence& arg_list) + { + return ( + std::not_equal_to()(T(0), value(arg_list[0])) || + std::not_equal_to()(T(0), value(arg_list[1])) || + std::not_equal_to()(T(0), value(arg_list[2])) || + std::not_equal_to()(T(0), value(arg_list[3])) + ) ? T(1) : T(0); + } + + template + static inline T process_5(const Sequence& arg_list) + { + return ( + std::not_equal_to()(T(0), value(arg_list[0])) || + std::not_equal_to()(T(0), value(arg_list[1])) || + std::not_equal_to()(T(0), value(arg_list[2])) || + std::not_equal_to()(T(0), value(arg_list[3])) || + std::not_equal_to()(T(0), value(arg_list[4])) + ) ? T(1) : T(0); + } + }; + + template + struct vararg_multi_op : public opr_base + { + typedef typename opr_base::Type Type; + + template class Sequence> + static inline T process(const Sequence& arg_list) + { + switch (arg_list.size()) + { + case 0 : return std::numeric_limits::quiet_NaN(); + case 1 : return process_1(arg_list); + case 2 : return process_2(arg_list); + case 3 : return process_3(arg_list); + case 4 : return process_4(arg_list); + case 5 : return process_5(arg_list); + case 6 : return process_6(arg_list); + case 7 : return process_7(arg_list); + case 8 : return process_8(arg_list); + default : + { + for (std::size_t i = 0; i < (arg_list.size() - 1); ++i) + { + value(arg_list[i]); + } + + return value(arg_list.back()); + } + } + } + + template + static inline T process_1(const Sequence& arg_list) + { + return value(arg_list[0]); + } + + template + static inline T process_2(const Sequence& arg_list) + { + value(arg_list[0]); + return value(arg_list[1]); + } + + template + static inline T process_3(const Sequence& arg_list) + { + value(arg_list[0]); + value(arg_list[1]); + return value(arg_list[2]); + } + + template + static inline T process_4(const Sequence& arg_list) + { + value(arg_list[0]); + value(arg_list[1]); + value(arg_list[2]); + return value(arg_list[3]); + } + + template + static inline T process_5(const Sequence& arg_list) + { + value(arg_list[0]); + value(arg_list[1]); + value(arg_list[2]); + value(arg_list[3]); + return value(arg_list[4]); + } + + template + static inline T process_6(const Sequence& arg_list) + { + value(arg_list[0]); + value(arg_list[1]); + value(arg_list[2]); + value(arg_list[3]); + value(arg_list[4]); + return value(arg_list[5]); + } + + template + static inline T process_7(const Sequence& arg_list) + { + value(arg_list[0]); + value(arg_list[1]); + value(arg_list[2]); + value(arg_list[3]); + value(arg_list[4]); + value(arg_list[5]); + return value(arg_list[6]); + } + + template + static inline T process_8(const Sequence& arg_list) + { + value(arg_list[0]); + value(arg_list[1]); + value(arg_list[2]); + value(arg_list[3]); + value(arg_list[4]); + value(arg_list[5]); + value(arg_list[6]); + return value(arg_list[7]); + } + }; + + template + struct vec_add_op + { + typedef vector_interface* ivector_ptr; + + static inline T process(const ivector_ptr v) + { + const T* vec = v->vec()->vds().data(); + const std::size_t vec_size = v->vec()->vds().size(); + + loop_unroll::details lud(vec_size); + + if (vec_size <= static_cast(lud.batch_size)) + { + T result = T(0); + int i = 0; + + exprtk_disable_fallthrough_begin + switch (vec_size) + { + #define case_stmt(N) \ + case N : result += vec[i++]; \ + + #ifndef exprtk_disable_superscalar_unroll + case_stmt(16) case_stmt(15) + case_stmt(14) case_stmt(13) + case_stmt(12) case_stmt(11) + case_stmt(10) case_stmt( 9) + case_stmt( 8) case_stmt( 7) + case_stmt( 6) case_stmt( 5) + #endif + case_stmt( 4) case_stmt( 3) + case_stmt( 2) case_stmt( 1) + } + exprtk_disable_fallthrough_end + + #undef case_stmt + + return result; + } + + T r[] = { + T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0), + T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0) + }; + + const T* upper_bound = vec + lud.upper_bound; + + while (vec < upper_bound) + { + #define exprtk_loop(N) \ + r[N] += vec[N]; \ + + exprtk_loop( 0) exprtk_loop( 1) + exprtk_loop( 2) exprtk_loop( 3) + #ifndef exprtk_disable_superscalar_unroll + exprtk_loop( 4) exprtk_loop( 5) + exprtk_loop( 6) exprtk_loop( 7) + exprtk_loop( 8) exprtk_loop( 9) + exprtk_loop(10) exprtk_loop(11) + exprtk_loop(12) exprtk_loop(13) + exprtk_loop(14) exprtk_loop(15) + #endif + + vec += lud.batch_size; + } + + int i = 0; + + exprtk_disable_fallthrough_begin + switch (lud.remainder) + { + #define case_stmt(N) \ + case N : r[0] += vec[i++]; \ + + #ifndef exprtk_disable_superscalar_unroll + case_stmt(15) case_stmt(14) + case_stmt(13) case_stmt(12) + case_stmt(11) case_stmt(10) + case_stmt( 9) case_stmt( 8) + case_stmt( 7) case_stmt( 6) + case_stmt( 5) case_stmt( 4) + #endif + case_stmt( 3) case_stmt( 2) + case_stmt( 1) + } + exprtk_disable_fallthrough_end + + #undef exprtk_loop + #undef case_stmt + + return (r[ 0] + r[ 1] + r[ 2] + r[ 3]) + #ifndef exprtk_disable_superscalar_unroll + + (r[ 4] + r[ 5] + r[ 6] + r[ 7]) + + (r[ 8] + r[ 9] + r[10] + r[11]) + + (r[12] + r[13] + r[14] + r[15]) + #endif + ; + } + }; + + template + struct vec_mul_op + { + typedef vector_interface* ivector_ptr; + + static inline T process(const ivector_ptr v) + { + const T* vec = v->vec()->vds().data(); + const std::size_t vec_size = v->vec()->vds().size(); + + loop_unroll::details lud(vec_size); + + if (vec_size <= static_cast(lud.batch_size)) + { + T result = T(1); + int i = 0; + + exprtk_disable_fallthrough_begin + switch (vec_size) + { + #define case_stmt(N) \ + case N : result *= vec[i++]; \ + + #ifndef exprtk_disable_superscalar_unroll + case_stmt(16) case_stmt(15) + case_stmt(14) case_stmt(13) + case_stmt(12) case_stmt(11) + case_stmt(10) case_stmt( 9) + case_stmt( 8) case_stmt( 7) + case_stmt( 6) case_stmt( 5) + #endif + case_stmt( 4) case_stmt( 3) + case_stmt( 2) case_stmt( 1) + } + exprtk_disable_fallthrough_end + + #undef case_stmt + + return result; + } + + T r[] = { + T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1), + T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1) + }; + + const T* upper_bound = vec + lud.upper_bound; + + while (vec < upper_bound) + { + #define exprtk_loop(N) \ + r[N] *= vec[N]; \ + + exprtk_loop( 0) exprtk_loop( 1) + exprtk_loop( 2) exprtk_loop( 3) + #ifndef exprtk_disable_superscalar_unroll + exprtk_loop( 4) exprtk_loop( 5) + exprtk_loop( 6) exprtk_loop( 7) + exprtk_loop( 8) exprtk_loop( 9) + exprtk_loop(10) exprtk_loop(11) + exprtk_loop(12) exprtk_loop(13) + exprtk_loop(14) exprtk_loop(15) + #endif + + vec += lud.batch_size; + } + + int i = 0; + + exprtk_disable_fallthrough_begin + switch (lud.remainder) + { + #define case_stmt(N) \ + case N : r[0] *= vec[i++]; \ + + #ifndef exprtk_disable_superscalar_unroll + case_stmt(15) case_stmt(14) + case_stmt(13) case_stmt(12) + case_stmt(11) case_stmt(10) + case_stmt( 9) case_stmt( 8) + case_stmt( 7) case_stmt( 6) + case_stmt( 5) case_stmt( 4) + #endif + case_stmt( 3) case_stmt( 2) + case_stmt( 1) + } + exprtk_disable_fallthrough_end + + #undef exprtk_loop + #undef case_stmt + + return (r[ 0] * r[ 1] * r[ 2] * r[ 3]) + #ifndef exprtk_disable_superscalar_unroll + + (r[ 4] * r[ 5] * r[ 6] * r[ 7]) + + (r[ 8] * r[ 9] * r[10] * r[11]) + + (r[12] * r[13] * r[14] * r[15]) + #endif + ; + } + }; + + template + struct vec_avg_op + { + typedef vector_interface* ivector_ptr; + + static inline T process(const ivector_ptr v) + { + const std::size_t vec_size = v->vec()->vds().size(); + + return vec_add_op::process(v) / vec_size; + } + }; + + template + struct vec_min_op + { + typedef vector_interface* ivector_ptr; + + static inline T process(const ivector_ptr v) + { + const T* vec = v->vec()->vds().data(); + const std::size_t vec_size = v->vec()->vds().size(); + + T result = vec[0]; + + for (std::size_t i = 1; i < vec_size; ++i) + { + T v_i = vec[i]; + + if (v_i < result) + result = v_i; + } + + return result; + } + }; + + template + struct vec_max_op + { + typedef vector_interface* ivector_ptr; + + static inline T process(const ivector_ptr v) + { + const T* vec = v->vec()->vds().data(); + const std::size_t vec_size = v->vec()->vds().size(); + + T result = vec[0]; + + for (std::size_t i = 1; i < vec_size; ++i) + { + T v_i = vec[i]; + + if (v_i > result) + result = v_i; + } + + return result; + } + }; + + template + class vov_base_node : public expression_node + { + public: + + virtual ~vov_base_node() + {} + + inline virtual operator_type operation() const + { + return details::e_default; + } + + virtual const T& v0() const = 0; + + virtual const T& v1() const = 0; + }; + + template + class cov_base_node : public expression_node + { + public: + + virtual ~cov_base_node() + {} + + inline virtual operator_type operation() const + { + return details::e_default; + } + + virtual const T c() const = 0; + + virtual const T& v() const = 0; + }; + + template + class voc_base_node : public expression_node + { + public: + + virtual ~voc_base_node() + {} + + inline virtual operator_type operation() const + { + return details::e_default; + } + + virtual const T c() const = 0; + + virtual const T& v() const = 0; + }; + + template + class vob_base_node : public expression_node + { + public: + + virtual ~vob_base_node() + {} + + virtual const T& v() const = 0; + }; + + template + class bov_base_node : public expression_node + { + public: + + virtual ~bov_base_node() + {} + + virtual const T& v() const = 0; + }; + + template + class cob_base_node : public expression_node + { + public: + + virtual ~cob_base_node() + {} + + inline virtual operator_type operation() const + { + return details::e_default; + } + + virtual const T c() const = 0; + + virtual void set_c(const T) = 0; + + virtual expression_node* move_branch(const std::size_t& index) = 0; + }; + + template + class boc_base_node : public expression_node + { + public: + + virtual ~boc_base_node() + {} + + inline virtual operator_type operation() const + { + return details::e_default; + } + + virtual const T c() const = 0; + + virtual void set_c(const T) = 0; + + virtual expression_node* move_branch(const std::size_t& index) = 0; + }; + + template + class uv_base_node : public expression_node + { + public: + + virtual ~uv_base_node() + {} + + inline virtual operator_type operation() const + { + return details::e_default; + } + + virtual const T& v() const = 0; + }; + + template + class sos_base_node : public expression_node + { + public: + + virtual ~sos_base_node() + {} + + inline virtual operator_type operation() const + { + return details::e_default; + } + }; + + template + class sosos_base_node : public expression_node + { + public: + + virtual ~sosos_base_node() + {} + + inline virtual operator_type operation() const + { + return details::e_default; + } + }; + + template + class T0oT1oT2_base_node : public expression_node + { + public: + + virtual ~T0oT1oT2_base_node() + {} + + virtual std::string type_id() const = 0; + }; + + template + class T0oT1oT2oT3_base_node : public expression_node + { + public: + + virtual ~T0oT1oT2oT3_base_node() + {} + + virtual std::string type_id() const = 0; + }; + + template + class unary_variable_node : public uv_base_node + { + public: + + typedef expression_node* expression_ptr; + typedef Operation operation_t; + + explicit unary_variable_node(const T& var) + : v_(var) + {} + + inline T value() const + { + return Operation::process(v_); + } + + inline typename expression_node::node_type type() const + { + return Operation::type(); + } + + inline operator_type operation() const + { + return Operation::operation(); + } + + inline const T& v() const + { + return v_; + } + + private: + + unary_variable_node(unary_variable_node&); + unary_variable_node& operator=(unary_variable_node&); + + const T& v_; + }; + + template + class uvouv_node : public expression_node + { + public: + + // UOpr1(v0) Op UOpr2(v1) + + typedef expression_node* expression_ptr; + typedef typename details::functor_t functor_t; + typedef typename functor_t::bfunc_t bfunc_t; + typedef typename functor_t::ufunc_t ufunc_t; + + explicit uvouv_node(const T& var0,const T& var1, + ufunc_t uf0, ufunc_t uf1, bfunc_t bf) + : v0_(var0), + v1_(var1), + u0_(uf0 ), + u1_(uf1 ), + f_ (bf ) + {} + + inline T value() const + { + return f_(u0_(v0_),u1_(v1_)); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_uvouv; + } + + inline operator_type operation() const + { + return details::e_default; + } + + inline const T& v0() + { + return v0_; + } + + inline const T& v1() + { + return v1_; + } + + inline ufunc_t u0() + { + return u0_; + } + + inline ufunc_t u1() + { + return u1_; + } + + inline ufunc_t f() + { + return f_; + } + + private: + + uvouv_node(uvouv_node&); + uvouv_node& operator=(uvouv_node&); + + const T& v0_; + const T& v1_; + const ufunc_t u0_; + const ufunc_t u1_; + const bfunc_t f_; + }; + + template + class unary_branch_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + typedef Operation operation_t; + + explicit unary_branch_node(expression_ptr brnch) + : branch_(brnch), + branch_deletable_(branch_deletable(branch_)) + {} + + ~unary_branch_node() + { + if (branch_ && branch_deletable_) + { + destroy_node(branch_); + } + } + + inline T value() const + { + return Operation::process(branch_->value()); + } + + inline typename expression_node::node_type type() const + { + return Operation::type(); + } + + inline operator_type operation() const + { + return Operation::operation(); + } + + inline expression_node* branch(const std::size_t&) const + { + return branch_; + } + + inline void release() + { + branch_deletable_ = false; + } + + private: + + unary_branch_node(unary_branch_node&); + unary_branch_node& operator=(unary_branch_node&); + + expression_ptr branch_; + bool branch_deletable_; + }; + + template struct is_const { enum {result = 0}; }; + template struct is_const { enum {result = 1}; }; + template struct is_const_ref { enum {result = 0}; }; + template struct is_const_ref { enum {result = 1}; }; + template struct is_ref { enum {result = 0}; }; + template struct is_ref { enum {result = 1}; }; + template struct is_ref { enum {result = 0}; }; + + template + struct param_to_str { static std::string result() { static const std::string r("v"); return r; } }; + + template <> + struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } }; + + #define exprtk_crtype(Type) \ + param_to_str::result>::result() \ + + template + struct T0oT1oT2process + { + typedef typename details::functor_t functor_t; + typedef typename functor_t::bfunc_t bfunc_t; + + struct mode0 + { + static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1) + { + // (T0 o0 T1) o1 T2 + return bf1(bf0(t0,t1),t2); + } + + template + static inline std::string id() + { + static const std::string result = "(" + exprtk_crtype(T0) + "o" + + exprtk_crtype(T1) + ")o(" + + exprtk_crtype(T2) + ")" ; + return result; + } + }; + + struct mode1 + { + static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1) + { + // T0 o0 (T1 o1 T2) + return bf0(t0,bf1(t1,t2)); + } + + template + static inline std::string id() + { + static const std::string result = "(" + exprtk_crtype(T0) + ")o(" + + exprtk_crtype(T1) + "o" + + exprtk_crtype(T2) + ")" ; + return result; + } + }; + }; + + template + struct T0oT1oT20T3process + { + typedef typename details::functor_t functor_t; + typedef typename functor_t::bfunc_t bfunc_t; + + struct mode0 + { + static inline T process(const T& t0, const T& t1, + const T& t2, const T& t3, + const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) + { + // (T0 o0 T1) o1 (T2 o2 T3) + return bf1(bf0(t0,t1),bf2(t2,t3)); + } + + template + static inline std::string id() + { + static const std::string result = "(" + exprtk_crtype(T0) + "o" + + exprtk_crtype(T1) + ")o" + + "(" + exprtk_crtype(T2) + "o" + + exprtk_crtype(T3) + ")" ; + return result; + } + }; + + struct mode1 + { + static inline T process(const T& t0, const T& t1, + const T& t2, const T& t3, + const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) + { + // (T0 o0 (T1 o1 (T2 o2 T3)) + return bf0(t0,bf1(t1,bf2(t2,t3))); + } + template + static inline std::string id() + { + static const std::string result = "(" + exprtk_crtype(T0) + ")o((" + + exprtk_crtype(T1) + ")o(" + + exprtk_crtype(T2) + "o" + + exprtk_crtype(T3) + "))" ; + return result; + } + }; + + struct mode2 + { + static inline T process(const T& t0, const T& t1, + const T& t2, const T& t3, + const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) + { + // (T0 o0 ((T1 o1 T2) o2 T3) + return bf0(t0,bf2(bf1(t1,t2),t3)); + } + + template + static inline std::string id() + { + static const std::string result = "(" + exprtk_crtype(T0) + ")o((" + + exprtk_crtype(T1) + "o" + + exprtk_crtype(T2) + ")o(" + + exprtk_crtype(T3) + "))" ; + return result; + } + }; + + struct mode3 + { + static inline T process(const T& t0, const T& t1, + const T& t2, const T& t3, + const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) + { + // (((T0 o0 T1) o1 T2) o2 T3) + return bf2(bf1(bf0(t0,t1),t2),t3); + } + + template + static inline std::string id() + { + static const std::string result = "((" + exprtk_crtype(T0) + "o" + + exprtk_crtype(T1) + ")o(" + + exprtk_crtype(T2) + "))o(" + + exprtk_crtype(T3) + ")"; + return result; + } + }; + + struct mode4 + { + static inline T process(const T& t0, const T& t1, + const T& t2, const T& t3, + const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) + { + // ((T0 o0 (T1 o1 T2)) o2 T3 + return bf2(bf0(t0,bf1(t1,t2)),t3); + } + + template + static inline std::string id() + { + static const std::string result = "((" + exprtk_crtype(T0) + ")o(" + + exprtk_crtype(T1) + "o" + + exprtk_crtype(T2) + "))o(" + + exprtk_crtype(T3) + ")" ; + return result; + } + }; + }; + + #undef exprtk_crtype + + template + struct nodetype_T0oT1 { static const typename expression_node::node_type result; }; + template + const typename expression_node::node_type nodetype_T0oT1::result = expression_node::e_none; + + #define synthesis_node_type_define(T0_,T1_,v_) \ + template \ + struct nodetype_T0oT1 { static const typename expression_node::node_type result; }; \ + template \ + const typename expression_node::node_type nodetype_T0oT1::result = expression_node:: v_; \ + + synthesis_node_type_define(const T0&, const T1&, e_vov) + synthesis_node_type_define(const T0&, const T1 , e_voc) + synthesis_node_type_define(const T0 , const T1&, e_cov) + synthesis_node_type_define( T0&, T1&, e_none) + synthesis_node_type_define(const T0 , const T1 , e_none) + synthesis_node_type_define( T0&, const T1 , e_none) + synthesis_node_type_define(const T0 , T1&, e_none) + synthesis_node_type_define(const T0&, T1&, e_none) + synthesis_node_type_define( T0&, const T1&, e_none) + #undef synthesis_node_type_define + + template + struct nodetype_T0oT1oT2 { static const typename expression_node::node_type result; }; + template + const typename expression_node::node_type nodetype_T0oT1oT2::result = expression_node::e_none; + + #define synthesis_node_type_define(T0_,T1_,T2_,v_) \ + template \ + struct nodetype_T0oT1oT2 { static const typename expression_node::node_type result; }; \ + template \ + const typename expression_node::node_type nodetype_T0oT1oT2::result = expression_node:: v_; \ + + synthesis_node_type_define(const T0&, const T1&, const T2&, e_vovov) + synthesis_node_type_define(const T0&, const T1&, const T2 , e_vovoc) + synthesis_node_type_define(const T0&, const T1 , const T2&, e_vocov) + synthesis_node_type_define(const T0 , const T1&, const T2&, e_covov) + synthesis_node_type_define(const T0 , const T1&, const T2 , e_covoc) + synthesis_node_type_define(const T0 , const T1 , const T2 , e_none ) + synthesis_node_type_define(const T0 , const T1 , const T2&, e_none ) + synthesis_node_type_define(const T0&, const T1 , const T2 , e_none ) + synthesis_node_type_define( T0&, T1&, T2&, e_none ) + #undef synthesis_node_type_define + + template + struct nodetype_T0oT1oT2oT3 { static const typename expression_node::node_type result; }; + template + const typename expression_node::node_type nodetype_T0oT1oT2oT3::result = expression_node::e_none; + + #define synthesis_node_type_define(T0_,T1_,T2_,T3_,v_) \ + template \ + struct nodetype_T0oT1oT2oT3 { static const typename expression_node::node_type result; }; \ + template \ + const typename expression_node::node_type nodetype_T0oT1oT2oT3::result = expression_node:: v_; \ + + synthesis_node_type_define(const T0&, const T1&, const T2&, const T3&, e_vovovov) + synthesis_node_type_define(const T0&, const T1&, const T2&, const T3 , e_vovovoc) + synthesis_node_type_define(const T0&, const T1&, const T2 , const T3&, e_vovocov) + synthesis_node_type_define(const T0&, const T1 , const T2&, const T3&, e_vocovov) + synthesis_node_type_define(const T0 , const T1&, const T2&, const T3&, e_covovov) + synthesis_node_type_define(const T0 , const T1&, const T2 , const T3&, e_covocov) + synthesis_node_type_define(const T0&, const T1 , const T2&, const T3 , e_vocovoc) + synthesis_node_type_define(const T0 , const T1&, const T2&, const T3 , e_covovoc) + synthesis_node_type_define(const T0&, const T1 , const T2 , const T3&, e_vococov) + synthesis_node_type_define(const T0 , const T1 , const T2 , const T3 , e_none ) + synthesis_node_type_define(const T0 , const T1 , const T2 , const T3&, e_none ) + synthesis_node_type_define(const T0 , const T1 , const T2&, const T3 , e_none ) + synthesis_node_type_define(const T0 , const T1&, const T2 , const T3 , e_none ) + synthesis_node_type_define(const T0&, const T1 , const T2 , const T3 , e_none ) + synthesis_node_type_define(const T0 , const T1 , const T2&, const T3&, e_none ) + synthesis_node_type_define(const T0&, const T1&, const T2 , const T3 , e_none ) + #undef synthesis_node_type_define + + template + class T0oT1 : public expression_node + { + public: + + typedef typename details::functor_t functor_t; + typedef typename functor_t::bfunc_t bfunc_t; + typedef T value_type; + typedef T0oT1 node_type; + + T0oT1(T0 p0, T1 p1, const bfunc_t p2) + : t0_(p0), + t1_(p1), + f_ (p2) + {} + + inline typename expression_node::node_type type() const + { + static const typename expression_node::node_type result = nodetype_T0oT1::result; + return result; + } + + inline operator_type operation() const + { + return e_default; + } + + inline T value() const + { + return f_(t0_,t1_); + } + + inline T0 t0() const + { + return t0_; + } + + inline T1 t1() const + { + return t1_; + } + + inline bfunc_t f() const + { + return f_; + } + + template + static inline expression_node* allocate(Allocator& allocator, + T0 p0, T1 p1, + bfunc_t p2) + { + return allocator + .template allocate_type + (p0, p1, p2); + } + + private: + + T0oT1(T0oT1&) {} + T0oT1& operator=(T0oT1&) { return (*this); } + + T0 t0_; + T1 t1_; + const bfunc_t f_; + }; + + template + class T0oT1oT2 : public T0oT1oT2_base_node + { + public: + + typedef typename details::functor_t functor_t; + typedef typename functor_t::bfunc_t bfunc_t; + typedef T value_type; + typedef T0oT1oT2 node_type; + typedef ProcessMode process_mode_t; + + T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4) + : t0_(p0), + t1_(p1), + t2_(p2), + f0_(p3), + f1_(p4) + {} + + inline typename expression_node::node_type type() const + { + static const typename expression_node::node_type result = nodetype_T0oT1oT2::result; + return result; + } + + inline operator_type operation() const + { + return e_default; + } + + inline T value() const + { + return ProcessMode::process(t0_, t1_, t2_, f0_, f1_); + } + + inline T0 t0() const + { + return t0_; + } + + inline T1 t1() const + { + return t1_; + } + + inline T2 t2() const + { + return t2_; + } + + bfunc_t f0() const + { + return f0_; + } + + bfunc_t f1() const + { + return f1_; + } + + std::string type_id() const + { + return id(); + } + + static inline std::string id() + { + return process_mode_t::template id(); + } + + template + static inline expression_node* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4) + { + return allocator + .template allocate_type + (p0, p1, p2, p3, p4); + } + + private: + + T0oT1oT2(node_type&) {} + node_type& operator=(node_type&) { return (*this); } + + T0 t0_; + T1 t1_; + T2 t2_; + const bfunc_t f0_; + const bfunc_t f1_; + }; + + template + class T0oT1oT2oT3 : public T0oT1oT2oT3_base_node + { + public: + + typedef typename details::functor_t functor_t; + typedef typename functor_t::bfunc_t bfunc_t; + typedef T value_type; + typedef T0_ T0; + typedef T1_ T1; + typedef T2_ T2; + typedef T3_ T3; + typedef T0oT1oT2oT3 node_type; + typedef ProcessMode process_mode_t; + + T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6) + : t0_(p0), + t1_(p1), + t2_(p2), + t3_(p3), + f0_(p4), + f1_(p5), + f2_(p6) + {} + + inline T value() const + { + return ProcessMode::process(t0_, t1_, t2_, t3_, f0_, f1_, f2_); + } + + inline T0 t0() const + { + return t0_; + } + + inline T1 t1() const + { + return t1_; + } + + inline T2 t2() const + { + return t2_; + } + + inline T3 t3() const + { + return t3_; + } + + inline bfunc_t f0() const + { + return f0_; + } + + inline bfunc_t f1() const + { + return f1_; + } + + inline bfunc_t f2() const + { + return f2_; + } + + inline std::string type_id() const + { + return id(); + } + + static inline std::string id() + { + return process_mode_t::template id(); + } + + template + static inline expression_node* allocate(Allocator& allocator, + T0 p0, T1 p1, T2 p2, T3 p3, + bfunc_t p4, bfunc_t p5, bfunc_t p6) + { + return allocator + .template allocate_type + (p0, p1, p2, p3, p4, p5, p6); + } + + private: + + T0oT1oT2oT3(node_type&) {} + node_type& operator=(node_type&) { return (*this); } + + T0 t0_; + T1 t1_; + T2 t2_; + T3 t3_; + const bfunc_t f0_; + const bfunc_t f1_; + const bfunc_t f2_; + }; + + template + class T0oT1oT2_sf3 : public T0oT1oT2_base_node + { + public: + + typedef typename details::functor_t functor_t; + typedef typename functor_t::tfunc_t tfunc_t; + typedef T value_type; + typedef T0oT1oT2_sf3 node_type; + + T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3) + : t0_(p0), + t1_(p1), + t2_(p2), + f_ (p3) + {} + + inline typename expression_node::node_type type() const + { + static const typename expression_node::node_type result = nodetype_T0oT1oT2::result; + return result; + } + + inline operator_type operation() const + { + return e_default; + } + + inline T value() const + { + return f_(t0_, t1_, t2_); + } + + inline T0 t0() const + { + return t0_; + } + + inline T1 t1() const + { + return t1_; + } + + inline T2 t2() const + { + return t2_; + } + + tfunc_t f() const + { + return f_; + } + + std::string type_id() const + { + return id(); + } + + static inline std::string id() + { + return "sf3"; + } + + template + static inline expression_node* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, tfunc_t p3) + { + return allocator + .template allocate_type + (p0, p1, p2, p3); + } + + private: + + T0oT1oT2_sf3(node_type&) {} + node_type& operator=(node_type&) { return (*this); } + + T0 t0_; + T1 t1_; + T2 t2_; + const tfunc_t f_; + }; + + template + class sf3ext_type_node : public T0oT1oT2_base_node + { + public: + + virtual ~sf3ext_type_node() + {} + + virtual T0 t0() const = 0; + + virtual T1 t1() const = 0; + + virtual T2 t2() const = 0; + }; + + template + class T0oT1oT2_sf3ext : public sf3ext_type_node + { + public: + + typedef typename details::functor_t functor_t; + typedef typename functor_t::tfunc_t tfunc_t; + typedef T value_type; + typedef T0oT1oT2_sf3ext node_type; + + T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2) + : t0_(p0), + t1_(p1), + t2_(p2) + {} + + inline typename expression_node::node_type type() const + { + static const typename expression_node::node_type result = nodetype_T0oT1oT2::result; + return result; + } + + inline operator_type operation() const + { + return e_default; + } + + inline T value() const + { + return SF3Operation::process(t0_, t1_, t2_); + } + + T0 t0() const + { + return t0_; + } + + T1 t1() const + { + return t1_; + } + + T2 t2() const + { + return t2_; + } + + std::string type_id() const + { + return id(); + } + + static inline std::string id() + { + return SF3Operation::id(); + } + + template + static inline expression_node* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2) + { + return allocator + .template allocate_type + (p0, p1, p2); + } + + private: + + T0oT1oT2_sf3ext(node_type&) {} + node_type& operator=(node_type&) { return (*this); } + + T0 t0_; + T1 t1_; + T2 t2_; + }; + + template + inline bool is_sf3ext_node(const expression_node* n) + { + switch (n->type()) + { + case expression_node::e_vovov : return true; + case expression_node::e_vovoc : return true; + case expression_node::e_vocov : return true; + case expression_node::e_covov : return true; + case expression_node::e_covoc : return true; + default : return false; + } + } + + template + class T0oT1oT2oT3_sf4 : public T0oT1oT2_base_node + { + public: + + typedef typename details::functor_t functor_t; + typedef typename functor_t::qfunc_t qfunc_t; + typedef T value_type; + typedef T0oT1oT2oT3_sf4 node_type; + + T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4) + : t0_(p0), + t1_(p1), + t2_(p2), + t3_(p3), + f_ (p4) + {} + + inline typename expression_node::node_type type() const + { + static const typename expression_node::node_type result = nodetype_T0oT1oT2oT3::result; + return result; + } + + inline operator_type operation() const + { + return e_default; + } + + inline T value() const + { + return f_(t0_, t1_, t2_, t3_); + } + + inline T0 t0() const + { + return t0_; + } + + inline T1 t1() const + { + return t1_; + } + + inline T2 t2() const + { + return t2_; + } + + inline T3 t3() const + { + return t3_; + } + + qfunc_t f() const + { + return f_; + } + + std::string type_id() const + { + return id(); + } + + static inline std::string id() + { + return "sf4"; + } + + template + static inline expression_node* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4) + { + return allocator + .template allocate_type + (p0, p1, p2, p3, p4); + } + + private: + + T0oT1oT2oT3_sf4(node_type&) {} + node_type& operator=(node_type&) { return (*this); } + + T0 t0_; + T1 t1_; + T2 t2_; + T3 t3_; + const qfunc_t f_; + }; + + template + class T0oT1oT2oT3_sf4ext : public T0oT1oT2oT3_base_node + { + public: + + typedef typename details::functor_t functor_t; + typedef typename functor_t::tfunc_t tfunc_t; + typedef T value_type; + typedef T0oT1oT2oT3_sf4ext node_type; + + T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3) + : t0_(p0), + t1_(p1), + t2_(p2), + t3_(p3) + {} + + inline typename expression_node::node_type type() const + { + static const typename expression_node::node_type result = nodetype_T0oT1oT2oT3::result; + return result; + } + + inline operator_type operation() const + { + return e_default; + } + + inline T value() const + { + return SF4Operation::process(t0_, t1_, t2_, t3_); + } + + inline T0 t0() const + { + return t0_; + } + + inline T1 t1() const + { + return t1_; + } + + inline T2 t2() const + { + return t2_; + } + + inline T3 t3() const + { + return t3_; + } + + std::string type_id() const + { + return id(); + } + + static inline std::string id() + { + return SF4Operation::id(); + } + + template + static inline expression_node* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3) + { + return allocator + .template allocate_type + (p0, p1, p2, p3); + } + + private: + + T0oT1oT2oT3_sf4ext(node_type&) {} + node_type& operator=(node_type&) { return (*this); } + + T0 t0_; + T1 t1_; + T2 t2_; + T3 t3_; + }; + + template + inline bool is_sf4ext_node(const expression_node* n) + { + switch (n->type()) + { + case expression_node::e_vovovov : return true; + case expression_node::e_vovovoc : return true; + case expression_node::e_vovocov : return true; + case expression_node::e_vocovov : return true; + case expression_node::e_covovov : return true; + case expression_node::e_covocov : return true; + case expression_node::e_vocovoc : return true; + case expression_node::e_covovoc : return true; + case expression_node::e_vococov : return true; + default : return false; + } + } + + template + struct T0oT1_define + { + typedef details::T0oT1 type0; + }; + + template + struct T0oT1oT2_define + { + typedef details::T0oT1oT2::mode0> type0; + typedef details::T0oT1oT2::mode1> type1; + typedef details::T0oT1oT2_sf3 sf3_type; + typedef details::sf3ext_type_node sf3_type_node; + }; + + template + struct T0oT1oT2oT3_define + { + typedef details::T0oT1oT2oT3::mode0> type0; + typedef details::T0oT1oT2oT3::mode1> type1; + typedef details::T0oT1oT2oT3::mode2> type2; + typedef details::T0oT1oT2oT3::mode3> type3; + typedef details::T0oT1oT2oT3::mode4> type4; + typedef details::T0oT1oT2oT3_sf4 sf4_type; + }; + + template + class vov_node : public vov_base_node + { + public: + + typedef expression_node* expression_ptr; + typedef Operation operation_t; + + // variable op variable node + explicit vov_node(const T& var0, const T& var1) + : v0_(var0), + v1_(var1) + {} + + inline T value() const + { + return Operation::process(v0_,v1_); + } + + inline typename expression_node::node_type type() const + { + return Operation::type(); + } + + inline operator_type operation() const + { + return Operation::operation(); + } + + inline const T& v0() const + { + return v0_; + } + + inline const T& v1() const + { + return v1_; + } + + protected: + + const T& v0_; + const T& v1_; + + private: + + vov_node(vov_node&); + vov_node& operator=(vov_node&); + }; + + template + class cov_node : public cov_base_node + { + public: + + typedef expression_node* expression_ptr; + typedef Operation operation_t; + + // constant op variable node + explicit cov_node(const T& const_var, const T& var) + : c_(const_var), + v_(var) + {} + + inline T value() const + { + return Operation::process(c_,v_); + } + + inline typename expression_node::node_type type() const + { + return Operation::type(); + } + + inline operator_type operation() const + { + return Operation::operation(); + } + + inline const T c() const + { + return c_; + } + + inline const T& v() const + { + return v_; + } + + protected: + + const T c_; + const T& v_; + + private: + + cov_node(const cov_node&); + cov_node& operator=(const cov_node&); + }; + + template + class voc_node : public voc_base_node + { + public: + + typedef expression_node* expression_ptr; + typedef Operation operation_t; + + // variable op constant node + explicit voc_node(const T& var, const T& const_var) + : v_(var), + c_(const_var) + {} + + inline T value() const + { + return Operation::process(v_,c_); + } + + inline operator_type operation() const + { + return Operation::operation(); + } + + inline const T c() const + { + return c_; + } + + inline const T& v() const + { + return v_; + } + + protected: + + const T& v_; + const T c_; + + private: + + voc_node(const voc_node&); + voc_node& operator=(const voc_node&); + }; + + template + class vob_node : public vob_base_node + { + public: + + typedef expression_node* expression_ptr; + typedef std::pair branch_t; + typedef Operation operation_t; + + // variable op constant node + explicit vob_node(const T& var, const expression_ptr brnch) + : v_(var) + { + init_branches<1>(branch_,brnch); + } + + ~vob_node() + { + cleanup_branches::execute(branch_); + } + + inline T value() const + { + return Operation::process(v_,branch_[0].first->value()); + } + + inline operator_type operation() const + { + return Operation::operation(); + } + + inline const T& v() const + { + return v_; + } + + inline expression_node* branch(const std::size_t&) const + { + return branch_[0].first; + } + + private: + + vob_node(const vob_node&); + vob_node& operator=(const vob_node&); + + const T& v_; + branch_t branch_[1]; + }; + + template + class bov_node : public bov_base_node + { + public: + + typedef expression_node* expression_ptr; + typedef std::pair branch_t; + typedef Operation operation_t; + + // variable op constant node + explicit bov_node(const expression_ptr brnch, const T& var) + : v_(var) + { + init_branches<1>(branch_,brnch); + } + + ~bov_node() + { + cleanup_branches::execute(branch_); + } + + inline T value() const + { + return Operation::process(branch_[0].first->value(),v_); + } + + inline operator_type operation() const + { + return Operation::operation(); + } + + inline const T& v() const + { + return v_; + } + + inline expression_node* branch(const std::size_t&) const + { + return branch_[0].first; + } + + private: + + bov_node(const bov_node&); + bov_node& operator=(const bov_node&); + + const T& v_; + branch_t branch_[1]; + }; + + template + class cob_node : public cob_base_node + { + public: + + typedef expression_node* expression_ptr; + typedef std::pair branch_t; + typedef Operation operation_t; + + // variable op constant node + explicit cob_node(const T const_var, const expression_ptr brnch) + : c_(const_var) + { + init_branches<1>(branch_,brnch); + } + + ~cob_node() + { + cleanup_branches::execute(branch_); + } + + inline T value() const + { + return Operation::process(c_,branch_[0].first->value()); + } + + inline operator_type operation() const + { + return Operation::operation(); + } + + inline const T c() const + { + return c_; + } + + inline void set_c(const T new_c) + { + (*const_cast(&c_)) = new_c; + } + + inline expression_node* branch(const std::size_t&) const + { + return branch_[0].first; + } + + inline expression_node* move_branch(const std::size_t&) + { + branch_[0].second = false; + return branch_[0].first; + } + + private: + + cob_node(const cob_node&); + cob_node& operator=(const cob_node&); + + const T c_; + branch_t branch_[1]; + }; + + template + class boc_node : public boc_base_node + { + public: + + typedef expression_node* expression_ptr; + typedef std::pair branch_t; + typedef Operation operation_t; + + // variable op constant node + explicit boc_node(const expression_ptr brnch, const T const_var) + : c_(const_var) + { + init_branches<1>(branch_,brnch); + } + + ~boc_node() + { + cleanup_branches::execute(branch_); + } + + inline T value() const + { + return Operation::process(branch_[0].first->value(),c_); + } + + inline operator_type operation() const + { + return Operation::operation(); + } + + inline const T c() const + { + return c_; + } + + inline void set_c(const T new_c) + { + (*const_cast(&c_)) = new_c; + } + + inline expression_node* branch(const std::size_t&) const + { + return branch_[0].first; + } + + inline expression_node* move_branch(const std::size_t&) + { + branch_[0].second = false; + return branch_[0].first; + } + + private: + + boc_node(const boc_node&); + boc_node& operator=(const boc_node&); + + const T c_; + branch_t branch_[1]; + }; + + #ifndef exprtk_disable_string_capabilities + template + class sos_node : public sos_base_node + { + public: + + typedef expression_node* expression_ptr; + typedef Operation operation_t; + + // string op string node + explicit sos_node(SType0 p0, SType1 p1) + : s0_(p0), + s1_(p1) + {} + + inline T value() const + { + return Operation::process(s0_,s1_); + } + + inline typename expression_node::node_type type() const + { + return Operation::type(); + } + + inline operator_type operation() const + { + return Operation::operation(); + } + + inline std::string& s0() + { + return s0_; + } + + inline std::string& s1() + { + return s1_; + } + + protected: + + SType0 s0_; + SType1 s1_; + + private: + + sos_node(sos_node&); + sos_node& operator=(sos_node&); + }; + + template + class str_xrox_node : public sos_base_node + { + public: + + typedef expression_node* expression_ptr; + typedef Operation operation_t; + + // string-range op string node + explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0) + : s0_ (p0 ), + s1_ (p1 ), + rp0_(rp0) + {} + + ~str_xrox_node() + { + rp0_.free(); + } + + inline T value() const + { + std::size_t r0 = 0; + std::size_t r1 = 0; + + if (rp0_(r0, r1, s0_.size())) + return Operation::process(s0_.substr(r0, (r1 - r0) + 1), s1_); + else + return T(0); + } + + inline typename expression_node::node_type type() const + { + return Operation::type(); + } + + inline operator_type operation() const + { + return Operation::operation(); + } + + inline std::string& s0() + { + return s0_; + } + + inline std::string& s1() + { + return s1_; + } + + protected: + + SType0 s0_; + SType1 s1_; + RangePack rp0_; + + private: + + str_xrox_node(str_xrox_node&); + str_xrox_node& operator=(str_xrox_node&); + }; + + template + class str_xoxr_node : public sos_base_node + { + public: + + typedef expression_node* expression_ptr; + typedef Operation operation_t; + + // string op string range node + explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1) + : s0_ (p0 ), + s1_ (p1 ), + rp1_(rp1) + {} + + ~str_xoxr_node() + { + rp1_.free(); + } + + inline T value() const + { + std::size_t r0 = 0; + std::size_t r1 = 0; + + if (rp1_(r0, r1, s1_.size())) + return Operation::process(s0_, s1_.substr(r0, (r1 - r0) + 1)); + else + return T(0); + } + + inline typename expression_node::node_type type() const + { + return Operation::type(); + } + + inline operator_type operation() const + { + return Operation::operation(); + } + + inline std::string& s0() + { + return s0_; + } + + inline std::string& s1() + { + return s1_; + } + + protected: + + SType0 s0_; + SType1 s1_; + RangePack rp1_; + + private: + + str_xoxr_node(str_xoxr_node&); + str_xoxr_node& operator=(str_xoxr_node&); + }; + + template + class str_xroxr_node : public sos_base_node + { + public: + + typedef expression_node* expression_ptr; + typedef Operation operation_t; + + // string-range op string-range node + explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1) + : s0_ (p0 ), + s1_ (p1 ), + rp0_(rp0), + rp1_(rp1) + {} + + ~str_xroxr_node() + { + rp0_.free(); + rp1_.free(); + } + + inline T value() const + { + std::size_t r0_0 = 0; + std::size_t r0_1 = 0; + std::size_t r1_0 = 0; + std::size_t r1_1 = 0; + + if ( + rp0_(r0_0, r1_0, s0_.size()) && + rp1_(r0_1, r1_1, s1_.size()) + ) + { + return Operation::process( + s0_.substr(r0_0, (r1_0 - r0_0) + 1), + s1_.substr(r0_1, (r1_1 - r0_1) + 1) + ); + } + else + return T(0); + } + + inline typename expression_node::node_type type() const + { + return Operation::type(); + } + + inline operator_type operation() const + { + return Operation::operation(); + } + + inline std::string& s0() + { + return s0_; + } + + inline std::string& s1() + { + return s1_; + } + + protected: + + SType0 s0_; + SType1 s1_; + RangePack rp0_; + RangePack rp1_; + + private: + + str_xroxr_node(str_xroxr_node&); + str_xroxr_node& operator=(str_xroxr_node&); + }; + + template + class str_sogens_node : public binary_node + { + public: + + typedef expression_node * expression_ptr; + typedef string_base_node* str_base_ptr; + typedef range_pack range_t; + typedef range_t* range_ptr; + typedef range_interface irange_t; + typedef irange_t* irange_ptr; + + str_sogens_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1), + str0_base_ptr_ (0), + str1_base_ptr_ (0), + str0_range_ptr_(0), + str1_range_ptr_(0) + { + if (is_generally_string_node(binary_node::branch_[0].first)) + { + str0_base_ptr_ = dynamic_cast(binary_node::branch_[0].first); + + if (0 == str0_base_ptr_) + return; + + irange_ptr range = dynamic_cast(binary_node::branch_[0].first); + + if (0 == range) + return; + + str0_range_ptr_ = &(range->range_ref()); + } + + if (is_generally_string_node(binary_node::branch_[1].first)) + { + str1_base_ptr_ = dynamic_cast(binary_node::branch_[1].first); + + if (0 == str1_base_ptr_) + return; + + irange_ptr range = dynamic_cast(binary_node::branch_[1].first); + + if (0 == range) + return; + + str1_range_ptr_ = &(range->range_ref()); + } + } + + inline T value() const + { + if ( + str0_base_ptr_ && + str1_base_ptr_ && + str0_range_ptr_ && + str1_range_ptr_ + ) + { + binary_node::branch_[0].first->value(); + binary_node::branch_[1].first->value(); + + std::size_t str0_r0 = 0; + std::size_t str0_r1 = 0; + + std::size_t str1_r0 = 0; + std::size_t str1_r1 = 0; + + range_t& range0 = (*str0_range_ptr_); + range_t& range1 = (*str1_range_ptr_); + + if ( + range0(str0_r0, str0_r1, str0_base_ptr_->size()) && + range1(str1_r0, str1_r1, str1_base_ptr_->size()) + ) + { + return Operation::process( + str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0) + 1), + str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0) + 1) + ); + } + } + + return std::numeric_limits::quiet_NaN(); + } + + inline typename expression_node::node_type type() const + { + return Operation::type(); + } + + inline operator_type operation() const + { + return Operation::operation(); + } + + private: + + str_sogens_node(str_sogens_node&); + str_sogens_node& operator=(str_sogens_node&); + + str_base_ptr str0_base_ptr_; + str_base_ptr str1_base_ptr_; + range_ptr str0_range_ptr_; + range_ptr str1_range_ptr_; + }; + + template + class sosos_node : public sosos_base_node + { + public: + + typedef expression_node* expression_ptr; + typedef Operation operation_t; + + // variable op variable node + explicit sosos_node(SType0 p0, SType1 p1, SType2 p2) + : s0_(p0), + s1_(p1), + s2_(p2) + {} + + inline T value() const + { + return Operation::process(s0_,s1_,s2_); + } + + inline typename expression_node::node_type type() const + { + return Operation::type(); + } + + inline operator_type operation() const + { + return Operation::operation(); + } + + inline std::string& s0() + { + return s0_; + } + + inline std::string& s1() + { + return s1_; + } + + inline std::string& s2() + { + return s2_; + } + + protected: + + SType0 s0_; + SType1 s1_; + SType2 s2_; + + private: + + sosos_node(sosos_node&); + sosos_node& operator=(sosos_node&); + }; + #endif + + template + class ipow_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + typedef PowOp operation_t; + + explicit ipow_node(const T& v) + : v_(v) + {} + + inline T value() const + { + return PowOp::result(v_); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_ipow; + } + + private: + + ipow_node(const ipow_node&); + ipow_node& operator=(const ipow_node&); + + const T& v_; + }; + + template + class bipow_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + typedef std::pair branch_t; + typedef PowOp operation_t; + + explicit bipow_node(expression_ptr brnch) + { + init_branches<1>(branch_, brnch); + } + + ~bipow_node() + { + cleanup_branches::execute(branch_); + } + + inline T value() const + { + return PowOp::result(branch_[0].first->value()); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_ipow; + } + + private: + + bipow_node(const bipow_node&); + bipow_node& operator=(const bipow_node&); + + branch_t branch_[1]; + }; + + template + class ipowinv_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + typedef PowOp operation_t; + + explicit ipowinv_node(const T& v) + : v_(v) + {} + + inline T value() const + { + return (T(1) / PowOp::result(v_)); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_ipowinv; + } + + private: + + ipowinv_node(const ipowinv_node&); + ipowinv_node& operator=(const ipowinv_node&); + + const T& v_; + }; + + template + class bipowninv_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + typedef std::pair branch_t; + typedef PowOp operation_t; + + explicit bipowninv_node(expression_ptr brnch) + { + init_branches<1>(branch_, brnch); + } + + ~bipowninv_node() + { + cleanup_branches::execute(branch_); + } + + inline T value() const + { + return (T(1) / PowOp::result(branch_[0].first->value())); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_ipowinv; + } + + private: + + bipowninv_node(const bipowninv_node&); + bipowninv_node& operator=(const bipowninv_node&); + + branch_t branch_[1]; + }; + + template + inline bool is_vov_node(const expression_node* node) + { + return (0 != dynamic_cast*>(node)); + } + + template + inline bool is_cov_node(const expression_node* node) + { + return (0 != dynamic_cast*>(node)); + } + + template + inline bool is_voc_node(const expression_node* node) + { + return (0 != dynamic_cast*>(node)); + } + + template + inline bool is_cob_node(const expression_node* node) + { + return (0 != dynamic_cast*>(node)); + } + + template + inline bool is_boc_node(const expression_node* node) + { + return (0 != dynamic_cast*>(node)); + } + + template + inline bool is_t0ot1ot2_node(const expression_node* node) + { + return (0 != dynamic_cast*>(node)); + } + + template + inline bool is_t0ot1ot2ot3_node(const expression_node* node) + { + return (0 != dynamic_cast*>(node)); + } + + template + inline bool is_uv_node(const expression_node* node) + { + return (0 != dynamic_cast*>(node)); + } + + template + inline bool is_string_node(const expression_node* node) + { + return node && (expression_node::e_stringvar == node->type()); + } + + template + inline bool is_string_range_node(const expression_node* node) + { + return node && (expression_node::e_stringvarrng == node->type()); + } + + template + inline bool is_const_string_node(const expression_node* node) + { + return node && (expression_node::e_stringconst == node->type()); + } + + template + inline bool is_const_string_range_node(const expression_node* node) + { + return node && (expression_node::e_cstringvarrng == node->type()); + } + + template + inline bool is_string_assignment_node(const expression_node* node) + { + return node && (expression_node::e_strass == node->type()); + } + + template + inline bool is_string_concat_node(const expression_node* node) + { + return node && (expression_node::e_strconcat == node->type()); + } + + template + inline bool is_string_function_node(const expression_node* node) + { + return node && (expression_node::e_strfunction == node->type()); + } + + template + inline bool is_string_condition_node(const expression_node* node) + { + return node && (expression_node::e_strcondition == node->type()); + } + + template + inline bool is_string_ccondition_node(const expression_node* node) + { + return node && (expression_node::e_strccondition == node->type()); + } + + template + inline bool is_string_vararg_node(const expression_node* node) + { + return node && (expression_node::e_stringvararg == node->type()); + } + + template + inline bool is_genricstring_range_node(const expression_node* node) + { + return node && (expression_node::e_strgenrange == node->type()); + } + + template + inline bool is_generally_string_node(const expression_node* node) + { + if (node) + { + switch (node->type()) + { + case expression_node::e_stringvar : + case expression_node::e_stringconst : + case expression_node::e_stringvarrng : + case expression_node::e_cstringvarrng : + case expression_node::e_strgenrange : + case expression_node::e_strass : + case expression_node::e_strconcat : + case expression_node::e_strfunction : + case expression_node::e_strcondition : + case expression_node::e_strccondition : + case expression_node::e_stringvararg : return true; + default : return false; + } + } + + return false; + } + + class node_allocator + { + public: + + template + inline expression_node* allocate(OpType& operation, ExprNode (&branch)[1]) + { + return allocate(operation, branch[0]); + } + + template + inline expression_node* allocate(OpType& operation, ExprNode (&branch)[2]) + { + return allocate(operation, branch[0], branch[1]); + } + + template + inline expression_node* allocate(OpType& operation, ExprNode (&branch)[3]) + { + return allocate(operation, branch[0], branch[1], branch[2]); + } + + template + inline expression_node* allocate(OpType& operation, ExprNode (&branch)[4]) + { + return allocate(operation, branch[0], branch[1], branch[2], branch[3]); + } + + template + inline expression_node* allocate(OpType& operation, ExprNode (&branch)[5]) + { + return allocate(operation, branch[0],branch[1], branch[2], branch[3], branch[4]); + } + + template + inline expression_node* allocate(OpType& operation, ExprNode (&branch)[6]) + { + return allocate(operation, branch[0], branch[1], branch[2], branch[3], branch[4], branch[5]); + } + + template + inline expression_node* allocate() const + { + return (new node_type()); + } + + template class Sequence> + inline expression_node* allocate(const Sequence& seq) const + { + return (new node_type(seq)); + } + + template + inline expression_node* allocate(T1& t1) const + { + return (new node_type(t1)); + } + + template + inline expression_node* allocate_c(const T1& t1) const + { + return (new node_type(t1)); + } + + template + inline expression_node* allocate(const T1& t1, const T2& t2) const + { + return (new node_type(t1, t2)); + } + + template + inline expression_node* allocate_cr(const T1& t1, T2& t2) const + { + return (new node_type(t1, t2)); + } + + template + inline expression_node* allocate_rc(T1& t1, const T2& t2) const + { + return (new node_type(t1, t2)); + } + + template + inline expression_node* allocate_rr(T1& t1, T2& t2) const + { + return (new node_type(t1, t2)); + } + + template + inline expression_node* allocate_tt(T1 t1, T2 t2) const + { + return (new node_type(t1, t2)); + } + + template + inline expression_node* allocate_ttt(T1 t1, T2 t2, T3 t3) const + { + return (new node_type(t1, t2, t3)); + } + + template + inline expression_node* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const + { + return (new node_type(t1, t2, t3, t4)); + } + + template + inline expression_node* allocate_rrr(T1& t1, T2& t2, T3& t3) const + { + return (new node_type(t1, t2, t3)); + } + + template + inline expression_node* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const + { + return (new node_type(t1, t2, t3, t4)); + } + + template + inline expression_node* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const + { + return (new node_type(t1, t2, t3, t4, t5)); + } + + template + inline expression_node* allocate(const T1& t1, const T2& t2, + const T3& t3) const + { + return (new node_type(t1, t2, t3)); + } + + template + inline expression_node* allocate(const T1& t1, const T2& t2, + const T3& t3, const T4& t4) const + { + return (new node_type(t1, t2, t3, t4)); + } + + template + inline expression_node* allocate(const T1& t1, const T2& t2, + const T3& t3, const T4& t4, + const T5& t5) const + { + return (new node_type(t1, t2, t3, t4, t5)); + } + + template + inline expression_node* allocate(const T1& t1, const T2& t2, + const T3& t3, const T4& t4, + const T5& t5, const T6& t6) const + { + return (new node_type(t1, t2, t3, t4, t5, t6)); + } + + template + inline expression_node* allocate(const T1& t1, const T2& t2, + const T3& t3, const T4& t4, + const T5& t5, const T6& t6, + const T7& t7) const + { + return (new node_type(t1, t2, t3, t4, t5, t6, t7)); + } + + template + inline expression_node* allocate(const T1& t1, const T2& t2, + const T3& t3, const T4& t4, + const T5& t5, const T6& t6, + const T7& t7, const T8& t8) const + { + return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8)); + } + + template + inline expression_node* allocate(const T1& t1, const T2& t2, + const T3& t3, const T4& t4, + const T5& t5, const T6& t6, + const T7& t7, const T8& t8, + const T9& t9) const + { + return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9)); + } + + template + inline expression_node* allocate(const T1& t1, const T2& t2, + const T3& t3, const T4& t4, + const T5& t5, const T6& t6, + const T7& t7, const T8& t8, + const T9& t9, const T10& t10) const + { + return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)); + } + + template + inline expression_node* allocate_type(T1 t1, T2 t2, T3 t3) const + { + return (new node_type(t1, t2, t3)); + } + + template + inline expression_node* allocate_type(T1 t1, T2 t2, + T3 t3, T4 t4) const + { + return (new node_type(t1, t2, t3, t4)); + } + + template + inline expression_node* allocate_type(T1 t1, T2 t2, + T3 t3, T4 t4, + T5 t5) const + { + return (new node_type(t1, t2, t3, t4, t5)); + } + + template + inline expression_node* allocate_type(T1 t1, T2 t2, + T3 t3, T4 t4, + T5 t5, T6 t6) const + { + return (new node_type(t1, t2, t3, t4, t5, t6)); + } + + template + inline expression_node* allocate_type(T1 t1, T2 t2, + T3 t3, T4 t4, + T5 t5, T6 t6, + T7 t7) const + { + return (new node_type(t1, t2, t3, t4, t5, t6, t7)); + } + + template + void inline free(expression_node*& e) const + { + delete e; + e = 0; + } + }; + + inline void load_operations_map(std::multimap& m) + { + #define register_op(Symbol,Type,Args) \ + m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \ + + register_op( "abs", e_abs , 1) + register_op( "acos", e_acos , 1) + register_op( "acosh", e_acosh , 1) + register_op( "asin", e_asin , 1) + register_op( "asinh", e_asinh , 1) + register_op( "atan", e_atan , 1) + register_op( "atanh", e_atanh , 1) + register_op( "ceil", e_ceil , 1) + register_op( "cos", e_cos , 1) + register_op( "cosh", e_cosh , 1) + register_op( "exp", e_exp , 1) + register_op( "expm1", e_expm1 , 1) + register_op( "floor", e_floor , 1) + register_op( "log", e_log , 1) + register_op( "log10", e_log10 , 1) + register_op( "log2", e_log2 , 1) + register_op( "log1p", e_log1p , 1) + register_op( "round", e_round , 1) + register_op( "sin", e_sin , 1) + register_op( "sinc", e_sinc , 1) + register_op( "sinh", e_sinh , 1) + register_op( "sec", e_sec , 1) + register_op( "csc", e_csc , 1) + register_op( "sqrt", e_sqrt , 1) + register_op( "tan", e_tan , 1) + register_op( "tanh", e_tanh , 1) + register_op( "cot", e_cot , 1) + register_op( "rad2deg", e_r2d , 1) + register_op( "deg2rad", e_d2r , 1) + register_op( "deg2grad", e_d2g , 1) + register_op( "grad2deg", e_g2d , 1) + register_op( "sgn", e_sgn , 1) + register_op( "not", e_notl , 1) + register_op( "erf", e_erf , 1) + register_op( "erfc", e_erfc , 1) + register_op( "ncdf", e_ncdf , 1) + register_op( "frac", e_frac , 1) + register_op( "trunc", e_trunc , 1) + register_op( "atan2", e_atan2 , 2) + register_op( "mod", e_mod , 2) + register_op( "logn", e_logn , 2) + register_op( "pow", e_pow , 2) + register_op( "root", e_root , 2) + register_op( "roundn", e_roundn , 2) + register_op( "equal", e_equal , 2) + register_op("not_equal", e_nequal , 2) + register_op( "hypot", e_hypot , 2) + register_op( "shr", e_shr , 2) + register_op( "shl", e_shl , 2) + register_op( "clamp", e_clamp , 3) + register_op( "iclamp", e_iclamp , 3) + register_op( "inrange", e_inrange , 3) + #undef register_op + } + + } // namespace details + + class function_traits + { + public: + + function_traits() + : allow_zero_parameters_(false), + has_side_effects_(true), + min_num_args_(0), + max_num_args_(std::numeric_limits::max()) + {} + + inline bool& allow_zero_parameters() + { + return allow_zero_parameters_; + } + + inline bool& has_side_effects() + { + return has_side_effects_; + } + + std::size_t& min_num_args() + { + return min_num_args_; + } + + std::size_t& max_num_args() + { + return max_num_args_; + } + + private: + + bool allow_zero_parameters_; + bool has_side_effects_; + std::size_t min_num_args_; + std::size_t max_num_args_; + }; + + template + void enable_zero_parameters(FunctionType& func) + { + func.allow_zero_parameters() = true; + + if (0 != func.min_num_args()) + { + func.min_num_args() = 0; + } + } + + template + void disable_zero_parameters(FunctionType& func) + { + func.allow_zero_parameters() = false; + } + + template + void enable_has_side_effects(FunctionType& func) + { + func.has_side_effects() = true; + } + + template + void disable_has_side_effects(FunctionType& func) + { + func.has_side_effects() = false; + } + + template + void set_min_num_args(FunctionType& func, const std::size_t& num_args) + { + func.min_num_args() = num_args; + + if ((0 != func.min_num_args()) && func.allow_zero_parameters()) + func.allow_zero_parameters() = false; + } + + template + void set_max_num_args(FunctionType& func, const std::size_t& num_args) + { + func.max_num_args() = num_args; + } + + template + class ifunction : public function_traits + { + public: + + explicit ifunction(const std::size_t& pc) + : param_count(pc) + {} + + virtual ~ifunction() + {} + + #define empty_method_body \ + { \ + return std::numeric_limits::quiet_NaN(); \ + } \ + + inline virtual T operator() () + empty_method_body + + inline virtual T operator() (const T&) + empty_method_body + + inline virtual T operator() (const T&,const T&) + empty_method_body + + inline virtual T operator() (const T&, const T&, const T&) + empty_method_body + + inline virtual T operator() (const T&, const T&, const T&, const T&) + empty_method_body + + inline virtual T operator() (const T&, const T&, const T&, const T&, const T&) + empty_method_body + + inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&) + empty_method_body + + inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&) + empty_method_body + + inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) + empty_method_body + + inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) + empty_method_body + + inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) + empty_method_body + + inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, + const T&) + empty_method_body + + inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, + const T&, const T&) + empty_method_body + + inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, + const T&, const T&, const T&) + empty_method_body + + inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, + const T&, const T&, const T&, const T&) + empty_method_body + + inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, + const T&, const T&, const T&, const T&, const T&) + empty_method_body + + inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, + const T&, const T&, const T&, const T&, const T&, const T&) + empty_method_body + + inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, + const T&, const T&, const T&, const T&, const T&, const T&, const T&) + empty_method_body + + inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, + const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) + empty_method_body + + inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, + const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) + empty_method_body + + inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, + const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) + empty_method_body + + #undef empty_method_body + + std::size_t param_count; + }; + + template + class ivararg_function : public function_traits + { + public: + + virtual ~ivararg_function() + {} + + inline virtual T operator() (const std::vector&) + { + exprtk_debug(("ivararg_function::operator() - Operator has not been overridden.\n")); + return std::numeric_limits::quiet_NaN(); + } + }; + + template + class igeneric_function : public function_traits + { + public: + + enum return_type + { + e_rtrn_scalar = 0, + e_rtrn_string = 1, + e_rtrn_overload = 2 + }; + + typedef T type; + typedef type_store generic_type; + typedef typename generic_type::parameter_list parameter_list_t; + + igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar) + : parameter_sequence(param_seq), + rtrn_type(rtr_type) + {} + + virtual ~igeneric_function() + {} + + #define igeneric_function_empty_body(N) \ + { \ + exprtk_debug(("igeneric_function::operator() - Operator has not been overridden. ["#N"]\n")); \ + return std::numeric_limits::quiet_NaN(); \ + } \ + + // f(i_0,i_1,....,i_N) --> Scalar + inline virtual T operator() (parameter_list_t) + igeneric_function_empty_body(1) + + // f(i_0,i_1,....,i_N) --> String + inline virtual T operator() (std::string&, parameter_list_t) + igeneric_function_empty_body(2) + + // f(psi,i_0,i_1,....,i_N) --> Scalar + inline virtual T operator() (const std::size_t&, parameter_list_t) + igeneric_function_empty_body(3) + + // f(psi,i_0,i_1,....,i_N) --> String + inline virtual T operator() (const std::size_t&, std::string&, parameter_list_t) + igeneric_function_empty_body(4) + + std::string parameter_sequence; + return_type rtrn_type; + }; + + template class parser; + template class expression_helper; + + template + class symbol_table + { + public: + + typedef T (*ff00_functor)(); + typedef T (*ff01_functor)(T); + typedef T (*ff02_functor)(T, T); + typedef T (*ff03_functor)(T, T, T); + typedef T (*ff04_functor)(T, T, T, T); + typedef T (*ff05_functor)(T, T, T, T, T); + typedef T (*ff06_functor)(T, T, T, T, T, T); + typedef T (*ff07_functor)(T, T, T, T, T, T, T); + typedef T (*ff08_functor)(T, T, T, T, T, T, T, T); + typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T); + typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T); + typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T); + typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T); + typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T); + typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T); + typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T); + + protected: + + struct freefunc00 : public exprtk::ifunction + { + using exprtk::ifunction::operator(); + + explicit freefunc00(ff00_functor ff) : exprtk::ifunction(0), f(ff) {} + inline T operator() () + { return f(); } + ff00_functor f; + }; + + struct freefunc01 : public exprtk::ifunction + { + using exprtk::ifunction::operator(); + + explicit freefunc01(ff01_functor ff) : exprtk::ifunction(1), f(ff) {} + inline T operator() (const T& v0) + { return f(v0); } + ff01_functor f; + }; + + struct freefunc02 : public exprtk::ifunction + { + using exprtk::ifunction::operator(); + + explicit freefunc02(ff02_functor ff) : exprtk::ifunction(2), f(ff) {} + inline T operator() (const T& v0, const T& v1) + { return f(v0, v1); } + ff02_functor f; + }; + + struct freefunc03 : public exprtk::ifunction + { + using exprtk::ifunction::operator(); + + explicit freefunc03(ff03_functor ff) : exprtk::ifunction(3), f(ff) {} + inline T operator() (const T& v0, const T& v1, const T& v2) + { return f(v0, v1, v2); } + ff03_functor f; + }; + + struct freefunc04 : public exprtk::ifunction + { + using exprtk::ifunction::operator(); + + explicit freefunc04(ff04_functor ff) : exprtk::ifunction(4), f(ff) {} + inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3) + { return f(v0, v1, v2, v3); } + ff04_functor f; + }; + + struct freefunc05 : public exprtk::ifunction + { + using exprtk::ifunction::operator(); + + explicit freefunc05(ff05_functor ff) : exprtk::ifunction(5), f(ff) {} + inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) + { return f(v0, v1, v2, v3, v4); } + ff05_functor f; + }; + + struct freefunc06 : public exprtk::ifunction + { + using exprtk::ifunction::operator(); + + explicit freefunc06(ff06_functor ff) : exprtk::ifunction(6), f(ff) {} + inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) + { return f(v0, v1, v2, v3, v4, v5); } + ff06_functor f; + }; + + struct freefunc07 : public exprtk::ifunction + { + using exprtk::ifunction::operator(); + + explicit freefunc07(ff07_functor ff) : exprtk::ifunction(7), f(ff) {} + inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, + const T& v5, const T& v6) + { return f(v0, v1, v2, v3, v4, v5, v6); } + ff07_functor f; + }; + + struct freefunc08 : public exprtk::ifunction + { + using exprtk::ifunction::operator(); + + explicit freefunc08(ff08_functor ff) : exprtk::ifunction(8), f(ff) {} + inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, + const T& v5, const T& v6, const T& v7) + { return f(v0, v1, v2, v3, v4, v5, v6, v7); } + ff08_functor f; + }; + + struct freefunc09 : public exprtk::ifunction + { + using exprtk::ifunction::operator(); + + explicit freefunc09(ff09_functor ff) : exprtk::ifunction(9), f(ff) {} + inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, + const T& v5, const T& v6, const T& v7, const T& v8) + { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); } + ff09_functor f; + }; + + struct freefunc10 : public exprtk::ifunction + { + using exprtk::ifunction::operator(); + + explicit freefunc10(ff10_functor ff) : exprtk::ifunction(10), f(ff) {} + inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, + const T& v5, const T& v6, const T& v7, const T& v8, const T& v9) + { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); } + ff10_functor f; + }; + + struct freefunc11 : public exprtk::ifunction + { + using exprtk::ifunction::operator(); + + explicit freefunc11(ff11_functor ff) : exprtk::ifunction(11), f(ff) {} + inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, + const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10) + { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); } + ff11_functor f; + }; + + struct freefunc12 : public exprtk::ifunction + { + using exprtk::ifunction::operator(); + + explicit freefunc12(ff12_functor ff) : exprtk::ifunction(12), f(ff) {} + inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, + const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, + const T& v10, const T& v11) + { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11); } + ff12_functor f; + }; + + struct freefunc13 : public exprtk::ifunction + { + using exprtk::ifunction::operator(); + + explicit freefunc13(ff13_functor ff) : exprtk::ifunction(13), f(ff) {} + inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, + const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, + const T& v10, const T& v11, const T& v12) + { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12); } + ff13_functor f; + }; + + struct freefunc14 : public exprtk::ifunction + { + using exprtk::ifunction::operator(); + + explicit freefunc14(ff14_functor ff) : exprtk::ifunction(14), f(ff) {} + inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, + const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, + const T& v10, const T& v11, const T& v12, const T& v13) + { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13); } + ff14_functor f; + }; + + struct freefunc15 : public exprtk::ifunction + { + using exprtk::ifunction::operator(); + + explicit freefunc15(ff15_functor ff) : exprtk::ifunction(15), f(ff) {} + inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, + const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, + const T& v10, const T& v11, const T& v12, const T& v13, const T& v14) + { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14); } + ff15_functor f; + }; + + template + struct type_store + { + typedef details::expression_node* expression_ptr; + typedef typename details::variable_node variable_node_t; + typedef ifunction ifunction_t; + typedef ivararg_function ivararg_function_t; + typedef igeneric_function igeneric_function_t; + typedef details::vector_holder vector_t; + #ifndef exprtk_disable_string_capabilities + typedef typename details::stringvar_node stringvar_node_t; + #endif + + typedef Type type_t; + typedef type_t* type_ptr; + typedef std::pair type_pair_t; + typedef std::map type_map_t; + typedef typename type_map_t::iterator tm_itr_t; + typedef typename type_map_t::const_iterator tm_const_itr_t; + + enum { lut_size = 256 }; + + type_map_t map; + std::size_t size; + + type_store() + : size(0) + {} + + inline bool symbol_exists(const std::string& symbol_name) const + { + if (symbol_name.empty()) + return false; + else if (map.end() != map.find(symbol_name)) + return true; + else + return false; + } + + template + inline std::string entity_name(const PtrType& ptr) const + { + if (map.empty()) + return std::string(); + + tm_const_itr_t itr = map.begin(); + + while (map.end() != itr) + { + if (itr->second.second == ptr) + { + return itr->first; + } + else + ++itr; + } + + return std::string(); + } + + inline bool is_constant(const std::string& symbol_name) const + { + if (symbol_name.empty()) + return false; + else + { + const tm_const_itr_t itr = map.find(symbol_name); + + if (map.end() == itr) + return false; + else + return (*itr).second.first; + } + } + + template + inline bool add_impl(const std::string& symbol_name, RType t, const bool is_const) + { + if (symbol_name.size() > 1) + { + for (std::size_t i = 0; i < details::reserved_symbols_size; ++i) + { + if (details::imatch(symbol_name, details::reserved_symbols[i])) + { + return false; + } + } + } + + const tm_itr_t itr = map.find(symbol_name); + + if (map.end() == itr) + { + map[symbol_name] = Tie::make(t,is_const); + ++size; + } + + return true; + } + + struct tie_array + { + static inline std::pair make(std::pair v, const bool is_const = false) + { + return std::make_pair(is_const, new vector_t(v.first, v.second)); + } + }; + + struct tie_stdvec + { + template + static inline std::pair make(std::vector& v, const bool is_const = false) + { + return std::make_pair(is_const, new vector_t(v)); + } + }; + + struct tie_vecview + { + static inline std::pair make(exprtk::vector_view& v, const bool is_const = false) + { + return std::make_pair(is_const, new vector_t(v)); + } + }; + + struct tie_stddeq + { + template + static inline std::pair make(std::deque& v, const bool is_const = false) + { + return std::make_pair(is_const, new vector_t(v)); + } + }; + + template + inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_const = false) + { + return add_impl > + (symbol_name, std::make_pair(v,v_size), is_const); + } + + inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_const = false) + { + return add_impl > + (symbol_name, std::make_pair(v,v_size), is_const); + } + + template + inline bool add(const std::string& symbol_name, std::vector& v, const bool is_const = false) + { + return add_impl&> + (symbol_name, v, is_const); + } + + inline bool add(const std::string& symbol_name, exprtk::vector_view& v, const bool is_const = false) + { + return add_impl&> + (symbol_name, v, is_const); + } + + template + inline bool add(const std::string& symbol_name, std::deque& v, const bool is_const = false) + { + return add_impl&> + (symbol_name, v, is_const); + } + + inline bool add(const std::string& symbol_name, RawType& t, const bool is_const = false) + { + struct tie + { + static inline std::pair make(T& t,const bool is_const = false) + { + return std::make_pair(is_const, new variable_node_t(t)); + } + + #ifndef exprtk_disable_string_capabilities + static inline std::pair make(std::string& t,const bool is_const = false) + { + return std::make_pair(is_const, new stringvar_node_t(t)); + } + #endif + + static inline std::pair make(function_t& t, const bool is_constant = false) + { + return std::make_pair(is_constant,&t); + } + + static inline std::pair make(vararg_function_t& t, const bool is_const = false) + { + return std::make_pair(is_const,&t); + } + + static inline std::pair make(generic_function_t& t, const bool is_constant = false) + { + return std::make_pair(is_constant,&t); + } + }; + + const tm_itr_t itr = map.find(symbol_name); + + if (map.end() == itr) + { + map[symbol_name] = tie::make(t,is_const); + ++size; + } + + return true; + } + + inline type_ptr get(const std::string& symbol_name) const + { + const tm_const_itr_t itr = map.find(symbol_name); + + if (map.end() == itr) + return reinterpret_cast(0); + else + return itr->second.second; + } + + template + struct ptr_match + { + static inline bool test(const PtrType, const void*) + { + return false; + } + }; + + template + struct ptr_match + { + static inline bool test(const variable_node_t* p, const void* ptr) + { + exprtk_debug(("ptr_match::test() - %p <--> %p\n",(void*)(&(p->ref())),ptr)); + return (&(p->ref()) == ptr); + } + }; + + inline type_ptr get_from_varptr(const void* ptr) const + { + tm_const_itr_t itr = map.begin(); + + while (map.end() != itr) + { + type_ptr ret_ptr = itr->second.second; + + if (ptr_match::test(ret_ptr,ptr)) + { + return ret_ptr; + } + + ++itr; + } + + return type_ptr(0); + } + + inline bool remove(const std::string& symbol_name, const bool delete_node = true) + { + const tm_itr_t itr = map.find(symbol_name); + + if (map.end() != itr) + { + struct deleter + { + static inline void process(std::pair& n) { delete n.second; } + static inline void process(std::pair& n) { delete n.second; } + #ifndef exprtk_disable_string_capabilities + static inline void process(std::pair& n) { delete n.second; } + #endif + static inline void process(std::pair&) { } + }; + + if (delete_node) + { + deleter::process((*itr).second); + } + + map.erase(itr); + --size; + + return true; + } + else + return false; + } + + inline RawType& type_ref(const std::string& symbol_name) + { + struct init_type + { + static inline double set(double) { return (0.0); } + static inline double set(long double) { return (0.0); } + static inline float set(float) { return (0.0f); } + static inline std::string set(std::string) { return std::string(""); } + }; + + static RawType null_type = init_type::set(RawType()); + + const tm_const_itr_t itr = map.find(symbol_name); + + if (map.end() == itr) + return null_type; + else + return itr->second.second->ref(); + } + + inline void clear(const bool delete_node = true) + { + struct deleter + { + static inline void process(std::pair& n) { delete n.second; } + static inline void process(std::pair& n) { delete n.second; } + static inline void process(std::pair&) { } + #ifndef exprtk_disable_string_capabilities + static inline void process(std::pair& n) { delete n.second; } + #endif + }; + + if (!map.empty()) + { + if (delete_node) + { + tm_itr_t itr = map.begin(); + tm_itr_t end = map.end (); + + while (end != itr) + { + deleter::process((*itr).second); + ++itr; + } + } + + map.clear(); + } + + size = 0; + } + + template class Sequence> + inline std::size_t get_list(Sequence,Allocator>& list) const + { + std::size_t count = 0; + + if (!map.empty()) + { + tm_const_itr_t itr = map.begin(); + tm_const_itr_t end = map.end (); + + while (end != itr) + { + list.push_back(std::make_pair((*itr).first,itr->second.second->ref())); + ++itr; + ++count; + } + } + + return count; + } + + template class Sequence> + inline std::size_t get_list(Sequence& vlist) const + { + std::size_t count = 0; + + if (!map.empty()) + { + tm_const_itr_t itr = map.begin(); + tm_const_itr_t end = map.end (); + + while (end != itr) + { + vlist.push_back((*itr).first); + ++itr; + ++count; + } + } + + return count; + } + }; + + typedef details::expression_node* expression_ptr; + typedef typename details::variable_node variable_t; + typedef typename details::vector_holder vector_holder_t; + typedef variable_t* variable_ptr; + #ifndef exprtk_disable_string_capabilities + typedef typename details::stringvar_node stringvar_t; + typedef stringvar_t* stringvar_ptr; + #endif + typedef ifunction function_t; + typedef ivararg_function vararg_function_t; + typedef igeneric_function generic_function_t; + typedef function_t* function_ptr; + typedef vararg_function_t* vararg_function_ptr; + typedef generic_function_t* generic_function_ptr; + + static const std::size_t lut_size = 256; + + // Symbol Table Holder + struct control_block + { + struct st_data + { + type_store,T> variable_store; + #ifndef exprtk_disable_string_capabilities + type_store,std::string> stringvar_store; + #endif + type_store,ifunction > function_store; + type_store,ivararg_function > vararg_function_store; + type_store,igeneric_function > generic_function_store; + type_store,igeneric_function > string_function_store; + type_store,igeneric_function > overload_function_store; + type_store vector_store; + + st_data() + { + for (std::size_t i = 0; i < details::reserved_words_size; ++i) + { + reserved_symbol_table_.insert(details::reserved_words[i]); + } + + for (std::size_t i = 0; i < details::reserved_symbols_size; ++i) + { + reserved_symbol_table_.insert(details::reserved_symbols[i]); + } + } + + ~st_data() + { + for (std::size_t i = 0; i < free_function_list_.size(); ++i) + { + delete free_function_list_[i]; + } + } + + inline bool is_reserved_symbol(const std::string& symbol) const + { + return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol)); + } + + static inline st_data* create() + { + return (new st_data); + } + + static inline void destroy(st_data*& sd) + { + delete sd; + sd = reinterpret_cast(0); + } + + std::list local_symbol_list_; + std::list local_stringvar_list_; + std::set reserved_symbol_table_; + std::vector*> free_function_list_; + }; + + control_block() + : ref_count(1), + data_(st_data::create()) + {} + + explicit control_block(st_data* data) + : ref_count(1), + data_(data) + {} + + ~control_block() + { + if (data_ && (0 == ref_count)) + { + st_data::destroy(data_); + } + } + + static inline control_block* create() + { + return (new control_block); + } + + template + static inline void destroy(control_block*& cntrl_blck, SymTab* sym_tab) + { + if (cntrl_blck) + { + if ( + (0 != cntrl_blck->ref_count) && + (0 == --cntrl_blck->ref_count) + ) + { + if (sym_tab) + sym_tab->clear(); + + delete cntrl_blck; + } + + cntrl_blck = 0; + } + } + + std::size_t ref_count; + st_data* data_; + }; + + public: + + symbol_table() + : control_block_(control_block::create()) + { + clear(); + } + + ~symbol_table() + { + control_block::destroy(control_block_,this); + } + + symbol_table(const symbol_table& st) + { + control_block_ = st.control_block_; + control_block_->ref_count++; + } + + inline symbol_table& operator=(const symbol_table& st) + { + if (this != &st) + { + control_block::destroy(control_block_,reinterpret_cast*>(0)); + + control_block_ = st.control_block_; + control_block_->ref_count++; + } + + return (*this); + } + + inline bool operator==(const symbol_table& st) const + { + return (this == &st) || (control_block_ == st.control_block_); + } + + inline void clear_variables(const bool delete_node = true) + { + local_data().variable_store.clear(delete_node); + } + + inline void clear_functions() + { + local_data().function_store.clear(); + } + + inline void clear_strings() + { + #ifndef exprtk_disable_string_capabilities + local_data().stringvar_store.clear(); + #endif + } + + inline void clear_vectors() + { + local_data().vector_store.clear(); + } + + inline void clear_local_constants() + { + local_data().local_symbol_list_.clear(); + } + + inline void clear() + { + if (!valid()) return; + clear_variables (); + clear_functions (); + clear_strings (); + clear_vectors (); + clear_local_constants(); + } + + inline std::size_t variable_count() const + { + if (valid()) + return local_data().variable_store.size; + else + return 0; + } + + #ifndef exprtk_disable_string_capabilities + inline std::size_t stringvar_count() const + { + if (valid()) + return local_data().stringvar_store.size; + else + return 0; + } + #endif + + inline std::size_t function_count() const + { + if (valid()) + return local_data().function_store.size; + else + return 0; + } + + inline std::size_t vector_count() const + { + if (valid()) + return local_data().vector_store.size; + else + return 0; + } + + inline variable_ptr get_variable(const std::string& variable_name) const + { + if (!valid()) + return reinterpret_cast(0); + else if (!valid_symbol(variable_name)) + return reinterpret_cast(0); + else + return local_data().variable_store.get(variable_name); + } + + inline variable_ptr get_variable(const T& var_ref) const + { + if (!valid()) + return reinterpret_cast(0); + else + return local_data().variable_store.get_from_varptr( + reinterpret_cast(&var_ref)); + } + + #ifndef exprtk_disable_string_capabilities + inline stringvar_ptr get_stringvar(const std::string& string_name) const + { + if (!valid()) + return reinterpret_cast(0); + else if (!valid_symbol(string_name)) + return reinterpret_cast(0); + else + return local_data().stringvar_store.get(string_name); + } + #endif + + inline function_ptr get_function(const std::string& function_name) const + { + if (!valid()) + return reinterpret_cast(0); + else if (!valid_symbol(function_name)) + return reinterpret_cast(0); + else + return local_data().function_store.get(function_name); + } + + inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const + { + if (!valid()) + return reinterpret_cast(0); + else if (!valid_symbol(vararg_function_name)) + return reinterpret_cast(0); + else + return local_data().vararg_function_store.get(vararg_function_name); + } + + inline generic_function_ptr get_generic_function(const std::string& function_name) const + { + if (!valid()) + return reinterpret_cast(0); + else if (!valid_symbol(function_name)) + return reinterpret_cast(0); + else + return local_data().generic_function_store.get(function_name); + } + + inline generic_function_ptr get_string_function(const std::string& function_name) const + { + if (!valid()) + return reinterpret_cast(0); + else if (!valid_symbol(function_name)) + return reinterpret_cast(0); + else + return local_data().string_function_store.get(function_name); + } + + inline generic_function_ptr get_overload_function(const std::string& function_name) const + { + if (!valid()) + return reinterpret_cast(0); + else if (!valid_symbol(function_name)) + return reinterpret_cast(0); + else + return local_data().overload_function_store.get(function_name); + } + + typedef vector_holder_t* vector_holder_ptr; + + inline vector_holder_ptr get_vector(const std::string& vector_name) const + { + if (!valid()) + return reinterpret_cast(0); + else if (!valid_symbol(vector_name)) + return reinterpret_cast(0); + else + return local_data().vector_store.get(vector_name); + } + + inline T& variable_ref(const std::string& symbol_name) + { + static T null_var = T(0); + if (!valid()) + return null_var; + else if (!valid_symbol(symbol_name)) + return null_var; + else + return local_data().variable_store.type_ref(symbol_name); + } + + #ifndef exprtk_disable_string_capabilities + inline std::string& stringvar_ref(const std::string& symbol_name) + { + static std::string null_stringvar; + if (!valid()) + return null_stringvar; + else if (!valid_symbol(symbol_name)) + return null_stringvar; + else + return local_data().stringvar_store.type_ref(symbol_name); + } + #endif + + inline bool is_constant_node(const std::string& symbol_name) const + { + if (!valid()) + return false; + else if (!valid_symbol(symbol_name)) + return false; + else + return local_data().variable_store.is_constant(symbol_name); + } + + #ifndef exprtk_disable_string_capabilities + inline bool is_constant_string(const std::string& symbol_name) const + { + if (!valid()) + return false; + else if (!valid_symbol(symbol_name)) + return false; + else if (!local_data().stringvar_store.symbol_exists(symbol_name)) + return false; + else + return local_data().stringvar_store.is_constant(symbol_name); + } + #endif + + inline bool create_variable(const std::string& variable_name, const T& value = T(0)) + { + if (!valid()) + return false; + else if (!valid_symbol(variable_name)) + return false; + else if (symbol_exists(variable_name)) + return false; + + local_data().local_symbol_list_.push_back(value); + T& t = local_data().local_symbol_list_.back(); + + return add_variable(variable_name,t); + } + + #ifndef exprtk_disable_string_capabilities + inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string("")) + { + if (!valid()) + return false; + else if (!valid_symbol(stringvar_name)) + return false; + else if (symbol_exists(stringvar_name)) + return false; + + local_data().local_stringvar_list_.push_back(value); + std::string& s = local_data().local_stringvar_list_.back(); + + return add_stringvar(stringvar_name,s); + } + #endif + + inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false) + { + if (!valid()) + return false; + else if (!valid_symbol(variable_name)) + return false; + else if (symbol_exists(variable_name)) + return false; + else + return local_data().variable_store.add(variable_name,t,is_constant); + } + + inline bool add_constant(const std::string& constant_name, const T& value) + { + if (!valid()) + return false; + else if (!valid_symbol(constant_name)) + return false; + else if (symbol_exists(constant_name)) + return false; + + local_data().local_symbol_list_.push_back(value); + T& t = local_data().local_symbol_list_.back(); + + return add_variable(constant_name,t,true); + } + + #ifndef exprtk_disable_string_capabilities + inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false) + { + if (!valid()) + return false; + else if (!valid_symbol(stringvar_name)) + return false; + else if (symbol_exists(stringvar_name)) + return false; + else + return local_data().stringvar_store.add(stringvar_name,s,is_constant); + } + #endif + + inline bool add_function(const std::string& function_name, function_t& function) + { + if (!valid()) + return false; + else if (!valid_symbol(function_name)) + return false; + else if (symbol_exists(function_name)) + return false; + else + return local_data().function_store.add(function_name,function); + } + + inline bool add_function(const std::string& vararg_function_name, vararg_function_t& vararg_function) + { + if (!valid()) + return false; + else if (!valid_symbol(vararg_function_name)) + return false; + else if (symbol_exists(vararg_function_name)) + return false; + else + return local_data().vararg_function_store.add(vararg_function_name,vararg_function); + } + + inline bool add_function(const std::string& function_name, generic_function_t& function) + { + if (!valid()) + return false; + else if (!valid_symbol(function_name)) + return false; + else if (symbol_exists(function_name)) + return false; + else if ( + ( + (generic_function_t::e_rtrn_scalar == function.rtrn_type) || + (generic_function_t::e_rtrn_string == function.rtrn_type) + ) && + std::string::npos != function.parameter_sequence.find_first_not_of("STVZ*?|") + ) + return false; + else if ( + (generic_function_t::e_rtrn_overload == function.rtrn_type) && + std::string::npos != function.parameter_sequence.find_first_not_of("STVZ*?|:") + ) + return false; + + switch (function.rtrn_type) + { + case generic_function_t::e_rtrn_scalar : + return local_data().generic_function_store.add(function_name,function); + + case generic_function_t::e_rtrn_string : + return local_data().string_function_store.add(function_name,function); + + case generic_function_t::e_rtrn_overload : + return local_data().overload_function_store.add(function_name,function); + } + + return false; + } + + #define exprtk_define_freefunction(NN) \ + inline bool add_function(const std::string& function_name, ff##NN##_functor function) \ + { \ + if (!valid()) \ + { return false; } \ + if (!valid_symbol(function_name)) \ + { return false; } \ + if (symbol_exists(function_name)) \ + { return false; } \ + \ + exprtk::ifunction* ifunc = new freefunc##NN(function); \ + \ + local_data().free_function_list_.push_back(ifunc); \ + \ + return add_function(function_name,(*local_data().free_function_list_.back())); \ + } \ + + exprtk_define_freefunction(00) exprtk_define_freefunction(01) + exprtk_define_freefunction(02) exprtk_define_freefunction(03) + exprtk_define_freefunction(04) exprtk_define_freefunction(05) + exprtk_define_freefunction(06) exprtk_define_freefunction(07) + exprtk_define_freefunction(08) exprtk_define_freefunction(09) + exprtk_define_freefunction(10) exprtk_define_freefunction(11) + exprtk_define_freefunction(12) exprtk_define_freefunction(13) + exprtk_define_freefunction(14) exprtk_define_freefunction(15) + + #undef exprtk_define_freefunction + + inline bool add_reserved_function(const std::string& function_name, function_t& function) + { + if (!valid()) + return false; + else if (!valid_symbol(function_name,false)) + return false; + else if (symbol_exists(function_name,false)) + return false; + else + return local_data().function_store.add(function_name,function); + } + + inline bool add_reserved_function(const std::string& vararg_function_name, vararg_function_t& vararg_function) + { + if (!valid()) + return false; + else if (!valid_symbol(vararg_function_name,false)) + return false; + else if (symbol_exists(vararg_function_name,false)) + return false; + else + return local_data().vararg_function_store.add(vararg_function_name,vararg_function); + } + + inline bool add_reserved_function(const std::string& function_name, generic_function_t& function) + { + if (!valid()) + return false; + else if (!valid_symbol(function_name,false)) + return false; + else if (symbol_exists(function_name,false)) + return false; + else if ( + ( + (generic_function_t::e_rtrn_scalar == function.rtrn_type) || + (generic_function_t::e_rtrn_string == function.rtrn_type) + ) && + std::string::npos != function.parameter_sequence.find_first_not_of("STV*?|") + ) + return false; + else if ( + generic_function_t::e_rtrn_overload && + std::string::npos != function.parameter_sequence.find_first_not_of("STV*?|:") + ) + return false; + + switch (function.rtrn_type) + { + case generic_function_t::e_rtrn_scalar : + return local_data().generic_function_store.add(function_name,function); + + case generic_function_t::e_rtrn_string : + return local_data().string_function_store.add(function_name,function); + + case generic_function_t::e_rtrn_overload : + return local_data().overload_function_store.add(function_name,function); + } + + return false; + } + + template + inline bool add_vector(const std::string& vector_name, T (&v)[N]) + { + if (!valid()) + return false; + else if (!valid_symbol(vector_name)) + return false; + else if (symbol_exists(vector_name)) + return false; + else + return local_data().vector_store.add(vector_name,v); + } + + inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size) + { + if (!valid()) + return false; + else if (!valid_symbol(vector_name)) + return false; + else if (symbol_exists(vector_name)) + return false; + else if (0 == v_size) + return false; + else + return local_data().vector_store.add(vector_name,v,v_size); + } + + template + inline bool add_vector(const std::string& vector_name, std::vector& v) + { + if (!valid()) + return false; + else if (!valid_symbol(vector_name)) + return false; + else if (symbol_exists(vector_name)) + return false; + else if (0 == v.size()) + return false; + else + return local_data().vector_store.add(vector_name,v); + } + + inline bool add_vector(const std::string& vector_name, exprtk::vector_view& v) + { + if (!valid()) + return false; + else if (!valid_symbol(vector_name)) + return false; + else if (symbol_exists(vector_name)) + return false; + else if (0 == v.size()) + return false; + else + return local_data().vector_store.add(vector_name,v); + } + + inline bool remove_variable(const std::string& variable_name, const bool delete_node = true) + { + if (!valid()) + return false; + else + return local_data().variable_store.remove(variable_name, delete_node); + } + + #ifndef exprtk_disable_string_capabilities + inline bool remove_stringvar(const std::string& string_name) + { + if (!valid()) + return false; + else + return local_data().stringvar_store.remove(string_name); + } + #endif + + inline bool remove_function(const std::string& function_name) + { + if (!valid()) + return false; + else + return local_data().function_store.remove(function_name); + } + + inline bool remove_vararg_function(const std::string& vararg_function_name) + { + if (!valid()) + return false; + else + return local_data().vararg_function_store.remove(vararg_function_name); + } + + inline bool remove_vector(const std::string& vector_name) + { + if (!valid()) + return false; + else + return local_data().vector_store.remove(vector_name); + } + + inline bool add_constants() + { + return add_pi () && + add_epsilon () && + add_infinity() ; + } + + inline bool add_pi() + { + const typename details::numeric::details::number_type::type num_type; + static const T local_pi = details::numeric::details::const_pi_impl(num_type); + return add_constant("pi",local_pi); + } + + inline bool add_epsilon() + { + static const T local_epsilon = details::numeric::details::epsilon_type::value(); + return add_constant("epsilon",local_epsilon); + } + + inline bool add_infinity() + { + static const T local_infinity = std::numeric_limits::infinity(); + return add_constant("inf",local_infinity); + } + + template + inline bool add_package(Package& package) + { + return package.register_package(*this); + } + + template class Sequence> + inline std::size_t get_variable_list(Sequence,Allocator>& vlist) const + { + if (!valid()) + return 0; + else + return local_data().variable_store.get_list(vlist); + } + + template class Sequence> + inline std::size_t get_variable_list(Sequence& vlist) const + { + if (!valid()) + return 0; + else + return local_data().variable_store.get_list(vlist); + } + + #ifndef exprtk_disable_string_capabilities + template class Sequence> + inline std::size_t get_stringvar_list(Sequence,Allocator>& svlist) const + { + if (!valid()) + return 0; + else + return local_data().stringvar_store.get_list(svlist); + } + + template class Sequence> + inline std::size_t get_stringvar_list(Sequence& svlist) const + { + if (!valid()) + return 0; + else + return local_data().stringvar_store.get_list(svlist); + } + #endif + + template class Sequence> + inline std::size_t get_vector_list(Sequence& vlist) const + { + if (!valid()) + return 0; + else + return local_data().vector_store.get_list(vlist); + } + + inline bool symbol_exists(const std::string& symbol_name, const bool check_reserved_symb = true) const + { + /* + Function will return true if symbol_name exists as either a + reserved symbol, variable, stringvar, vector or function name + in any of the type stores. + */ + if (!valid()) + return false; + else if (local_data().variable_store.symbol_exists(symbol_name)) + return true; + #ifndef exprtk_disable_string_capabilities + else if (local_data().stringvar_store.symbol_exists(symbol_name)) + return true; + #endif + else if (local_data().vector_store.symbol_exists(symbol_name)) + return true; + else if (local_data().function_store.symbol_exists(symbol_name)) + return true; + else if (check_reserved_symb && local_data().is_reserved_symbol(symbol_name)) + return true; + else + return false; + } + + inline bool is_variable(const std::string& variable_name) const + { + if (!valid()) + return false; + else + return local_data().variable_store.symbol_exists(variable_name); + } + + #ifndef exprtk_disable_string_capabilities + inline bool is_stringvar(const std::string& stringvar_name) const + { + if (!valid()) + return false; + else + return local_data().stringvar_store.symbol_exists(stringvar_name); + } + + inline bool is_conststr_stringvar(const std::string& symbol_name) const + { + if (!valid()) + return false; + else if (!valid_symbol(symbol_name)) + return false; + else if (!local_data().stringvar_store.symbol_exists(symbol_name)) + return false; + + return ( + local_data().stringvar_store.symbol_exists(symbol_name) || + local_data().stringvar_store.is_constant (symbol_name) + ); + } + #endif + + inline bool is_function(const std::string& function_name) const + { + if (!valid()) + return false; + else + return local_data().function_store.symbol_exists(function_name); + } + + inline bool is_vararg_function(const std::string& vararg_function_name) const + { + if (!valid()) + return false; + else + return local_data().vararg_function_store.symbol_exists(vararg_function_name); + } + + inline bool is_vector(const std::string& vector_name) const + { + if (!valid()) + return false; + else + return local_data().vector_store.symbol_exists(vector_name); + } + + inline std::string get_variable_name(const expression_ptr& ptr) const + { + return local_data().variable_store.entity_name(ptr); + } + + inline std::string get_vector_name(const vector_holder_ptr& ptr) const + { + return local_data().vector_store.entity_name(ptr); + } + + #ifndef exprtk_disable_string_capabilities + inline std::string get_stringvar_name(const expression_ptr& ptr) const + { + return local_data().stringvar_store.entity_name(ptr); + } + + inline std::string get_conststr_stringvar_name(const expression_ptr& ptr) const + { + return local_data().stringvar_store.entity_name(ptr); + } + #endif + + inline bool valid() const + { + // Symbol table sanity check. + return control_block_ && control_block_->data_; + } + + inline void load_from(const symbol_table& st) + { + { + std::vector name_list; + + st.local_data().function_store.get_list(name_list); + + if (!name_list.empty()) + { + for (std::size_t i = 0; i < name_list.size(); ++i) + { + exprtk::ifunction& ifunc = *st.get_function(name_list[i]); + add_function(name_list[i],ifunc); + } + } + } + + { + std::vector name_list; + + st.local_data().vararg_function_store.get_list(name_list); + + if (!name_list.empty()) + { + for (std::size_t i = 0; i < name_list.size(); ++i) + { + exprtk::ivararg_function& ivafunc = *st.get_vararg_function(name_list[i]); + add_function(name_list[i],ivafunc); + } + } + } + + { + std::vector name_list; + + st.local_data().generic_function_store.get_list(name_list); + + if (!name_list.empty()) + { + for (std::size_t i = 0; i < name_list.size(); ++i) + { + exprtk::igeneric_function& ifunc = *st.get_generic_function(name_list[i]); + add_function(name_list[i],ifunc); + } + } + } + + { + std::vector name_list; + + st.local_data().string_function_store.get_list(name_list); + + if (!name_list.empty()) + { + for (std::size_t i = 0; i < name_list.size(); ++i) + { + exprtk::igeneric_function& ifunc = *st.get_string_function(name_list[i]); + add_function(name_list[i],ifunc); + } + } + } + + { + std::vector name_list; + + st.local_data().overload_function_store.get_list(name_list); + + if (!name_list.empty()) + { + for (std::size_t i = 0; i < name_list.size(); ++i) + { + exprtk::igeneric_function& ifunc = *st.get_overload_function(name_list[i]); + add_function(name_list[i],ifunc); + } + } + } + } + + private: + + inline bool valid_symbol(const std::string& symbol, const bool check_reserved_symb = true) const + { + if (symbol.empty()) + return false; + else if (!details::is_letter(symbol[0])) + return false; + else if (symbol.size() > 1) + { + for (std::size_t i = 1; i < symbol.size(); ++i) + { + if ( + !details::is_letter_or_digit(symbol[i]) && + ('_' != symbol[i]) + ) + { + if (('.' == symbol[i]) && (i < (symbol.size() - 1))) + continue; + else + return false; + } + } + } + + return (check_reserved_symb) ? (!local_data().is_reserved_symbol(symbol)) : true; + } + + inline bool valid_function(const std::string& symbol) const + { + if (symbol.empty()) + return false; + else if (!details::is_letter(symbol[0])) + return false; + else if (symbol.size() > 1) + { + for (std::size_t i = 1; i < symbol.size(); ++i) + { + if ( + !details::is_letter_or_digit(symbol[i]) && + ('_' != symbol[i]) + ) + { + if (('.' == symbol[i]) && (i < (symbol.size() - 1))) + continue; + else + return false; + } + } + } + + return true; + } + + typedef typename control_block::st_data local_data_t; + + inline local_data_t& local_data() + { + return *(control_block_->data_); + } + + inline const local_data_t& local_data() const + { + return *(control_block_->data_); + } + + control_block* control_block_; + + friend class parser; + }; + + template + class function_compositor; + + template + class expression + { + private: + + typedef details::expression_node* expression_ptr; + typedef details::vector_holder* vector_holder_ptr; + typedef std::vector > symtab_list_t; + + struct control_block + { + enum data_type + { + e_unknown , + e_expr , + e_vecholder, + e_data , + e_vecdata , + e_string + }; + + struct data_pack + { + data_pack() + : pointer(0), + type(e_unknown), + size(0) + {} + + data_pack(void* ptr, const data_type dt, const std::size_t sz = 0) + : pointer(ptr), + type(dt), + size(sz) + {} + + void* pointer; + data_type type; + std::size_t size; + }; + + typedef std::vector local_data_list_t; + typedef results_context results_context_t; + + control_block() + : ref_count(0), + expr (0), + results (0), + retinv_null(false), + return_invoked(&retinv_null) + {} + + explicit control_block(expression_ptr e) + : ref_count(1), + expr (e), + results (0), + retinv_null(false), + return_invoked(&retinv_null) + {} + + ~control_block() + { + if (expr && details::branch_deletable(expr)) + { + destroy_node(expr); + } + + if (!local_data_list.empty()) + { + for (std::size_t i = 0; i < local_data_list.size(); ++i) + { + switch (local_data_list[i].type) + { + case e_expr : delete reinterpret_cast(local_data_list[i].pointer); + break; + + case e_vecholder : delete reinterpret_cast(local_data_list[i].pointer); + break; + + case e_data : delete (T*)(local_data_list[i].pointer); + break; + + case e_vecdata : delete [] (T*)(local_data_list[i].pointer); + break; + + case e_string : delete (std::string*)(local_data_list[i].pointer); + break; + + default : break; + } + } + } + + if (results) + { + delete results; + } + } + + static inline control_block* create(expression_ptr e) + { + return new control_block(e); + } + + static inline void destroy(control_block*& cntrl_blck) + { + if (cntrl_blck) + { + if ( + (0 != cntrl_blck->ref_count) && + (0 == --cntrl_blck->ref_count) + ) + { + delete cntrl_blck; + } + + cntrl_blck = 0; + } + } + + std::size_t ref_count; + expression_ptr expr; + local_data_list_t local_data_list; + results_context_t* results; + bool retinv_null; + bool* return_invoked; + + friend class function_compositor; + }; + + public: + + expression() + : control_block_(0) + { + set_expression(new details::null_node()); + } + + expression(const expression& e) + : control_block_ (e.control_block_ ), + symbol_table_list_(e.symbol_table_list_) + { + control_block_->ref_count++; + } + + explicit expression(const symbol_table& symbol_table) + : control_block_(0) + { + set_expression(new details::null_node()); + symbol_table_list_.push_back(symbol_table); + } + + inline expression& operator=(const expression& e) + { + if (this != &e) + { + if (control_block_) + { + if ( + (0 != control_block_->ref_count) && + (0 == --control_block_->ref_count) + ) + { + delete control_block_; + } + + control_block_ = 0; + } + + control_block_ = e.control_block_; + control_block_->ref_count++; + symbol_table_list_ = e.symbol_table_list_; + } + + return *this; + } + + inline bool operator==(const expression& e) const + { + return (this == &e); + } + + inline bool operator!() const + { + return ( + (0 == control_block_ ) || + (0 == control_block_->expr) + ); + } + + inline expression& release() + { + control_block::destroy(control_block_); + + return (*this); + } + + ~expression() + { + control_block::destroy(control_block_); + } + + inline T value() const + { + return control_block_->expr->value(); + } + + inline T operator() () const + { + return value(); + } + + inline operator T() const + { + return value(); + } + + inline operator bool() const + { + return details::is_true(value()); + } + + inline void register_symbol_table(symbol_table& st) + { + symbol_table_list_.push_back(st); + } + + inline const symbol_table& get_symbol_table(const std::size_t& index = 0) const + { + return symbol_table_list_[index]; + } + + inline symbol_table& get_symbol_table(const std::size_t& index = 0) + { + return symbol_table_list_[index]; + } + + typedef results_context results_context_t; + + inline const results_context_t& results() const + { + if (control_block_->results) + return (*control_block_->results); + else + { + static const results_context_t null_results; + return null_results; + } + } + + inline bool return_invoked() const + { + return (*control_block_->return_invoked); + } + + private: + + inline symtab_list_t get_symbol_table_list() const + { + return symbol_table_list_; + } + + inline void set_expression(const expression_ptr expr) + { + if (expr) + { + if (control_block_) + { + if (0 == --control_block_->ref_count) + { + delete control_block_; + } + } + + control_block_ = control_block::create(expr); + } + } + + inline void register_local_var(expression_ptr expr) + { + if (expr) + { + if (control_block_) + { + control_block_-> + local_data_list.push_back( + typename expression::control_block:: + data_pack(reinterpret_cast(expr), + control_block::e_expr)); + } + } + } + + inline void register_local_var(vector_holder_ptr vec_holder) + { + if (vec_holder) + { + if (control_block_) + { + control_block_-> + local_data_list.push_back( + typename expression::control_block:: + data_pack(reinterpret_cast(vec_holder), + control_block::e_vecholder)); + } + } + } + + inline void register_local_data(void* data, const std::size_t& size = 0, const std::size_t data_mode = 0) + { + if (data) + { + if (control_block_) + { + typename control_block::data_type dt = control_block::e_data; + + switch (data_mode) + { + case 0 : dt = control_block::e_data; break; + case 1 : dt = control_block::e_vecdata; break; + case 2 : dt = control_block::e_string; break; + } + + control_block_-> + local_data_list.push_back( + typename expression::control_block:: + data_pack(reinterpret_cast(data), dt, size)); + } + } + } + + inline const typename control_block::local_data_list_t& local_data_list() + { + if (control_block_) + { + return control_block_->local_data_list; + } + else + { + static typename control_block::local_data_list_t null_local_data_list; + return null_local_data_list; + } + } + + inline void register_return_results(results_context_t* rc) + { + if (control_block_ && rc) + { + control_block_->results = rc; + } + } + + inline void set_retinvk(bool* retinvk_ptr) + { + if (control_block_) + { + control_block_->return_invoked = retinvk_ptr; + } + } + + control_block* control_block_; + symtab_list_t symbol_table_list_; + + friend class parser; + friend class expression_helper; + friend class function_compositor; + }; + + template + class expression_helper + { + public: + + static inline bool is_constant(const expression& expr) + { + return details::is_constant_node(expr.control_block_->expr); + } + + static inline bool is_variable(const expression& expr) + { + return details::is_variable_node(expr.control_block_->expr); + } + + static inline bool is_unary(const expression& expr) + { + return details::is_unary_node(expr.control_block_->expr); + } + + static inline bool is_binary(const expression& expr) + { + return details::is_binary_node(expr.control_block_->expr); + } + + static inline bool is_function(const expression& expr) + { + return details::is_function(expr.control_block_->expr); + } + + static inline bool is_null(const expression& expr) + { + return details::is_null_node(expr.control_block_->expr); + } + }; + + template + inline bool is_valid(const expression& expr) + { + return !expression_helper::is_null(expr); + } + + namespace parser_error + { + enum error_mode + { + e_unknown = 0, + e_syntax = 1, + e_token = 2, + e_numeric = 4, + e_symtab = 5, + e_lexer = 6, + e_helper = 7 + }; + + struct type + { + type() + : mode(parser_error::e_unknown), + line_no (0), + column_no(0) + {} + + lexer::token token; + error_mode mode; + std::string diagnostic; + std::string src_location; + std::string error_line; + std::size_t line_no; + std::size_t column_no; + }; + + inline type make_error(const error_mode mode, + const std::string& diagnostic = "", + const std::string& src_location = "") + { + type t; + t.mode = mode; + t.token.type = lexer::token::e_error; + t.diagnostic = diagnostic; + t.src_location = src_location; + exprtk_debug(("%s\n",diagnostic .c_str())); + return t; + } + + inline type make_error(const error_mode mode, + const lexer::token& tk, + const std::string& diagnostic = "", + const std::string& src_location = "") + { + type t; + t.mode = mode; + t.token = tk; + t.diagnostic = diagnostic; + t.src_location = src_location; + exprtk_debug(("%s\n",diagnostic .c_str())); + return t; + } + + inline std::string to_str(error_mode mode) + { + switch (mode) + { + case e_unknown : return std::string("Unknown Error"); + case e_syntax : return std::string("Syntax Error" ); + case e_token : return std::string("Token Error" ); + case e_numeric : return std::string("Numeric Error"); + case e_symtab : return std::string("Symbol Error" ); + case e_lexer : return std::string("Lexer Error" ); + case e_helper : return std::string("Helper Error" ); + default : return std::string("Unknown Error"); + } + } + + inline bool update_error(type& error, const std::string& expression) + { + if ( + expression.empty() || + (error.token.position > expression.size()) || + (std::numeric_limits::max() == error.token.position) + ) + { + return false; + } + + std::size_t error_line_start = 0; + + for (std::size_t i = error.token.position; i > 0; --i) + { + const details::char_t c = expression[i]; + + if (('\n' == c) || ('\r' == c)) + { + error_line_start = i + 1; + break; + } + } + + std::size_t next_nl_position = std::min(expression.size(), + expression.find_first_of('\n',error.token.position + 1)); + + error.column_no = error.token.position - error_line_start; + error.error_line = expression.substr(error_line_start, + next_nl_position - error_line_start); + + error.line_no = 0; + + for (std::size_t i = 0; i < next_nl_position; ++i) + { + if ('\n' == expression[i]) + ++error.line_no; + } + + return true; + } + + inline void dump_error(const type& error) + { + printf("Position: %02d Type: [%s] Msg: %s\n", + static_cast(error.token.position), + exprtk::parser_error::to_str(error.mode).c_str(), + error.diagnostic.c_str()); + } + } + + namespace details + { + template + inline void disable_type_checking(Parser& p) + { + p.state_.type_check_enabled = false; + } + } + + template + class parser : public lexer::parser_helper + { + private: + + enum precedence_level + { + e_level00, + e_level01, + e_level02, + e_level03, + e_level04, + e_level05, + e_level06, + e_level07, + e_level08, + e_level09, + e_level10, + e_level11, + e_level12, + e_level13, + e_level14 + }; + + typedef const T& cref_t; + typedef const T const_t; + typedef ifunction F; + typedef ivararg_function VAF; + typedef igeneric_function GF; + typedef ifunction ifunction_t; + typedef ivararg_function ivararg_function_t; + typedef igeneric_function igeneric_function_t; + typedef details::expression_node expression_node_t; + typedef details::literal_node literal_node_t; + typedef details::unary_node unary_node_t; + typedef details::binary_node binary_node_t; + typedef details::trinary_node trinary_node_t; + typedef details::quaternary_node quaternary_node_t; + typedef details::conditional_node conditional_node_t; + typedef details::cons_conditional_node cons_conditional_node_t; + typedef details::while_loop_node while_loop_node_t; + typedef details::repeat_until_loop_node repeat_until_loop_node_t; + typedef details::for_loop_node for_loop_node_t; + #ifndef exprtk_disable_break_continue + typedef details::while_loop_bc_node while_loop_bc_node_t; + typedef details::repeat_until_loop_bc_node repeat_until_loop_bc_node_t; + typedef details::for_loop_bc_node for_loop_bc_node_t; + #endif + typedef details::switch_node switch_node_t; + typedef details::variable_node variable_node_t; + typedef details::vector_elem_node vector_elem_node_t; + typedef details::rebasevector_elem_node rebasevector_elem_node_t; + typedef details::rebasevector_celem_node rebasevector_celem_node_t; + typedef details::vector_node vector_node_t; + typedef details::range_pack range_t; + #ifndef exprtk_disable_string_capabilities + typedef details::stringvar_node stringvar_node_t; + typedef details::string_literal_node string_literal_node_t; + typedef details::string_range_node string_range_node_t; + typedef details::const_string_range_node const_string_range_node_t; + typedef details::generic_string_range_node generic_string_range_node_t; + typedef details::string_concat_node string_concat_node_t; + typedef details::assignment_string_node assignment_string_node_t; + typedef details::assignment_string_range_node assignment_string_range_node_t; + typedef details::conditional_string_node conditional_string_node_t; + typedef details::cons_conditional_str_node cons_conditional_str_node_t; + #endif + typedef details::assignment_node assignment_node_t; + typedef details::assignment_vec_elem_node assignment_vec_elem_node_t; + typedef details::assignment_rebasevec_elem_node assignment_rebasevec_elem_node_t; + typedef details::assignment_rebasevec_celem_node assignment_rebasevec_celem_node_t; + typedef details::assignment_vec_node assignment_vec_node_t; + typedef details::assignment_vecvec_node assignment_vecvec_node_t; + typedef details::scand_node scand_node_t; + typedef details::scor_node scor_node_t; + typedef lexer::token token_t; + typedef expression_node_t* expression_node_ptr; + typedef expression expression_t; + typedef symbol_table symbol_table_t; + typedef typename expression::symtab_list_t symbol_table_list_t; + typedef details::vector_holder* vector_holder_ptr; + + typedef typename details::functor_t functor_t; + typedef typename functor_t::qfunc_t quaternary_functor_t; + typedef typename functor_t::tfunc_t trinary_functor_t; + typedef typename functor_t::bfunc_t binary_functor_t; + typedef typename functor_t::ufunc_t unary_functor_t; + + typedef details::operator_type operator_t; + + typedef std::map unary_op_map_t; + typedef std::map binary_op_map_t; + typedef std::map trinary_op_map_t; + + typedef std::map > sf3_map_t; + typedef std::map > sf4_map_t; + + typedef std::map inv_binary_op_map_t; + typedef std::multimap base_ops_map_t; + typedef std::set disabled_func_set_t; + + typedef details::T0oT1_define vov_t; + typedef details::T0oT1_define cov_t; + typedef details::T0oT1_define voc_t; + + typedef details::T0oT1oT2_define vovov_t; + typedef details::T0oT1oT2_define vovoc_t; + typedef details::T0oT1oT2_define vocov_t; + typedef details::T0oT1oT2_define covov_t; + typedef details::T0oT1oT2_define covoc_t; + typedef details::T0oT1oT2_define cocov_t; + typedef details::T0oT1oT2_define vococ_t; + + typedef details::T0oT1oT2oT3_define vovovov_t; + typedef details::T0oT1oT2oT3_define vovovoc_t; + typedef details::T0oT1oT2oT3_define vovocov_t; + typedef details::T0oT1oT2oT3_define vocovov_t; + typedef details::T0oT1oT2oT3_define covovov_t; + + typedef details::T0oT1oT2oT3_define covocov_t; + typedef details::T0oT1oT2oT3_define vocovoc_t; + typedef details::T0oT1oT2oT3_define covovoc_t; + typedef details::T0oT1oT2oT3_define vococov_t; + + typedef results_context results_context_t; + + typedef parser_helper prsrhlpr_t; + + struct scope_element + { + enum element_type + { + e_none , + e_variable, + e_vector , + e_vecelem , + e_string + }; + + typedef details::vector_holder vector_holder_t; + typedef variable_node_t* variable_node_ptr; + typedef vector_holder_t* vector_holder_ptr; + typedef expression_node_t* expression_node_ptr; + #ifndef exprtk_disable_string_capabilities + typedef stringvar_node_t* stringvar_node_ptr; + #endif + + scope_element() + : name("???"), + size (std::numeric_limits::max()), + index(std::numeric_limits::max()), + depth(std::numeric_limits::max()), + ref_count(0), + ip_index (0), + type (e_none), + active(false), + data (0), + var_node(0), + vec_node(0) + #ifndef exprtk_disable_string_capabilities + ,str_node(0) + #endif + {} + + bool operator < (const scope_element& se) const + { + if (ip_index < se.ip_index) + return true; + else if (ip_index > se.ip_index) + return false; + else if (depth < se.depth) + return true; + else if (depth > se.depth) + return false; + else if (index < se.index) + return true; + else if (index > se.index) + return false; + else + return (name < se.name); + } + + void clear() + { + name = "???"; + size = std::numeric_limits::max(); + index = std::numeric_limits::max(); + depth = std::numeric_limits::max(); + type = e_none; + active = false; + ref_count = 0; + ip_index = 0; + data = 0; + var_node = 0; + vec_node = 0; + #ifndef exprtk_disable_string_capabilities + str_node = 0; + #endif + } + + std::string name; + std::size_t size; + std::size_t index; + std::size_t depth; + std::size_t ref_count; + std::size_t ip_index; + element_type type; + bool active; + void* data; + expression_node_ptr var_node; + vector_holder_ptr vec_node; + #ifndef exprtk_disable_string_capabilities + stringvar_node_ptr str_node; + #endif + }; + + class scope_element_manager + { + public: + + typedef expression_node_t* expression_node_ptr; + typedef variable_node_t* variable_node_ptr; + typedef parser parser_t; + + explicit scope_element_manager(parser& p) + : parser_(p), + input_param_cnt_(0) + {} + + inline std::size_t size() const + { + return element_.size(); + } + + inline bool empty() const + { + return element_.empty(); + } + + inline scope_element& get_element(const std::size_t& index) + { + if (index < element_.size()) + return element_[index]; + else + return null_element_; + } + + inline scope_element& get_element(const std::string& var_name, + const std::size_t index = std::numeric_limits::max()) + { + const std::size_t current_depth = parser_.state_.scope_depth; + + for (std::size_t i = 0; i < element_.size(); ++i) + { + scope_element& se = element_[i]; + + if (se.depth > current_depth) + continue; + else if ( + details::imatch(se.name, var_name) && + (se.index == index) + ) + return se; + } + + return null_element_; + } + + inline scope_element& get_active_element(const std::string& var_name, + const std::size_t index = std::numeric_limits::max()) + { + const std::size_t current_depth = parser_.state_.scope_depth; + + for (std::size_t i = 0; i < element_.size(); ++i) + { + scope_element& se = element_[i]; + + if (se.depth > current_depth) + continue; + else if ( + details::imatch(se.name, var_name) && + (se.index == index) && + (se.active) + ) + return se; + } + + return null_element_; + } + + inline bool add_element(const scope_element& se) + { + for (std::size_t i = 0; i < element_.size(); ++i) + { + scope_element& cse = element_[i]; + + if ( + details::imatch(cse.name, se.name) && + (cse.depth <= se.depth) && + (cse.index == se.index) && + (cse.size == se.size ) && + (cse.type == se.type ) && + (cse.active) + ) + return false; + } + + element_.push_back(se); + std::sort(element_.begin(),element_.end()); + + return true; + } + + inline void deactivate(const std::size_t& scope_depth) + { + exprtk_debug(("deactivate() - Scope depth: %d\n", + static_cast(parser_.state_.scope_depth))); + + for (std::size_t i = 0; i < element_.size(); ++i) + { + scope_element& se = element_[i]; + + if (se.active && (se.depth >= scope_depth)) + { + exprtk_debug(("deactivate() - element[%02d] '%s'\n", + static_cast(i), + se.name.c_str())); + + se.active = false; + } + } + } + + inline void free_element(scope_element& se) + { + #ifdef exprtk_enable_debugging + exprtk_debug(("free_element() - se[%s]\n", se.name.c_str())); + #endif + + switch (se.type) + { + case scope_element::e_variable : if (se.data ) delete (T*) se.data; + if (se.var_node) delete se.var_node; + break; + + case scope_element::e_vector : if (se.data ) delete[] (T*) se.data; + if (se.vec_node) delete se.vec_node; + break; + + case scope_element::e_vecelem : if (se.var_node) delete se.var_node; + break; + + #ifndef exprtk_disable_string_capabilities + case scope_element::e_string : if (se.data ) delete (std::string*) se.data; + if (se.str_node) delete se.str_node; + break; + #endif + + default : return; + } + + se.clear(); + } + + inline void cleanup() + { + for (std::size_t i = 0; i < element_.size(); ++i) + { + free_element(element_[i]); + } + + element_.clear(); + + input_param_cnt_ = 0; + } + + inline std::size_t next_ip_index() + { + return ++input_param_cnt_; + } + + inline expression_node_ptr get_variable(const T& v) + { + for (std::size_t i = 0; i < element_.size(); ++i) + { + scope_element& se = element_[i]; + + if ( + se.active && + se.var_node && + details::is_variable_node(se.var_node) + ) + { + variable_node_ptr vn = reinterpret_cast(se.var_node); + + if (&(vn->ref()) == (&v)) + { + return se.var_node; + } + } + } + + return expression_node_ptr(0); + } + + private: + + scope_element_manager& operator=(const scope_element_manager&); + + parser_t& parser_; + std::vector element_; + scope_element null_element_; + std::size_t input_param_cnt_; + }; + + class scope_handler + { + public: + + typedef parser parser_t; + + explicit scope_handler(parser& p) + : parser_(p) + { + parser_.state_.scope_depth++; + #ifdef exprtk_enable_debugging + const std::string depth(2 * parser_.state_.scope_depth,'-'); + exprtk_debug(("%s> Scope Depth: %02d\n", + depth.c_str(), + static_cast(parser_.state_.scope_depth))); + #endif + } + + ~scope_handler() + { + parser_.sem_.deactivate(parser_.state_.scope_depth); + parser_.state_.scope_depth--; + #ifdef exprtk_enable_debugging + const std::string depth(2 * parser_.state_.scope_depth,'-'); + exprtk_debug(("<%s Scope Depth: %02d\n", + depth.c_str(), + static_cast(parser_.state_.scope_depth))); + #endif + } + + private: + + scope_handler& operator=(const scope_handler&); + + parser_t& parser_; + }; + + struct symtab_store + { + symbol_table_list_t symtab_list_; + + typedef typename symbol_table_t::local_data_t local_data_t; + typedef typename symbol_table_t::variable_ptr variable_ptr; + typedef typename symbol_table_t::function_ptr function_ptr; + #ifndef exprtk_disable_string_capabilities + typedef typename symbol_table_t::stringvar_ptr stringvar_ptr; + #endif + typedef typename symbol_table_t::vector_holder_ptr vector_holder_ptr; + typedef typename symbol_table_t::vararg_function_ptr vararg_function_ptr; + typedef typename symbol_table_t::generic_function_ptr generic_function_ptr; + + inline bool empty() const + { + return symtab_list_.empty(); + } + + inline void clear() + { + symtab_list_.clear(); + } + + inline bool valid() const + { + if (!empty()) + { + for (std::size_t i = 0; i < symtab_list_.size(); ++i) + { + if (symtab_list_[i].valid()) + return true; + } + } + + return false; + } + + inline bool valid_symbol(const std::string& symbol) const + { + if (!symtab_list_.empty()) + return symtab_list_[0].valid_symbol(symbol); + else + return false; + } + + inline bool valid_function_name(const std::string& symbol) const + { + if (!symtab_list_.empty()) + return symtab_list_[0].valid_function(symbol); + else + return false; + } + + inline variable_ptr get_variable(const std::string& variable_name) const + { + if (!valid_symbol(variable_name)) + return reinterpret_cast(0); + + variable_ptr result = reinterpret_cast(0); + + for (std::size_t i = 0; i < symtab_list_.size(); ++i) + { + if (!symtab_list_[i].valid()) + continue; + else + result = local_data(i) + .variable_store.get(variable_name); + + if (result) break; + } + + return result; + } + + inline variable_ptr get_variable(const T& var_ref) const + { + variable_ptr result = reinterpret_cast(0); + + for (std::size_t i = 0; i < symtab_list_.size(); ++i) + { + if (!symtab_list_[i].valid()) + continue; + else + result = local_data(i).variable_store + .get_from_varptr(reinterpret_cast(&var_ref)); + + if (result) break; + } + + return result; + } + + #ifndef exprtk_disable_string_capabilities + inline stringvar_ptr get_stringvar(const std::string& string_name) const + { + if (!valid_symbol(string_name)) + return reinterpret_cast(0); + + stringvar_ptr result = reinterpret_cast(0); + + for (std::size_t i = 0; i < symtab_list_.size(); ++i) + { + if (!symtab_list_[i].valid()) + continue; + else + result = local_data(i) + .stringvar_store.get(string_name); + + if (result) break; + } + + return result; + } + #endif + + inline function_ptr get_function(const std::string& function_name) const + { + if (!valid_function_name(function_name)) + return reinterpret_cast(0); + + function_ptr result = reinterpret_cast(0); + + for (std::size_t i = 0; i < symtab_list_.size(); ++i) + { + if (!symtab_list_[i].valid()) + continue; + else + result = local_data(i) + .function_store.get(function_name); + + if (result) break; + } + + return result; + } + + inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const + { + if (!valid_function_name(vararg_function_name)) + return reinterpret_cast(0); + + vararg_function_ptr result = reinterpret_cast(0); + + for (std::size_t i = 0; i < symtab_list_.size(); ++i) + { + if (!symtab_list_[i].valid()) + continue; + else + result = local_data(i) + .vararg_function_store.get(vararg_function_name); + + if (result) break; + } + + return result; + } + + inline generic_function_ptr get_generic_function(const std::string& function_name) const + { + if (!valid_function_name(function_name)) + return reinterpret_cast(0); + + generic_function_ptr result = reinterpret_cast(0); + + for (std::size_t i = 0; i < symtab_list_.size(); ++i) + { + if (!symtab_list_[i].valid()) + continue; + else + result = local_data(i) + .generic_function_store.get(function_name); + + if (result) break; + } + + return result; + } + + inline generic_function_ptr get_string_function(const std::string& function_name) const + { + if (!valid_function_name(function_name)) + return reinterpret_cast(0); + + generic_function_ptr result = reinterpret_cast(0); + + for (std::size_t i = 0; i < symtab_list_.size(); ++i) + { + if (!symtab_list_[i].valid()) + continue; + else + result = + local_data(i).string_function_store.get(function_name); + + if (result) break; + } + + return result; + } + + inline generic_function_ptr get_overload_function(const std::string& function_name) const + { + if (!valid_function_name(function_name)) + return reinterpret_cast(0); + + generic_function_ptr result = reinterpret_cast(0); + + for (std::size_t i = 0; i < symtab_list_.size(); ++i) + { + if (!symtab_list_[i].valid()) + continue; + else + result = + local_data(i).overload_function_store.get(function_name); + + if (result) break; + } + + return result; + } + + inline vector_holder_ptr get_vector(const std::string& vector_name) const + { + if (!valid_symbol(vector_name)) + return reinterpret_cast(0); + + vector_holder_ptr result = reinterpret_cast(0); + + for (std::size_t i = 0; i < symtab_list_.size(); ++i) + { + if (!symtab_list_[i].valid()) + continue; + else + result = + local_data(i).vector_store.get(vector_name); + + if (result) break; + } + + return result; + } + + inline bool is_constant_node(const std::string& symbol_name) const + { + if (!valid_symbol(symbol_name)) + return false; + + for (std::size_t i = 0; i < symtab_list_.size(); ++i) + { + if (!symtab_list_[i].valid()) + continue; + else if (local_data(i).variable_store.is_constant(symbol_name)) + return true; + } + + return false; + } + + #ifndef exprtk_disable_string_capabilities + inline bool is_constant_string(const std::string& symbol_name) const + { + if (!valid_symbol(symbol_name)) + return false; + + for (std::size_t i = 0; i < symtab_list_.size(); ++i) + { + if (!symtab_list_[i].valid()) + continue; + else if (!local_data(i).stringvar_store.symbol_exists(symbol_name)) + continue; + else if ( local_data(i).stringvar_store.is_constant(symbol_name)) + return true; + } + + return false; + } + #endif + + inline bool symbol_exists(const std::string& symbol) const + { + for (std::size_t i = 0; i < symtab_list_.size(); ++i) + { + if (!symtab_list_[i].valid()) + continue; + else if (symtab_list_[i].symbol_exists(symbol)) + return true; + } + + return false; + } + + inline bool is_variable(const std::string& variable_name) const + { + for (std::size_t i = 0; i < symtab_list_.size(); ++i) + { + if (!symtab_list_[i].valid()) + continue; + else if ( + symtab_list_[i].local_data().variable_store + .symbol_exists(variable_name) + ) + return true; + } + + return false; + } + + #ifndef exprtk_disable_string_capabilities + inline bool is_stringvar(const std::string& stringvar_name) const + { + for (std::size_t i = 0; i < symtab_list_.size(); ++i) + { + if (!symtab_list_[i].valid()) + continue; + else if ( + symtab_list_[i].local_data().stringvar_store + .symbol_exists(stringvar_name) + ) + return true; + } + + return false; + } + + inline bool is_conststr_stringvar(const std::string& symbol_name) const + { + for (std::size_t i = 0; i < symtab_list_.size(); ++i) + { + if (!symtab_list_[i].valid()) + continue; + else if ( + symtab_list_[i].local_data().stringvar_store + .symbol_exists(symbol_name) + ) + { + return ( + local_data(i).stringvar_store.symbol_exists(symbol_name) || + local_data(i).stringvar_store.is_constant (symbol_name) + ); + + } + } + + return false; + } + #endif + + inline bool is_function(const std::string& function_name) const + { + for (std::size_t i = 0; i < symtab_list_.size(); ++i) + { + if (!symtab_list_[i].valid()) + continue; + else if ( + local_data(i).vararg_function_store + .symbol_exists(function_name) + ) + return true; + } + + return false; + } + + inline bool is_vararg_function(const std::string& vararg_function_name) const + { + for (std::size_t i = 0; i < symtab_list_.size(); ++i) + { + if (!symtab_list_[i].valid()) + continue; + else if ( + local_data(i).vararg_function_store + .symbol_exists(vararg_function_name) + ) + return true; + } + + return false; + } + + inline bool is_vector(const std::string& vector_name) const + { + for (std::size_t i = 0; i < symtab_list_.size(); ++i) + { + if (!symtab_list_[i].valid()) + continue; + else if ( + local_data(i).vector_store + .symbol_exists(vector_name) + ) + return true; + } + + return false; + } + + inline std::string get_variable_name(const expression_node_ptr& ptr) const + { + return local_data().variable_store.entity_name(ptr); + } + + inline std::string get_vector_name(const vector_holder_ptr& ptr) const + { + return local_data().vector_store.entity_name(ptr); + } + + #ifndef exprtk_disable_string_capabilities + inline std::string get_stringvar_name(const expression_node_ptr& ptr) const + { + return local_data().stringvar_store.entity_name(ptr); + } + + inline std::string get_conststr_stringvar_name(const expression_node_ptr& ptr) const + { + return local_data().stringvar_store.entity_name(ptr); + } + #endif + + inline local_data_t& local_data(const std::size_t& index = 0) + { + return symtab_list_[index].local_data(); + } + + inline const local_data_t& local_data(const std::size_t& index = 0) const + { + return symtab_list_[index].local_data(); + } + + inline symbol_table_t& get_symbol_table(const std::size_t& index = 0) + { + return symtab_list_[index]; + } + }; + + struct parser_state + { + parser_state() + : type_check_enabled(true) + { + reset(); + } + + void reset() + { + parsing_return_stmt = false; + parsing_break_stmt = false; + return_stmt_present = false; + side_effect_present = false; + scope_depth = 0; + } + + #ifndef exprtk_enable_debugging + void activate_side_effect(const std::string&) + #else + void activate_side_effect(const std::string& source) + #endif + { + if (!side_effect_present) + { + side_effect_present = true; + + exprtk_debug(("activate_side_effect() - caller: %s\n",source.c_str())); + } + } + + bool parsing_return_stmt; + bool parsing_break_stmt; + bool return_stmt_present; + bool side_effect_present; + bool type_check_enabled; + std::size_t scope_depth; + }; + + public: + + struct unknown_symbol_resolver + { + + enum usr_symbol_type + { + e_usr_unknown_type = 0, + e_usr_variable_type = 1, + e_usr_constant_type = 2 + }; + + enum usr_mode + { + e_usrmode_default = 0, + e_usrmode_extended = 1 + }; + + usr_mode mode; + + unknown_symbol_resolver(const usr_mode m = e_usrmode_default) + : mode(m) + {} + + virtual ~unknown_symbol_resolver() + {} + + virtual bool process(const std::string& /*unknown_symbol*/, + usr_symbol_type& st, + T& default_value, + std::string& error_message) + { + if (e_usrmode_default != mode) + return false; + + st = e_usr_variable_type; + default_value = T(0); + error_message.clear(); + + return true; + } + + virtual bool process(const std::string& /* unknown_symbol */, + symbol_table_t& /* symbol_table */, + std::string& /* error_message */) + { + return false; + } + }; + + enum collect_type + { + e_ct_none = 0, + e_ct_variables = 1, + e_ct_functions = 2, + e_ct_assignments = 4 + }; + + enum symbol_type + { + e_st_unknown = 0, + e_st_variable = 1, + e_st_vector = 2, + e_st_vecelem = 3, + e_st_string = 4, + e_st_function = 5, + e_st_local_variable = 6, + e_st_local_vector = 7, + e_st_local_string = 8 + }; + + class dependent_entity_collector + { + public: + + typedef std::pair symbol_t; + typedef std::vector symbol_list_t; + + dependent_entity_collector(const std::size_t options = e_ct_none) + : options_(options), + collect_variables_ ((options_ & e_ct_variables ) == e_ct_variables ), + collect_functions_ ((options_ & e_ct_functions ) == e_ct_functions ), + collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments), + return_present_ (false), + final_stmt_return_(false) + {} + + template class Sequence> + inline std::size_t symbols(Sequence& symbols_list) + { + if (!collect_variables_ && !collect_functions_) + return 0; + else if (symbol_name_list_.empty()) + return 0; + + for (std::size_t i = 0; i < symbol_name_list_.size(); ++i) + { + details::case_normalise(symbol_name_list_[i].first); + } + + std::sort(symbol_name_list_.begin(),symbol_name_list_.end()); + + std::unique_copy(symbol_name_list_.begin(), + symbol_name_list_.end (), + std::back_inserter(symbols_list)); + + return symbols_list.size(); + } + + template class Sequence> + inline std::size_t assignment_symbols(Sequence& assignment_list) + { + if (!collect_assignments_) + return 0; + else if (assignment_name_list_.empty()) + return 0; + + for (std::size_t i = 0; i < assignment_name_list_.size(); ++i) + { + details::case_normalise(assignment_name_list_[i].first); + } + + std::sort(assignment_name_list_.begin(),assignment_name_list_.end()); + + std::unique_copy(assignment_name_list_.begin(), + assignment_name_list_.end (), + std::back_inserter(assignment_list)); + + return assignment_list.size(); + } + + void clear() + { + symbol_name_list_ .clear(); + assignment_name_list_.clear(); + retparam_list_ .clear(); + return_present_ = false; + final_stmt_return_ = false; + } + + bool& collect_variables() + { + return collect_variables_; + } + + bool& collect_functions() + { + return collect_functions_; + } + + bool& collect_assignments() + { + return collect_assignments_; + } + + bool return_present() const + { + return return_present_; + } + + bool final_stmt_return() const + { + return final_stmt_return_; + } + + typedef std::vector retparam_list_t; + + retparam_list_t return_param_type_list() const + { + return retparam_list_; + } + + private: + + inline void add_symbol(const std::string& symbol, const symbol_type st) + { + switch (st) + { + case e_st_variable : + case e_st_vector : + case e_st_string : + case e_st_local_variable : + case e_st_local_vector : + case e_st_local_string : if (collect_variables_) + symbol_name_list_ + .push_back(std::make_pair(symbol, st)); + break; + + case e_st_function : if (collect_functions_) + symbol_name_list_ + .push_back(std::make_pair(symbol, st)); + break; + + default : return; + } + } + + inline void add_assignment(const std::string& symbol, const symbol_type st) + { + switch (st) + { + case e_st_variable : + case e_st_vector : + case e_st_string : if (collect_assignments_) + assignment_name_list_ + .push_back(std::make_pair(symbol, st)); + break; + + default : return; + } + } + + std::size_t options_; + bool collect_variables_; + bool collect_functions_; + bool collect_assignments_; + bool return_present_; + bool final_stmt_return_; + symbol_list_t symbol_name_list_; + symbol_list_t assignment_name_list_; + retparam_list_t retparam_list_; + + friend class parser; + }; + + class settings_store + { + private: + + typedef std::set disabled_entity_set_t; + typedef disabled_entity_set_t::iterator des_itr_t; + + public: + + enum settings_compilation_options + { + e_unknown = 0, + e_replacer = 1, + e_joiner = 2, + e_numeric_check = 4, + e_bracket_check = 8, + e_sequence_check = 16, + e_commutative_check = 32, + e_strength_reduction = 64, + e_disable_vardef = 128, + e_collect_vars = 256, + e_collect_funcs = 512, + e_collect_assings = 1024, + e_disable_usr_on_rsrvd = 2048, + e_disable_zero_return = 4096 + }; + + enum settings_base_funcs + { + e_bf_unknown = 0, + e_bf_abs , e_bf_acos , e_bf_acosh , e_bf_asin , + e_bf_asinh , e_bf_atan , e_bf_atan2 , e_bf_atanh , + e_bf_avg , e_bf_ceil , e_bf_clamp , e_bf_cos , + e_bf_cosh , e_bf_cot , e_bf_csc , e_bf_equal , + e_bf_erf , e_bf_erfc , e_bf_exp , e_bf_expm1 , + e_bf_floor , e_bf_frac , e_bf_hypot , e_bf_iclamp , + e_bf_like , e_bf_log , e_bf_log10 , e_bf_log1p , + e_bf_log2 , e_bf_logn , e_bf_mand , e_bf_max , + e_bf_min , e_bf_mod , e_bf_mor , e_bf_mul , + e_bf_ncdf , e_bf_pow , e_bf_root , e_bf_round , + e_bf_roundn , e_bf_sec , e_bf_sgn , e_bf_sin , + e_bf_sinc , e_bf_sinh , e_bf_sqrt , e_bf_sum , + e_bf_swap , e_bf_tan , e_bf_tanh , e_bf_trunc , + e_bf_not_equal , e_bf_inrange , e_bf_deg2grad , e_bf_deg2rad, + e_bf_rad2deg , e_bf_grad2deg + }; + + enum settings_control_structs + { + e_ctrl_unknown = 0, + e_ctrl_ifelse, + e_ctrl_switch, + e_ctrl_for_loop, + e_ctrl_while_loop, + e_ctrl_repeat_loop, + e_ctrl_return + }; + + enum settings_logic_opr + { + e_logic_unknown = 0, + e_logic_and, e_logic_nand, e_logic_nor, + e_logic_not, e_logic_or, e_logic_xnor, + e_logic_xor, e_logic_scand, e_logic_scor + }; + + enum settings_arithmetic_opr + { + e_arith_unknown = 0, + e_arith_add, e_arith_sub, e_arith_mul, + e_arith_div, e_arith_mod, e_arith_pow + }; + + enum settings_assignment_opr + { + e_assign_unknown = 0, + e_assign_assign, e_assign_addass, e_assign_subass, + e_assign_mulass, e_assign_divass, e_assign_modass + }; + + enum settings_inequality_opr + { + e_ineq_unknown = 0, + e_ineq_lt, e_ineq_lte, e_ineq_eq, + e_ineq_equal, e_ineq_ne, e_ineq_nequal, + e_ineq_gte, e_ineq_gt + }; + + static const std::size_t compile_all_opts = e_replacer + + e_joiner + + e_numeric_check + + e_bracket_check + + e_sequence_check + + e_commutative_check + + e_strength_reduction; + + settings_store(const std::size_t compile_options = compile_all_opts) + { + load_compile_options(compile_options); + } + + settings_store& enable_all_base_functions() + { + disabled_func_set_.clear(); + return (*this); + } + + settings_store& enable_all_control_structures() + { + disabled_ctrl_set_.clear(); + return (*this); + } + + settings_store& enable_all_logic_ops() + { + disabled_logic_set_.clear(); + return (*this); + } + + settings_store& enable_all_arithmetic_ops() + { + disabled_arithmetic_set_.clear(); + return (*this); + } + + settings_store& enable_all_assignment_ops() + { + disabled_assignment_set_.clear(); + return (*this); + } + + settings_store& enable_all_inequality_ops() + { + disabled_inequality_set_.clear(); + return (*this); + } + + settings_store& enable_local_vardef() + { + disable_vardef_ = false; + return (*this); + } + + settings_store& disable_all_base_functions() + { + std::copy(details::base_function_list, + details::base_function_list + details::base_function_list_size, + std::insert_iterator + (disabled_func_set_, disabled_func_set_.begin())); + return (*this); + } + + settings_store& disable_all_control_structures() + { + std::copy(details::cntrl_struct_list, + details::cntrl_struct_list + details::cntrl_struct_list_size, + std::insert_iterator + (disabled_ctrl_set_, disabled_ctrl_set_.begin())); + return (*this); + } + + settings_store& disable_all_logic_ops() + { + std::copy(details::logic_ops_list, + details::logic_ops_list + details::logic_ops_list_size, + std::insert_iterator + (disabled_logic_set_, disabled_logic_set_.begin())); + return (*this); + } + + settings_store& disable_all_arithmetic_ops() + { + std::copy(details::arithmetic_ops_list, + details::arithmetic_ops_list + details::arithmetic_ops_list_size, + std::insert_iterator + (disabled_arithmetic_set_, disabled_arithmetic_set_.begin())); + return (*this); + } + + settings_store& disable_all_assignment_ops() + { + std::copy(details::assignment_ops_list, + details::assignment_ops_list + details::assignment_ops_list_size, + std::insert_iterator + (disabled_assignment_set_, disabled_assignment_set_.begin())); + return (*this); + } + + settings_store& disable_all_inequality_ops() + { + std::copy(details::inequality_ops_list, + details::inequality_ops_list + details::inequality_ops_list_size, + std::insert_iterator + (disabled_inequality_set_, disabled_inequality_set_.begin())); + return (*this); + } + + settings_store& disable_local_vardef() + { + disable_vardef_ = true; + return (*this); + } + + bool replacer_enabled () const { return enable_replacer_; } + bool commutative_check_enabled () const { return enable_commutative_check_; } + bool joiner_enabled () const { return enable_joiner_; } + bool numeric_check_enabled () const { return enable_numeric_check_; } + bool bracket_check_enabled () const { return enable_bracket_check_; } + bool sequence_check_enabled () const { return enable_sequence_check_; } + bool strength_reduction_enabled () const { return enable_strength_reduction_; } + bool collect_variables_enabled () const { return enable_collect_vars_; } + bool collect_functions_enabled () const { return enable_collect_funcs_; } + bool collect_assignments_enabled() const { return enable_collect_assings_; } + bool vardef_disabled () const { return disable_vardef_; } + bool rsrvd_sym_usr_disabled () const { return disable_rsrvd_sym_usr_; } + bool zero_return_disabled () const { return disable_zero_return_; } + + bool function_enabled(const std::string& function_name) const + { + if (disabled_func_set_.empty()) + return true; + else + return (disabled_func_set_.end() == disabled_func_set_.find(function_name)); + } + + bool control_struct_enabled(const std::string& control_struct) const + { + if (disabled_ctrl_set_.empty()) + return true; + else + return (disabled_ctrl_set_.end() == disabled_ctrl_set_.find(control_struct)); + } + + bool logic_enabled(const std::string& logic_operation) const + { + if (disabled_logic_set_.empty()) + return true; + else + return (disabled_logic_set_.end() == disabled_logic_set_.find(logic_operation)); + } + + bool arithmetic_enabled(const details::operator_type& arithmetic_operation) const + { + if (disabled_logic_set_.empty()) + return true; + else + return disabled_arithmetic_set_.end() == disabled_arithmetic_set_ + .find(arith_opr_to_string(arithmetic_operation)); + } + + bool assignment_enabled(const details::operator_type& assignment) const + { + if (disabled_assignment_set_.empty()) + return true; + else + return disabled_assignment_set_.end() == disabled_assignment_set_ + .find(assign_opr_to_string(assignment)); + } + + bool inequality_enabled(const details::operator_type& inequality) const + { + if (disabled_inequality_set_.empty()) + return true; + else + return disabled_inequality_set_.end() == disabled_inequality_set_ + .find(inequality_opr_to_string(inequality)); + } + + bool function_disabled(const std::string& function_name) const + { + if (disabled_func_set_.empty()) + return false; + else + return (disabled_func_set_.end() != disabled_func_set_.find(function_name)); + } + + bool control_struct_disabled(const std::string& control_struct) const + { + if (disabled_ctrl_set_.empty()) + return false; + else + return (disabled_ctrl_set_.end() != disabled_ctrl_set_.find(control_struct)); + } + + bool logic_disabled(const std::string& logic_operation) const + { + if (disabled_logic_set_.empty()) + return false; + else + return (disabled_logic_set_.end() != disabled_logic_set_.find(logic_operation)); + } + + bool assignment_disabled(const details::operator_type assignment_operation) const + { + if (disabled_assignment_set_.empty()) + return false; + else + return disabled_assignment_set_.end() != disabled_assignment_set_ + .find(assign_opr_to_string(assignment_operation)); + } + + bool arithmetic_disabled(const details::operator_type arithmetic_operation) const + { + if (disabled_arithmetic_set_.empty()) + return false; + else + return disabled_arithmetic_set_.end() != disabled_arithmetic_set_ + .find(arith_opr_to_string(arithmetic_operation)); + } + + bool inequality_disabled(const details::operator_type& inequality) const + { + if (disabled_inequality_set_.empty()) + return false; + else + return disabled_inequality_set_.end() != disabled_inequality_set_ + .find(inequality_opr_to_string(inequality)); + } + + settings_store& disable_base_function(settings_base_funcs bf) + { + if ( + (e_bf_unknown != bf) && + (static_cast(bf) < (details::base_function_list_size + 1)) + ) + { + disabled_func_set_.insert(details::base_function_list[bf - 1]); + } + + return (*this); + } + + settings_store& disable_control_structure(settings_control_structs ctrl_struct) + { + if ( + (e_ctrl_unknown != ctrl_struct) && + (static_cast(ctrl_struct) < (details::cntrl_struct_list_size + 1)) + ) + { + disabled_ctrl_set_.insert(details::cntrl_struct_list[ctrl_struct - 1]); + } + + return (*this); + } + + settings_store& disable_logic_operation(settings_logic_opr logic) + { + if ( + (e_logic_unknown != logic) && + (static_cast(logic) < (details::logic_ops_list_size + 1)) + ) + { + disabled_logic_set_.insert(details::logic_ops_list[logic - 1]); + } + + return (*this); + } + + settings_store& disable_arithmetic_operation(settings_arithmetic_opr arithmetic) + { + if ( + (e_arith_unknown != arithmetic) && + (static_cast(arithmetic) < (details::arithmetic_ops_list_size + 1)) + ) + { + disabled_arithmetic_set_.insert(details::arithmetic_ops_list[arithmetic - 1]); + } + + return (*this); + } + + settings_store& disable_assignment_operation(settings_assignment_opr assignment) + { + if ( + (e_assign_unknown != assignment) && + (static_cast(assignment) < (details::assignment_ops_list_size + 1)) + ) + { + disabled_assignment_set_.insert(details::assignment_ops_list[assignment - 1]); + } + + return (*this); + } + + settings_store& disable_inequality_operation(settings_inequality_opr inequality) + { + if ( + (e_ineq_unknown != inequality) && + (static_cast(inequality) < (details::inequality_ops_list_size + 1)) + ) + { + disabled_inequality_set_.insert(details::inequality_ops_list[inequality - 1]); + } + + return (*this); + } + + settings_store& enable_base_function(settings_base_funcs bf) + { + if ( + (e_bf_unknown != bf) && + (static_cast(bf) < (details::base_function_list_size + 1)) + ) + { + const des_itr_t itr = disabled_func_set_.find(details::base_function_list[bf - 1]); + + if (disabled_func_set_.end() != itr) + { + disabled_func_set_.erase(itr); + } + } + + return (*this); + } + + settings_store& enable_control_structure(settings_control_structs ctrl_struct) + { + if ( + (e_ctrl_unknown != ctrl_struct) && + (static_cast(ctrl_struct) < (details::cntrl_struct_list_size + 1)) + ) + { + const des_itr_t itr = disabled_ctrl_set_.find(details::cntrl_struct_list[ctrl_struct - 1]); + + if (disabled_ctrl_set_.end() != itr) + { + disabled_ctrl_set_.erase(itr); + } + } + + return (*this); + } + + settings_store& enable_logic_operation(settings_logic_opr logic) + { + if ( + (e_logic_unknown != logic) && + (static_cast(logic) < (details::logic_ops_list_size + 1)) + ) + { + const des_itr_t itr = disabled_logic_set_.find(details::logic_ops_list[logic - 1]); + + if (disabled_logic_set_.end() != itr) + { + disabled_logic_set_.erase(itr); + } + } + + return (*this); + } + + settings_store& enable_arithmetic_operation(settings_arithmetic_opr arithmetic) + { + if ( + (e_arith_unknown != arithmetic) && + (static_cast(arithmetic) < (details::arithmetic_ops_list_size + 1)) + ) + { + const des_itr_t itr = disabled_arithmetic_set_.find(details::arithmetic_ops_list[arithmetic - 1]); + + if (disabled_arithmetic_set_.end() != itr) + { + disabled_arithmetic_set_.erase(itr); + } + } + + return (*this); + } + + settings_store& enable_assignment_operation(settings_assignment_opr assignment) + { + if ( + (e_assign_unknown != assignment) && + (static_cast(assignment) < (details::assignment_ops_list_size + 1)) + ) + { + const des_itr_t itr = disabled_assignment_set_.find(details::assignment_ops_list[assignment - 1]); + + if (disabled_assignment_set_.end() != itr) + { + disabled_assignment_set_.erase(itr); + } + } + + return (*this); + } + + settings_store& enable_inequality_operation(settings_inequality_opr inequality) + { + if ( + (e_ineq_unknown != inequality) && + (static_cast(inequality) < (details::inequality_ops_list_size + 1)) + ) + { + const des_itr_t itr = disabled_inequality_set_.find(details::inequality_ops_list[inequality - 1]); + + if (disabled_inequality_set_.end() != itr) + { + disabled_inequality_set_.erase(itr); + } + } + + return (*this); + } + + private: + + void load_compile_options(const std::size_t compile_options) + { + enable_replacer_ = (compile_options & e_replacer ) == e_replacer; + enable_joiner_ = (compile_options & e_joiner ) == e_joiner; + enable_numeric_check_ = (compile_options & e_numeric_check ) == e_numeric_check; + enable_bracket_check_ = (compile_options & e_bracket_check ) == e_bracket_check; + enable_sequence_check_ = (compile_options & e_sequence_check ) == e_sequence_check; + enable_commutative_check_ = (compile_options & e_commutative_check ) == e_commutative_check; + enable_strength_reduction_ = (compile_options & e_strength_reduction ) == e_strength_reduction; + enable_collect_vars_ = (compile_options & e_collect_vars ) == e_collect_vars; + enable_collect_funcs_ = (compile_options & e_collect_funcs ) == e_collect_funcs; + enable_collect_assings_ = (compile_options & e_collect_assings ) == e_collect_assings; + disable_vardef_ = (compile_options & e_disable_vardef ) == e_disable_vardef; + disable_rsrvd_sym_usr_ = (compile_options & e_disable_usr_on_rsrvd) == e_disable_usr_on_rsrvd; + disable_zero_return_ = (compile_options & e_disable_zero_return ) == e_disable_zero_return; + } + + std::string assign_opr_to_string(details::operator_type opr) const + { + switch (opr) + { + case details::e_assign : return ":="; + case details::e_addass : return "+="; + case details::e_subass : return "-="; + case details::e_mulass : return "*="; + case details::e_divass : return "/="; + case details::e_modass : return "%="; + default : return ""; + } + } + + std::string arith_opr_to_string(details::operator_type opr) const + { + switch (opr) + { + case details::e_add : return "+"; + case details::e_sub : return "-"; + case details::e_mul : return "*"; + case details::e_div : return "/"; + case details::e_mod : return "%"; + default : return ""; + } + } + + std::string inequality_opr_to_string(details::operator_type opr) const + { + switch (opr) + { + case details::e_lt : return "<"; + case details::e_lte : return "<="; + case details::e_eq : return "=="; + case details::e_equal : return "="; + case details::e_ne : return "!="; + case details::e_nequal: return "<>"; + case details::e_gte : return ">="; + case details::e_gt : return ">"; + default : return ""; + } + } + + bool enable_replacer_; + bool enable_joiner_; + bool enable_numeric_check_; + bool enable_bracket_check_; + bool enable_sequence_check_; + bool enable_commutative_check_; + bool enable_strength_reduction_; + bool enable_collect_vars_; + bool enable_collect_funcs_; + bool enable_collect_assings_; + bool disable_vardef_; + bool disable_rsrvd_sym_usr_; + bool disable_zero_return_; + + disabled_entity_set_t disabled_func_set_ ; + disabled_entity_set_t disabled_ctrl_set_ ; + disabled_entity_set_t disabled_logic_set_; + disabled_entity_set_t disabled_arithmetic_set_; + disabled_entity_set_t disabled_assignment_set_; + disabled_entity_set_t disabled_inequality_set_; + + friend class parser; + }; + + typedef settings_store settings_t; + + parser(const settings_t& settings = settings_t()) + : settings_(settings), + resolve_unknown_symbol_(false), + results_context_(0), + unknown_symbol_resolver_(reinterpret_cast(0)), + #ifdef _MSC_VER + #pragma warning(push) + #pragma warning (disable:4355) + #endif + sem_(*this), + #ifdef _MSC_VER + #pragma warning(pop) + #endif + operator_joiner_2_(2), + operator_joiner_3_(3) + { + init_precompilation(); + + load_operations_map (base_ops_map_ ); + load_unary_operations_map (unary_op_map_ ); + load_binary_operations_map (binary_op_map_ ); + load_inv_binary_operations_map(inv_binary_op_map_); + load_sf3_map (sf3_map_ ); + load_sf4_map (sf4_map_ ); + + expression_generator_.init_synthesize_map(); + expression_generator_.set_parser(*this); + expression_generator_.set_uom(unary_op_map_); + expression_generator_.set_bom(binary_op_map_); + expression_generator_.set_ibom(inv_binary_op_map_); + expression_generator_.set_sf3m(sf3_map_); + expression_generator_.set_sf4m(sf4_map_); + expression_generator_.set_strength_reduction_state(settings_.strength_reduction_enabled()); + } + + ~parser() + {} + + inline void init_precompilation() + { + if (settings_.collect_variables_enabled()) + dec_.collect_variables() = true; + + if (settings_.collect_functions_enabled()) + dec_.collect_functions() = true; + + if (settings_.collect_assignments_enabled()) + dec_.collect_assignments() = true; + + if (settings_.replacer_enabled()) + { + symbol_replacer_.clear(); + symbol_replacer_.add_replace("true" ,"1",lexer::token::e_number); + symbol_replacer_.add_replace("false","0",lexer::token::e_number); + helper_assembly_.token_modifier_list.clear(); + helper_assembly_.register_modifier(&symbol_replacer_); + } + + if (settings_.commutative_check_enabled()) + { + for (std::size_t i = 0; i < details::reserved_words_size; ++i) + { + commutative_inserter_.ignore_symbol(details::reserved_words[i]); + } + + helper_assembly_.token_inserter_list.clear(); + helper_assembly_.register_inserter(&commutative_inserter_); + } + + if (settings_.joiner_enabled()) + { + helper_assembly_.token_joiner_list.clear(); + helper_assembly_.register_joiner(&operator_joiner_2_); + helper_assembly_.register_joiner(&operator_joiner_3_); + } + + if ( + settings_.numeric_check_enabled () || + settings_.bracket_check_enabled () || + settings_.sequence_check_enabled() + ) + { + helper_assembly_.token_scanner_list.clear(); + + if (settings_.numeric_check_enabled()) + { + helper_assembly_.register_scanner(&numeric_checker_); + } + + if (settings_.bracket_check_enabled()) + { + helper_assembly_.register_scanner(&bracket_checker_); + } + + if (settings_.sequence_check_enabled()) + { + helper_assembly_.register_scanner(&sequence_validator_ ); + helper_assembly_.register_scanner(&sequence_validator_3tkns_); + } + } + } + + inline bool compile(const std::string& expression_string, expression& expr) + { + state_ .reset(); + error_list_ .clear(); + brkcnt_list_ .clear(); + synthesis_error_.clear(); + sem_ .cleanup(); + + return_cleanup(); + + expression_generator_.set_allocator(node_allocator_); + + if (expression_string.empty()) + { + set_error( + make_error(parser_error::e_syntax, + "ERR000 - Empty expression!", + exprtk_error_location)); + + return false; + } + + if (!init(expression_string)) + { + process_lexer_errors(); + return false; + } + + if (lexer().empty()) + { + set_error( + make_error(parser_error::e_syntax, + "ERR001 - Empty expression!", + exprtk_error_location)); + + return false; + } + + if (!run_assemblies()) + { + return false; + } + + symtab_store_.symtab_list_ = expr.get_symbol_table_list(); + dec_.clear(); + + lexer().begin(); + + next_token(); + + expression_node_ptr e = parse_corpus(); + + if ((0 != e) && (token_t::e_eof == current_token().type)) + { + bool* retinvk_ptr = 0; + + if (state_.return_stmt_present) + { + dec_.return_present_ = true; + + e = expression_generator_ + .return_envelope(e, results_context_, retinvk_ptr); + } + + expr.set_expression(e); + expr.set_retinvk(retinvk_ptr); + + register_local_vars(expr); + register_return_results(expr); + + return !(!expr); + } + else + { + if (error_list_.empty()) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR002 - Invalid expression encountered", + exprtk_error_location)); + } + + if ((0 != e) && branch_deletable(e)) + { + destroy_node(e); + } + + dec_.clear (); + sem_.cleanup (); + return_cleanup(); + + return false; + } + } + + inline expression_t compile(const std::string& expression_string, symbol_table_t& symtab) + { + expression_t expr; + + expr.register_symbol_table(symtab); + + compile(expression_string,expr); + + return expr; + } + + void process_lexer_errors() + { + for (std::size_t i = 0; i < lexer().size(); ++i) + { + if (lexer()[i].is_error()) + { + std::string diagnostic = "ERR003 - "; + + switch (lexer()[i].type) + { + case lexer::token::e_error : diagnostic += "General token error"; + break; + + case lexer::token::e_err_symbol : diagnostic += "Symbol error"; + break; + + case lexer::token::e_err_number : diagnostic += "Invalid numeric token"; + break; + + case lexer::token::e_err_string : diagnostic += "Invalid string token"; + break; + + case lexer::token::e_err_sfunc : diagnostic += "Invalid special function token"; + break; + + default : diagnostic += "Unknown compiler error"; + } + + set_error( + make_error(parser_error::e_lexer, + lexer()[i], + diagnostic + ": " + lexer()[i].value, + exprtk_error_location)); + } + } + } + + inline bool run_assemblies() + { + if (settings_.commutative_check_enabled()) + { + helper_assembly_.run_inserters(lexer()); + } + + if (settings_.joiner_enabled()) + { + helper_assembly_.run_joiners(lexer()); + } + + if (settings_.replacer_enabled()) + { + helper_assembly_.run_modifiers(lexer()); + } + + if ( + settings_.numeric_check_enabled () || + settings_.bracket_check_enabled () || + settings_.sequence_check_enabled() + ) + { + if (!helper_assembly_.run_scanners(lexer())) + { + if (helper_assembly_.error_token_scanner) + { + lexer::helper::bracket_checker* bracket_checker_ptr = 0; + lexer::helper::numeric_checker* numeric_checker_ptr = 0; + lexer::helper::sequence_validator* sequence_validator_ptr = 0; + lexer::helper::sequence_validator_3tokens* sequence_validator3_ptr = 0; + + if (0 != (bracket_checker_ptr = dynamic_cast(helper_assembly_.error_token_scanner))) + { + set_error( + make_error(parser_error::e_token, + bracket_checker_ptr->error_token(), + "ERR004 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'", + exprtk_error_location)); + } + else if (0 != (numeric_checker_ptr = dynamic_cast(helper_assembly_.error_token_scanner))) + { + for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i) + { + lexer::token error_token = lexer()[numeric_checker_ptr->error_index(i)]; + + set_error( + make_error(parser_error::e_token, + error_token, + "ERR005 - Invalid numeric token: '" + error_token.value + "'", + exprtk_error_location)); + } + + if (numeric_checker_ptr->error_count()) + { + numeric_checker_ptr->clear_errors(); + } + } + else if (0 != (sequence_validator_ptr = dynamic_cast(helper_assembly_.error_token_scanner))) + { + for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i) + { + std::pair error_token = sequence_validator_ptr->error(i); + + set_error( + make_error(parser_error::e_token, + error_token.first, + "ERR006 - Invalid token sequence: '" + + error_token.first.value + "' and '" + + error_token.second.value + "'", + exprtk_error_location)); + } + + if (sequence_validator_ptr->error_count()) + { + sequence_validator_ptr->clear_errors(); + } + } + else if (0 != (sequence_validator3_ptr = dynamic_cast(helper_assembly_.error_token_scanner))) + { + for (std::size_t i = 0; i < sequence_validator3_ptr->error_count(); ++i) + { + std::pair error_token = sequence_validator3_ptr->error(i); + + set_error( + make_error(parser_error::e_token, + error_token.first, + "ERR007 - Invalid token sequence: '" + + error_token.first.value + "' and '" + + error_token.second.value + "'", + exprtk_error_location)); + } + + if (sequence_validator3_ptr->error_count()) + { + sequence_validator3_ptr->clear_errors(); + } + } + } + + return false; + } + } + + return true; + } + + inline settings_store& settings() + { + return settings_; + } + + inline parser_error::type get_error(const std::size_t& index) const + { + if (index < error_list_.size()) + return error_list_[index]; + else + throw std::invalid_argument("parser::get_error() - Invalid error index specificed"); + } + + inline std::string error() const + { + if (!error_list_.empty()) + { + return error_list_[0].diagnostic; + } + else + return std::string("No Error"); + } + + inline std::size_t error_count() const + { + return error_list_.size(); + } + + inline dependent_entity_collector& dec() + { + return dec_; + } + + inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol) + { + if (!settings_.replacer_enabled()) + return false; + else if (details::is_reserved_word(old_symbol)) + return false; + else + return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol); + } + + inline bool remove_replace_symbol(const std::string& symbol) + { + if (!settings_.replacer_enabled()) + return false; + else if (details::is_reserved_word(symbol)) + return false; + else + return symbol_replacer_.remove(symbol); + } + + inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast(0)) + { + resolve_unknown_symbol_ = true; + + if (usr) + unknown_symbol_resolver_ = usr; + else + unknown_symbol_resolver_ = &default_usr_; + } + + inline void enable_unknown_symbol_resolver(unknown_symbol_resolver& usr) + { + enable_unknown_symbol_resolver(&usr); + } + + inline void disable_unknown_symbol_resolver() + { + resolve_unknown_symbol_ = false; + unknown_symbol_resolver_ = &default_usr_; + } + + private: + + inline bool valid_base_operation(const std::string& symbol) const + { + const std::size_t length = symbol.size(); + + if ( + (length < 3) || // Shortest base op symbol length + (length > 9) // Longest base op symbol length + ) + return false; + else + return settings_.function_enabled(symbol) && + (base_ops_map_.end() != base_ops_map_.find(symbol)); + } + + inline bool valid_vararg_operation(const std::string& symbol) const + { + static const std::string s_sum = "sum" ; + static const std::string s_mul = "mul" ; + static const std::string s_avg = "avg" ; + static const std::string s_min = "min" ; + static const std::string s_max = "max" ; + static const std::string s_mand = "mand"; + static const std::string s_mor = "mor" ; + static const std::string s_multi = "~" ; + static const std::string s_mswitch = "[*]" ; + + return + ( + details::imatch(symbol,s_sum ) || + details::imatch(symbol,s_mul ) || + details::imatch(symbol,s_avg ) || + details::imatch(symbol,s_min ) || + details::imatch(symbol,s_max ) || + details::imatch(symbol,s_mand ) || + details::imatch(symbol,s_mor ) || + details::imatch(symbol,s_multi ) || + details::imatch(symbol,s_mswitch) + ) && + settings_.function_enabled(symbol); + } + + bool is_invalid_arithmetic_operation(const details::operator_type operation) const + { + return settings_.arithmetic_disabled(operation); + } + + bool is_invalid_assignment_operation(const details::operator_type operation) const + { + return settings_.assignment_disabled(operation); + } + + bool is_invalid_inequality_operation(const details::operator_type operation) const + { + return settings_.inequality_disabled(operation); + } + + #ifdef exprtk_enable_debugging + inline void next_token() + { + const std::string ct_str = current_token().value; + parser_helper::next_token(); + const std::string depth(2 * state_.scope_depth,' '); + exprtk_debug(("%s" + "prev[%s] --> curr[%s]\n", + depth.c_str(), + ct_str.c_str(), + current_token().value.c_str())); + } + #endif + + inline expression_node_ptr parse_corpus() + { + std::vector arg_list; + std::vector side_effect_list; + + scoped_vec_delete sdd((*this),arg_list); + + lexer::token begin_token; + lexer::token end_token; + + for ( ; ; ) + { + state_.side_effect_present = false; + + begin_token = current_token(); + + expression_node_ptr arg = parse_expression(); + + if (0 == arg) + { + if (error_list_.empty()) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR008 - Invalid expression encountered", + exprtk_error_location)); + } + + return error_node(); + } + else + { + arg_list.push_back(arg); + + side_effect_list.push_back(state_.side_effect_present); + + end_token = current_token(); + + const std::string sub_expr = construct_subexpr(begin_token, end_token); + + exprtk_debug(("parse_corpus(%02d) Subexpr: %s\n", + static_cast(arg_list.size() - 1), + sub_expr.c_str())); + + exprtk_debug(("parse_corpus(%02d) - Side effect present: %s\n", + static_cast(arg_list.size() - 1), + state_.side_effect_present ? "true" : "false")); + + exprtk_debug(("-------------------------------------------------\n")); + } + + if (lexer().finished()) + break; + else if (token_is(token_t::e_eof,prsrhlpr_t::e_hold)) + { + if (lexer().finished()) + break; + else + next_token(); + } + } + + if ( + !arg_list.empty() && + is_return_node(arg_list.back()) + ) + { + dec_.final_stmt_return_ = true; + } + + const expression_node_ptr result = simplify(arg_list,side_effect_list); + + sdd.delete_ptr = (0 == result); + + return result; + } + + std::string construct_subexpr(lexer::token& begin_token, lexer::token& end_token) + { + std::string result = lexer().substr(begin_token.position,end_token.position); + + for (std::size_t i = 0; i < result.size(); ++i) + { + if (details::is_whitespace(result[i])) result[i] = ' '; + } + + return result; + } + + static const precedence_level default_precedence = e_level00; + + struct state_t + { + inline void set(const precedence_level& l, + const precedence_level& r, + const details::operator_type& o) + { + left = l; + right = r; + operation = o; + } + + inline void reset() + { + left = e_level00; + right = e_level00; + operation = details::e_default; + } + + precedence_level left; + precedence_level right; + details::operator_type operation; + }; + + inline expression_node_ptr parse_expression(precedence_level precedence = e_level00) + { + expression_node_ptr expression = parse_branch(precedence); + + if (0 == expression) + { + return error_node(); + } + + bool break_loop = false; + + state_t current_state; + + for ( ; ; ) + { + current_state.reset(); + + switch (current_token().type) + { + case token_t::e_assign : current_state.set(e_level00,e_level00, details::e_assign); break; + case token_t::e_addass : current_state.set(e_level00,e_level00, details::e_addass); break; + case token_t::e_subass : current_state.set(e_level00,e_level00, details::e_subass); break; + case token_t::e_mulass : current_state.set(e_level00,e_level00, details::e_mulass); break; + case token_t::e_divass : current_state.set(e_level00,e_level00, details::e_divass); break; + case token_t::e_modass : current_state.set(e_level00,e_level00, details::e_modass); break; + case token_t::e_swap : current_state.set(e_level00,e_level00, details::e_swap ); break; + case token_t::e_lt : current_state.set(e_level05,e_level06, details:: e_lt); break; + case token_t::e_lte : current_state.set(e_level05,e_level06, details:: e_lte); break; + case token_t::e_eq : current_state.set(e_level05,e_level06, details:: e_eq); break; + case token_t::e_ne : current_state.set(e_level05,e_level06, details:: e_ne); break; + case token_t::e_gte : current_state.set(e_level05,e_level06, details:: e_gte); break; + case token_t::e_gt : current_state.set(e_level05,e_level06, details:: e_gt); break; + case token_t::e_add : current_state.set(e_level07,e_level08, details:: e_add); break; + case token_t::e_sub : current_state.set(e_level07,e_level08, details:: e_sub); break; + case token_t::e_div : current_state.set(e_level10,e_level11, details:: e_div); break; + case token_t::e_mul : current_state.set(e_level10,e_level11, details:: e_mul); break; + case token_t::e_mod : current_state.set(e_level10,e_level11, details:: e_mod); break; + case token_t::e_pow : current_state.set(e_level12,e_level12, details:: e_pow); break; + default : if (token_t::e_symbol == current_token().type) + { + static const std::string s_and = "and"; + static const std::string s_nand = "nand"; + static const std::string s_or = "or"; + static const std::string s_nor = "nor"; + static const std::string s_xor = "xor"; + static const std::string s_xnor = "xnor"; + static const std::string s_in = "in"; + static const std::string s_like = "like"; + static const std::string s_ilike = "ilike"; + static const std::string s_and1 = "&"; + static const std::string s_or1 = "|"; + static const std::string s_not = "not"; + + if (details::imatch(current_token().value,s_and)) + { + current_state.set(e_level03, e_level04, details::e_and); + break; + } + else if (details::imatch(current_token().value,s_and1)) + { + #ifndef exprtk_disable_sc_andor + current_state.set(e_level03, e_level04, details::e_scand); + #else + current_state.set(e_level03, e_level04, details::e_and); + #endif + break; + } + else if (details::imatch(current_token().value,s_nand)) + { + current_state.set(e_level03, e_level04, details::e_nand); + break; + } + else if (details::imatch(current_token().value,s_or)) + { + current_state.set(e_level01, e_level02, details::e_or); + break; + } + else if (details::imatch(current_token().value,s_or1)) + { + #ifndef exprtk_disable_sc_andor + current_state.set(e_level01, e_level02, details::e_scor); + #else + current_state.set(e_level01, e_level02, details::e_or); + #endif + break; + } + else if (details::imatch(current_token().value,s_nor)) + { + current_state.set(e_level01, e_level02, details::e_nor); + break; + } + else if (details::imatch(current_token().value,s_xor)) + { + current_state.set(e_level01, e_level02, details::e_xor); + break; + } + else if (details::imatch(current_token().value,s_xnor)) + { + current_state.set(e_level01, e_level02, details::e_xnor); + break; + } + else if (details::imatch(current_token().value,s_in)) + { + current_state.set(e_level04, e_level04, details::e_in); + break; + } + else if (details::imatch(current_token().value,s_like)) + { + current_state.set(e_level04, e_level04, details::e_like); + break; + } + else if (details::imatch(current_token().value,s_ilike)) + { + current_state.set(e_level04, e_level04, details::e_ilike); + break; + } + else if (details::imatch(current_token().value,s_not)) + { + break; + } + } + + break_loop = true; + } + + if (break_loop) + { + parse_pending_string_rangesize(expression); + break; + } + else if (current_state.left < precedence) + break; + + const lexer::token prev_token = current_token(); + + next_token(); + + expression_node_ptr right_branch = error_node(); + expression_node_ptr new_expression = error_node(); + + if (is_invalid_arithmetic_operation(current_state.operation)) + { + free_node(node_allocator_,expression); + + set_error( + make_error(parser_error::e_syntax, + prev_token, + "ERR009 - Invalid arithmetic operation '" + details::to_str(current_state.operation) + "'", + exprtk_error_location)); + + return error_node(); + } + else if (is_invalid_inequality_operation(current_state.operation)) + { + free_node(node_allocator_,expression); + + set_error( + make_error(parser_error::e_syntax, + prev_token, + "ERR010 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'", + exprtk_error_location)); + + return error_node(); + } + else if (is_invalid_assignment_operation(current_state.operation)) + { + free_node(node_allocator_,expression); + + set_error( + make_error(parser_error::e_syntax, + prev_token, + "ERR011 - Invalid assignment operation '" + details::to_str(current_state.operation) + "'", + exprtk_error_location)); + + return error_node(); + } + + if (0 != (right_branch = parse_expression(current_state.right))) + { + if ( + details::is_return_node( expression) || + details::is_return_node(right_branch) + ) + { + free_node(node_allocator_, expression); + free_node(node_allocator_, right_branch); + + set_error( + make_error(parser_error::e_syntax, + prev_token, + "ERR012 - Return statements cannot be part of sub-expressions", + exprtk_error_location)); + + return error_node(); + } + + new_expression = expression_generator_ + ( + current_state.operation, + expression, + right_branch + ); + } + + if (0 == new_expression) + { + if (error_list_.empty()) + { + set_error( + make_error(parser_error::e_syntax, + prev_token, + !synthesis_error_.empty() ? + synthesis_error_ : + "ERR013 - General parsing error at token: '" + prev_token.value + "'", + exprtk_error_location)); + } + + free_node(node_allocator_, expression); + free_node(node_allocator_, right_branch); + + return error_node(); + } + else + { + if ( + token_is(token_t::e_ternary,prsrhlpr_t::e_hold) && + (precedence == e_level00) + ) + { + expression = parse_ternary_conditional_statement(new_expression); + } + else + expression = new_expression; + + parse_pending_string_rangesize(expression); + } + } + + return expression; + } + + bool simplify_unary_negation_branch(expression_node_ptr& node) + { + { + typedef details::unary_branch_node > ubn_t; + ubn_t* n = dynamic_cast(node); + + if (n) + { + expression_node_ptr un_r = n->branch(0); + n->release(); + free_node(node_allocator_,node); + node = un_r; + + return true; + } + } + + { + typedef details::unary_variable_node > uvn_t; + + uvn_t* n = dynamic_cast(node); + + if (n) + { + const T& v = n->v(); + expression_node_ptr return_node = error_node(); + + if ( + (0 != (return_node = symtab_store_.get_variable(v))) || + (0 != (return_node = sem_ .get_variable(v))) + ) + { + free_node(node_allocator_,node); + node = return_node; + + return true; + } + else + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR014 - Failed to find variable node in symbol table", + exprtk_error_location)); + + free_node(node_allocator_,node); + + return false; + } + } + } + + return false; + } + + static inline expression_node_ptr error_node() + { + return reinterpret_cast(0); + } + + template + struct scoped_delete + { + typedef Type* ptr_t; + + scoped_delete(parser& pr, ptr_t& p) + : delete_ptr(true), + parser_(pr), + p_(&p) + {} + + scoped_delete(parser& pr, ptr_t (&p)[N]) + : delete_ptr(true), + parser_(pr), + p_(&p[0]) + {} + + ~scoped_delete() + { + if (delete_ptr) + { + for (std::size_t i = 0; i < N; ++i) + { + free_node(parser_.node_allocator_,p_[i]); + } + } + } + + bool delete_ptr; + parser& parser_; + ptr_t* p_; + + private: + + scoped_delete& operator=(const scoped_delete&); + }; + + template + struct scoped_deq_delete + { + typedef Type* ptr_t; + + scoped_deq_delete(parser& pr, std::deque& deq) + : delete_ptr(true), + parser_(pr), + deq_(deq) + {} + + ~scoped_deq_delete() + { + if (delete_ptr && !deq_.empty()) + { + for (std::size_t i = 0; i < deq_.size(); ++i) + { + free_node(parser_.node_allocator_,deq_[i]); + } + + deq_.clear(); + } + } + + bool delete_ptr; + parser& parser_; + std::deque& deq_; + + private: + + scoped_deq_delete& operator=(const scoped_deq_delete&); + }; + + template + struct scoped_vec_delete + { + typedef Type* ptr_t; + + scoped_vec_delete(parser& pr, std::vector& vec) + : delete_ptr(true), + parser_(pr), + vec_(vec) + {} + + ~scoped_vec_delete() + { + if (delete_ptr && !vec_.empty()) + { + for (std::size_t i = 0; i < vec_.size(); ++i) + { + free_node(parser_.node_allocator_,vec_[i]); + } + + vec_.clear(); + } + } + + bool delete_ptr; + parser& parser_; + std::vector& vec_; + + private: + + scoped_vec_delete& operator=(const scoped_vec_delete&); + }; + + struct scoped_bool_negator + { + explicit scoped_bool_negator(bool& bb) + : b(bb) + { b = !b; } + + ~scoped_bool_negator() + { b = !b; } + + bool& b; + }; + + struct scoped_bool_or_restorer + { + explicit scoped_bool_or_restorer(bool& bb) + : b(bb), + original_value_(bb) + {} + + ~scoped_bool_or_restorer() + { + b = b || original_value_; + } + + bool& b; + bool original_value_; + }; + + inline expression_node_ptr parse_function_invocation(ifunction* function, const std::string& function_name) + { + expression_node_ptr func_node = reinterpret_cast(0); + + switch (function->param_count) + { + case 0 : func_node = parse_function_call_0 (function,function_name); break; + case 1 : func_node = parse_function_call< 1>(function,function_name); break; + case 2 : func_node = parse_function_call< 2>(function,function_name); break; + case 3 : func_node = parse_function_call< 3>(function,function_name); break; + case 4 : func_node = parse_function_call< 4>(function,function_name); break; + case 5 : func_node = parse_function_call< 5>(function,function_name); break; + case 6 : func_node = parse_function_call< 6>(function,function_name); break; + case 7 : func_node = parse_function_call< 7>(function,function_name); break; + case 8 : func_node = parse_function_call< 8>(function,function_name); break; + case 9 : func_node = parse_function_call< 9>(function,function_name); break; + case 10 : func_node = parse_function_call<10>(function,function_name); break; + case 11 : func_node = parse_function_call<11>(function,function_name); break; + case 12 : func_node = parse_function_call<12>(function,function_name); break; + case 13 : func_node = parse_function_call<13>(function,function_name); break; + case 14 : func_node = parse_function_call<14>(function,function_name); break; + case 15 : func_node = parse_function_call<15>(function,function_name); break; + case 16 : func_node = parse_function_call<16>(function,function_name); break; + case 17 : func_node = parse_function_call<17>(function,function_name); break; + case 18 : func_node = parse_function_call<18>(function,function_name); break; + case 19 : func_node = parse_function_call<19>(function,function_name); break; + case 20 : func_node = parse_function_call<20>(function,function_name); break; + default : { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR015 - Invalid number of parameters for function: '" + function_name + "'", + exprtk_error_location)); + + return error_node(); + } + } + + if (func_node) + return func_node; + else + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR016 - Failed to generate call to function: '" + function_name + "'", + exprtk_error_location)); + + return error_node(); + } + } + + template + inline expression_node_ptr parse_function_call(ifunction* function, const std::string& function_name) + { + #ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable: 4127) + #endif + if (0 == NumberofParameters) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR017 - Expecting ifunction '" + function_name + "' to have non-zero parameter count", + exprtk_error_location)); + + return error_node(); + } + #ifdef _MSC_VER + #pragma warning(pop) + #endif + + expression_node_ptr branch[NumberofParameters]; + expression_node_ptr result = error_node(); + + std::fill_n(branch, NumberofParameters, reinterpret_cast(0)); + + scoped_delete sd((*this),branch); + + next_token(); + + if (!token_is(token_t::e_lbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR018 - Expecting argument list for function: '" + function_name + "'", + exprtk_error_location)); + + return error_node(); + } + + for (int i = 0; i < static_cast(NumberofParameters); ++i) + { + branch[i] = parse_expression(); + + if (0 == branch[i]) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR019 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'", + exprtk_error_location)); + + return error_node(); + } + else if (i < static_cast(NumberofParameters - 1)) + { + if (!token_is(token_t::e_comma)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR020 - Invalid number of arguments for function: '" + function_name + "'", + exprtk_error_location)); + + return error_node(); + } + } + } + + if (!token_is(token_t::e_rbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR021 - Invalid number of arguments for function: '" + function_name + "'", + exprtk_error_location)); + + return error_node(); + } + else + result = expression_generator_.function(function,branch); + + sd.delete_ptr = false; + + return result; + } + + inline expression_node_ptr parse_function_call_0(ifunction* function, const std::string& function_name) + { + expression_node_ptr result = expression_generator_.function(function); + + state_.side_effect_present = function->has_side_effects(); + + next_token(); + + if ( + token_is(token_t::e_lbracket) && + !token_is(token_t::e_rbracket) + ) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR022 - Expecting '()' to proceed call to function: '" + function_name + "'", + exprtk_error_location)); + + free_node(node_allocator_,result); + + return error_node(); + } + else + return result; + } + + template + inline std::size_t parse_base_function_call(expression_node_ptr (¶m_list)[MaxNumberofParameters], const std::string& function_name = "") + { + std::fill_n(param_list, MaxNumberofParameters, reinterpret_cast(0)); + + scoped_delete sd((*this),param_list); + + next_token(); + + if (!token_is(token_t::e_lbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR023 - Expected a '(' at start of function call to '" + function_name + + "', instead got: '" + current_token().value + "'", + exprtk_error_location)); + + return 0; + } + + if (token_is(token_t::e_rbracket, e_hold)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR024 - Expected at least one input parameter for function call '" + function_name + "'", + exprtk_error_location)); + + return 0; + } + + std::size_t param_index = 0; + + for (; param_index < MaxNumberofParameters; ++param_index) + { + param_list[param_index] = parse_expression(); + + if (0 == param_list[param_index]) + return 0; + else if (token_is(token_t::e_rbracket)) + { + sd.delete_ptr = false; + break; + } + else if (token_is(token_t::e_comma)) + continue; + else + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR025 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'", + exprtk_error_location)); + + return 0; + } + } + + if (sd.delete_ptr) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR026 - Invalid number of input parameters passed to function '" + function_name + "'", + exprtk_error_location)); + + return 0; + } + + return (param_index + 1); + } + + inline expression_node_ptr parse_base_operation() + { + typedef std::pair map_range_t; + + const std::string operation_name = current_token().value; + const token_t diagnostic_token = current_token(); + + map_range_t itr_range = base_ops_map_.equal_range(operation_name); + + if (0 == std::distance(itr_range.first,itr_range.second)) + { + set_error( + make_error(parser_error::e_syntax, + diagnostic_token, + "ERR027 - No entry found for base operation: " + operation_name, + exprtk_error_location)); + + return error_node(); + } + + static const std::size_t MaxNumberofParameters = 4; + expression_node_ptr param_list[MaxNumberofParameters] = {0}; + + const std::size_t parameter_count = parse_base_function_call(param_list, operation_name); + + if ((parameter_count > 0) && (parameter_count <= MaxNumberofParameters)) + { + for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr) + { + const details::base_operation_t& operation = itr->second; + + if (operation.num_params == parameter_count) + { + switch (parameter_count) + { + #define base_opr_case(N) \ + case N : { \ + expression_node_ptr pl##N[N] = {0}; \ + std::copy(param_list, param_list + N, pl##N); \ + lodge_symbol(operation_name, e_st_function); \ + return expression_generator_(operation.type, pl##N); \ + } \ + + base_opr_case(1) + base_opr_case(2) + base_opr_case(3) + base_opr_case(4) + #undef base_opr_case + } + } + } + } + + for (std::size_t i = 0; i < MaxNumberofParameters; ++i) + { + free_node(node_allocator_, param_list[i]); + } + + set_error( + make_error(parser_error::e_syntax, + diagnostic_token, + "ERR028 - Invalid number of input parameters for call to function: '" + operation_name + "'", + exprtk_error_location)); + + return error_node(); + } + + inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition) + { + // Parse: [if][(][condition][,][consequent][,][alternative][)] + + expression_node_ptr consequent = error_node(); + expression_node_ptr alternative = error_node(); + + bool result = true; + + if (!token_is(token_t::e_comma)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR029 - Expected ',' between if-statement condition and consequent", + exprtk_error_location)); + result = false; + } + else if (0 == (consequent = parse_expression())) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR030 - Failed to parse consequent for if-statement", + exprtk_error_location)); + result = false; + } + else if (!token_is(token_t::e_comma)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR031 - Expected ',' between if-statement consequent and alternative", + exprtk_error_location)); + result = false; + } + else if (0 == (alternative = parse_expression())) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR032 - Failed to parse alternative for if-statement", + exprtk_error_location)); + result = false; + } + else if (!token_is(token_t::e_rbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR033 - Expected ')' at the end of if-statement", + exprtk_error_location)); + result = false; + } + + #ifndef exprtk_disable_string_capabilities + if (result) + { + const bool consq_is_str = is_generally_string_node( consequent); + const bool alter_is_str = is_generally_string_node(alternative); + + if (consq_is_str || alter_is_str) + { + if (consq_is_str && alter_is_str) + { + return expression_generator_ + .conditional_string(condition,consequent,alternative); + } + + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR034 - Return types of ternary if-statement differ", + exprtk_error_location)); + + result = false; + } + } + #endif + + if (!result) + { + free_node(node_allocator_, condition); + free_node(node_allocator_, consequent); + free_node(node_allocator_,alternative); + + return error_node(); + } + else + return expression_generator_ + .conditional(condition,consequent,alternative); + } + + inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition) + { + expression_node_ptr consequent = error_node(); + expression_node_ptr alternative = error_node(); + + bool result = true; + + if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) + { + if (0 == (consequent = parse_multi_sequence("if-statement-01"))) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR035 - Failed to parse body of consequent for if-statement", + exprtk_error_location)); + + result = false; + } + } + else + { + if ( + settings_.commutative_check_enabled() && + token_is(token_t::e_mul,prsrhlpr_t::e_hold) + ) + { + next_token(); + } + + if (0 != (consequent = parse_expression())) + { + if (!token_is(token_t::e_eof)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR036 - Expected ';' at the end of the consequent for if-statement", + exprtk_error_location)); + + result = false; + } + } + else + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR037 - Failed to parse body of consequent for if-statement", + exprtk_error_location)); + + result = false; + } + } + + if (result) + { + if (details::imatch(current_token().value,"else")) + { + next_token(); + + if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) + { + if (0 == (alternative = parse_multi_sequence("else-statement-01"))) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR038 - Failed to parse body of the 'else' for if-statement", + exprtk_error_location)); + + result = false; + } + } + else if (details::imatch(current_token().value,"if")) + { + if (0 == (alternative = parse_conditional_statement())) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR039 - Failed to parse body of if-else statement", + exprtk_error_location)); + + result = false; + } + } + else if (0 != (alternative = parse_expression())) + { + if (!token_is(token_t::e_eof)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR040 - Expected ';' at the end of the 'else-if' for the if-statement", + exprtk_error_location)); + + result = false; + } + } + else + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR041 - Failed to parse body of the 'else' for if-statement", + exprtk_error_location)); + + result = false; + } + } + } + + #ifndef exprtk_disable_string_capabilities + if (result) + { + const bool consq_is_str = is_generally_string_node( consequent); + const bool alter_is_str = is_generally_string_node(alternative); + + if (consq_is_str || alter_is_str) + { + if (consq_is_str && alter_is_str) + { + return expression_generator_ + .conditional_string(condition, consequent, alternative); + } + + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR042 - Return types of ternary if-statement differ", + exprtk_error_location)); + + result = false; + } + } + #endif + + if (!result) + { + free_node(node_allocator_, condition); + free_node(node_allocator_, consequent); + free_node(node_allocator_, alternative); + + return error_node(); + } + else + return expression_generator_ + .conditional(condition, consequent, alternative); + } + + inline expression_node_ptr parse_conditional_statement() + { + expression_node_ptr condition = error_node(); + + next_token(); + + if (!token_is(token_t::e_lbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR043 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'", + exprtk_error_location)); + + return error_node(); + } + else if (0 == (condition = parse_expression())) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR044 - Failed to parse condition for if-statement", + exprtk_error_location)); + + return error_node(); + } + else if (token_is(token_t::e_comma,prsrhlpr_t::e_hold)) + { + // if (x,y,z) + return parse_conditional_statement_01(condition); + } + else if (token_is(token_t::e_rbracket)) + { + // 00. if (x) y; + // 01. if (x) y; else z; + // 02. if (x) y; else {z0; ... zn;} + // 03. if (x) y; else if (z) w; + // 04. if (x) y; else if (z) w; else u; + // 05. if (x) y; else if (z) w; else {u0; ... un;} + // 06. if (x) y; else if (z) {w0; ... wn;} + // 07. if (x) {y0; ... yn;} + // 08. if (x) {y0; ... yn;} else z; + // 09. if (x) {y0; ... yn;} else {z0; ... zn;}; + // 10. if (x) {y0; ... yn;} else if (z) w; + // 11. if (x) {y0; ... yn;} else if (z) w; else u; + // 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;} + // 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;} + return parse_conditional_statement_02(condition); + } + + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR045 - Invalid if-statement", + exprtk_error_location)); + + free_node(node_allocator_,condition); + + return error_node(); + } + + inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition) + { + // Parse: [condition][?][consequent][:][alternative] + expression_node_ptr consequent = error_node(); + expression_node_ptr alternative = error_node(); + + bool result = true; + + if (0 == condition) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR046 - Encountered invalid condition branch for ternary if-statement", + exprtk_error_location)); + + return error_node(); + } + else if (!token_is(token_t::e_ternary)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR047 - Expected '?' after condition of ternary if-statement", + exprtk_error_location)); + + result = false; + } + else if (0 == (consequent = parse_expression())) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR048 - Failed to parse consequent for ternary if-statement", + exprtk_error_location)); + + result = false; + } + else if (!token_is(token_t::e_colon)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR049 - Expected ':' between ternary if-statement consequent and alternative", + exprtk_error_location)); + + result = false; + } + else if (0 == (alternative = parse_expression())) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR050 - Failed to parse alternative for ternary if-statement", + exprtk_error_location)); + + result = false; + } + + #ifndef exprtk_disable_string_capabilities + if (result) + { + const bool consq_is_str = is_generally_string_node( consequent); + const bool alter_is_str = is_generally_string_node(alternative); + + if (consq_is_str || alter_is_str) + { + if (consq_is_str && alter_is_str) + { + return expression_generator_ + .conditional_string(condition, consequent, alternative); + } + + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR051 - Return types of ternary if-statement differ", + exprtk_error_location)); + + result = false; + } + } + #endif + + if (!result) + { + free_node(node_allocator_, condition); + free_node(node_allocator_, consequent); + free_node(node_allocator_, alternative); + + return error_node(); + } + else + return expression_generator_ + .conditional(condition, consequent, alternative); + } + + inline expression_node_ptr parse_while_loop() + { + // Parse: [while][(][test expr][)][{][expression][}] + expression_node_ptr condition = error_node(); + expression_node_ptr branch = error_node(); + expression_node_ptr result_node = error_node(); + + bool result = true; + + next_token(); + + if (!token_is(token_t::e_lbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR052 - Expected '(' at start of while-loop condition statement", + exprtk_error_location)); + + return error_node(); + } + else if (0 == (condition = parse_expression())) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR053 - Failed to parse condition for while-loop", + exprtk_error_location)); + + return error_node(); + } + else if (!token_is(token_t::e_rbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR054 - Expected ')' at end of while-loop condition statement", + exprtk_error_location)); + + result = false; + } + + brkcnt_list_.push_front(false); + + if (result) + { + if (0 == (branch = parse_multi_sequence("while-loop"))) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR055 - Failed to parse body of while-loop")); + result = false; + } + else if (0 == (result_node = expression_generator_.while_loop(condition, + branch, + brkcnt_list_.front()))) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR056 - Failed to synthesize while-loop", + exprtk_error_location)); + + result = false; + } + } + + if (!result) + { + free_node(node_allocator_, branch); + free_node(node_allocator_, condition); + free_node(node_allocator_, result_node); + + brkcnt_list_.pop_front(); + + return error_node(); + } + else + return result_node; + } + + inline expression_node_ptr parse_repeat_until_loop() + { + // Parse: [repeat][{][expression][}][until][(][test expr][)] + expression_node_ptr condition = error_node(); + expression_node_ptr branch = error_node(); + next_token(); + + std::vector arg_list; + std::vector side_effect_list; + + scoped_vec_delete sdd((*this),arg_list); + + brkcnt_list_.push_front(false); + + if (details::imatch(current_token().value,"until")) + { + next_token(); + branch = node_allocator_.allocate >(); + } + else + { + const token_t::token_type seperator = token_t::e_eof; + + scope_handler sh(*this); + + scoped_bool_or_restorer sbr(state_.side_effect_present); + + for ( ; ; ) + { + state_.side_effect_present = false; + + expression_node_ptr arg = parse_expression(); + + if (0 == arg) + return error_node(); + else + { + arg_list.push_back(arg); + side_effect_list.push_back(state_.side_effect_present); + } + + if (details::imatch(current_token().value,"until")) + { + next_token(); + break; + } + + const bool is_next_until = peek_token_is(token_t::e_symbol) && + peek_token_is("until"); + + if (!token_is(seperator) && is_next_until) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR057 - Expected '" + token_t::to_str(seperator) + "' in body of repeat until loop", + exprtk_error_location)); + + return error_node(); + } + + if (details::imatch(current_token().value,"until")) + { + next_token(); + break; + } + } + + branch = simplify(arg_list,side_effect_list); + + sdd.delete_ptr = (0 == branch); + + if (sdd.delete_ptr) + { + brkcnt_list_.pop_front(); + + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR058 - Failed to parse body of repeat until loop", + exprtk_error_location)); + + return error_node(); + } + } + + if (!token_is(token_t::e_lbracket)) + { + brkcnt_list_.pop_front(); + + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR059 - Expected '(' before condition statement of repeat until loop", + exprtk_error_location)); + + free_node(node_allocator_,branch); + + return error_node(); + } + else if (0 == (condition = parse_expression())) + { + brkcnt_list_.pop_front(); + + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR060 - Failed to parse condition for repeat until loop", + exprtk_error_location)); + + free_node(node_allocator_,branch); + + return error_node(); + } + else if (!token_is(token_t::e_rbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR061 - Expected ')' after condition of repeat until loop", + exprtk_error_location)); + + free_node(node_allocator_, branch); + free_node(node_allocator_, condition); + + brkcnt_list_.pop_front(); + + return error_node(); + } + + expression_node_ptr result; + + result = expression_generator_ + .repeat_until_loop(condition, branch, brkcnt_list_.front()); + + if (0 == result) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR062 - Failed to synthesize repeat until loop", + exprtk_error_location)); + + free_node(node_allocator_,condition); + + brkcnt_list_.pop_front(); + + return error_node(); + } + else + { + brkcnt_list_.pop_front(); + return result; + } + } + + inline expression_node_ptr parse_for_loop() + { + expression_node_ptr initialiser = error_node(); + expression_node_ptr condition = error_node(); + expression_node_ptr incrementor = error_node(); + expression_node_ptr loop_body = error_node(); + + scope_element* se = 0; + bool result = true; + + next_token(); + + scope_handler sh(*this); + + if (!token_is(token_t::e_lbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR063 - Expected '(' at start of for-loop", + exprtk_error_location)); + + return error_node(); + } + + if (!token_is(token_t::e_eof)) + { + if ( + !token_is(token_t::e_symbol,prsrhlpr_t::e_hold) && + details::imatch(current_token().value,"var") + ) + { + next_token(); + + if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR064 - Expected a variable at the start of initialiser section of for-loop", + exprtk_error_location)); + + return error_node(); + } + else if (!peek_token_is(token_t::e_assign)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR065 - Expected variable assignment of initialiser section of for-loop", + exprtk_error_location)); + + return error_node(); + } + + const std::string loop_counter_symbol = current_token().value; + + se = &sem_.get_element(loop_counter_symbol); + + if ((se->name == loop_counter_symbol) && se->active) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR066 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration", + exprtk_error_location)); + + return error_node(); + } + else if (!symtab_store_.is_variable(loop_counter_symbol)) + { + if ( + !se->active && + (se->name == loop_counter_symbol) && + (se->type == scope_element::e_variable) + ) + { + se->active = true; + se->ref_count++; + } + else + { + scope_element nse; + nse.name = loop_counter_symbol; + nse.active = true; + nse.ref_count = 1; + nse.type = scope_element::e_variable; + nse.depth = state_.scope_depth; + nse.data = new T(T(0)); + nse.var_node = node_allocator_.allocate(*(T*)(nse.data)); + + if (!sem_.add_element(nse)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR067 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM", + exprtk_error_location)); + + sem_.free_element(nse); + + result = false; + } + else + { + exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n",nse.name.c_str())); + + state_.activate_side_effect("parse_for_loop()"); + } + } + } + } + + if (0 == (initialiser = parse_expression())) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR068 - Failed to parse initialiser of for-loop", + exprtk_error_location)); + + result = false; + } + else if (!token_is(token_t::e_eof)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR069 - Expected ';' after initialiser of for-loop", + exprtk_error_location)); + + result = false; + } + } + + if (!token_is(token_t::e_eof)) + { + if (0 == (condition = parse_expression())) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR070 - Failed to parse condition of for-loop", + exprtk_error_location)); + + result = false; + } + else if (!token_is(token_t::e_eof)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR071 - Expected ';' after condition section of for-loop", + exprtk_error_location)); + + result = false; + } + } + + if (!token_is(token_t::e_rbracket)) + { + if (0 == (incrementor = parse_expression())) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR072 - Failed to parse incrementor of for-loop", + exprtk_error_location)); + + result = false; + } + else if (!token_is(token_t::e_rbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR073 - Expected ')' after incrementor section of for-loop", + exprtk_error_location)); + + result = false; + } + } + + if (result) + { + brkcnt_list_.push_front(false); + + if (0 == (loop_body = parse_multi_sequence("for-loop"))) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR074 - Failed to parse body of for-loop", + exprtk_error_location)); + + result = false; + } + } + + if (!result) + { + if (se) + { + se->ref_count--; + } + + free_node(node_allocator_, initialiser); + free_node(node_allocator_, condition); + free_node(node_allocator_, incrementor); + free_node(node_allocator_, loop_body); + + if (!brkcnt_list_.empty()) + { + brkcnt_list_.pop_front(); + } + + return error_node(); + } + else + { + expression_node_ptr result_node = + expression_generator_.for_loop(initialiser, + condition, + incrementor, + loop_body, + brkcnt_list_.front()); + brkcnt_list_.pop_front(); + + return result_node; + } + } + + inline expression_node_ptr parse_switch_statement() + { + std::vector arg_list; + expression_node_ptr result = error_node(); + + if (!details::imatch(current_token().value,"switch")) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR075 - Expected keyword 'switch'", + exprtk_error_location)); + + return error_node(); + } + + scoped_vec_delete svd((*this),arg_list); + + next_token(); + + if (!token_is(token_t::e_lcrlbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR076 - Expected '{' for call to switch statement", + exprtk_error_location)); + + return error_node(); + } + + for ( ; ; ) + { + if (!details::imatch("case",current_token().value)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR077 - Expected either a 'case' or 'default' statement", + exprtk_error_location)); + + return error_node(); + } + + next_token(); + + expression_node_ptr condition = parse_expression(); + + if (0 == condition) + return error_node(); + else if (!token_is(token_t::e_colon)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR078 - Expected ':' for case of switch statement", + exprtk_error_location)); + + return error_node(); + } + + expression_node_ptr consequent = parse_expression(); + + if (0 == consequent) + return error_node(); + else if (!token_is(token_t::e_eof)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR079 - Expected ';' at end of case for switch statement", + exprtk_error_location)); + + return error_node(); + } + + // Can we optimise away the case statement? + if (is_constant_node(condition) && is_false(condition)) + { + free_node(node_allocator_, condition); + free_node(node_allocator_, consequent); + } + else + { + arg_list.push_back( condition); + arg_list.push_back(consequent); + } + + if (details::imatch("default",current_token().value)) + { + next_token(); + if (!token_is(token_t::e_colon)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR080 - Expected ':' for default of switch statement", + exprtk_error_location)); + + return error_node(); + } + + expression_node_ptr default_statement = error_node(); + + if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) + default_statement = parse_multi_sequence("switch-default"); + else + default_statement = parse_expression(); + + if (0 == default_statement) + return error_node(); + else if (!token_is(token_t::e_eof)) + { + free_node(node_allocator_,default_statement); + + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR081 - Expected ';' at end of default for switch statement", + exprtk_error_location)); + + return error_node(); + } + + arg_list.push_back(default_statement); + break; + } + } + + if (!token_is(token_t::e_rcrlbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR082 - Expected '}' at end of switch statement", + exprtk_error_location)); + + return error_node(); + } + + result = expression_generator_.switch_statement(arg_list); + + svd.delete_ptr = (0 == result); + + return result; + } + + inline expression_node_ptr parse_multi_switch_statement() + { + std::vector arg_list; + + if (!details::imatch(current_token().value,"[*]")) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR083 - Expected token '[*]'", + exprtk_error_location)); + + return error_node(); + } + + scoped_vec_delete svd((*this),arg_list); + + next_token(); + + if (!token_is(token_t::e_lcrlbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR084 - Expected '{' for call to [*] statement", + exprtk_error_location)); + + return error_node(); + } + + for ( ; ; ) + { + if (!details::imatch("case",current_token().value)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR085 - Expected a 'case' statement for multi-switch", + exprtk_error_location)); + + return error_node(); + } + + next_token(); + + expression_node_ptr condition = parse_expression(); + + if (0 == condition) + return error_node(); + + if (!token_is(token_t::e_colon)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR086 - Expected ':' for case of [*] statement", + exprtk_error_location)); + + return error_node(); + } + + expression_node_ptr consequent = parse_expression(); + + if (0 == consequent) + return error_node(); + + if (!token_is(token_t::e_eof)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR087 - Expected ';' at end of case for [*] statement", + exprtk_error_location)); + + return error_node(); + } + + // Can we optimise away the case statement? + if (is_constant_node(condition) && is_false(condition)) + { + free_node(node_allocator_, condition); + free_node(node_allocator_, consequent); + } + else + { + arg_list.push_back( condition); + arg_list.push_back(consequent); + } + + if (token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold)) + { + break; + } + } + + if (!token_is(token_t::e_rcrlbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR088 - Expected '}' at end of [*] statement", + exprtk_error_location)); + + return error_node(); + } + + const expression_node_ptr result = expression_generator_.multi_switch_statement(arg_list); + + svd.delete_ptr = (0 == result); + + return result; + } + + inline expression_node_ptr parse_vararg_function() + { + std::vector arg_list; + + details::operator_type opt_type = details::e_default; + const std::string symbol = current_token().value; + + if (details::imatch(symbol,"~")) + { + next_token(); + return parse_multi_sequence(); + } + else if (details::imatch(symbol,"[*]")) + { + return parse_multi_switch_statement(); + } + else if (details::imatch(symbol, "avg" )) opt_type = details::e_avg ; + else if (details::imatch(symbol, "mand")) opt_type = details::e_mand; + else if (details::imatch(symbol, "max" )) opt_type = details::e_max ; + else if (details::imatch(symbol, "min" )) opt_type = details::e_min ; + else if (details::imatch(symbol, "mor" )) opt_type = details::e_mor ; + else if (details::imatch(symbol, "mul" )) opt_type = details::e_prod; + else if (details::imatch(symbol, "sum" )) opt_type = details::e_sum ; + else + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR089 - Unsupported vararg function: " + symbol, + exprtk_error_location)); + + return error_node(); + } + + scoped_vec_delete sdd((*this),arg_list); + + lodge_symbol(symbol, e_st_function); + + next_token(); + + if (!token_is(token_t::e_lbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR090 - Expected '(' for call to vararg function: " + symbol, + exprtk_error_location)); + + return error_node(); + } + + for ( ; ; ) + { + expression_node_ptr arg = parse_expression(); + + if (0 == arg) + return error_node(); + else + arg_list.push_back(arg); + + if (token_is(token_t::e_rbracket)) + break; + else if (!token_is(token_t::e_comma)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR091 - Expected ',' for call to vararg function: " + symbol, + exprtk_error_location)); + + return error_node(); + } + } + + const expression_node_ptr result = expression_generator_.vararg_function(opt_type,arg_list); + + sdd.delete_ptr = (0 == result); + return result; + } + + #ifndef exprtk_disable_string_capabilities + inline expression_node_ptr parse_string_range_statement(expression_node_ptr& expression) + { + if (!token_is(token_t::e_lsqrbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR092 - Expected '[' as start of string range definition", + exprtk_error_location)); + + free_node(node_allocator_,expression); + + return error_node(); + } + else if (token_is(token_t::e_rsqrbracket)) + { + return node_allocator_.allocate >(expression); + } + + range_t rp; + + if (!parse_range(rp,true)) + { + free_node(node_allocator_,expression); + + return error_node(); + } + + expression_node_ptr result = expression_generator_(expression,rp); + + if (0 == result) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR093 - Failed to generate string range node", + exprtk_error_location)); + + free_node(node_allocator_,expression); + } + + rp.clear(); + + return result; + } + #else + inline expression_node_ptr parse_string_range_statement(expression_node_ptr&) + { + return error_node(); + } + #endif + + inline void parse_pending_string_rangesize(expression_node_ptr& expression) + { + // Allow no more than 100 range calls, eg: s[][][]...[][] + const std::size_t max_rangesize_parses = 100; + + std::size_t i = 0; + + while + ( + (0 != expression) && + (i++ < max_rangesize_parses) && + error_list_.empty() && + is_generally_string_node(expression) && + token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold) + ) + { + expression = parse_string_range_statement(expression); + } + } + + template class Sequence> + inline expression_node_ptr simplify(Sequence& expression_list, + Sequence& side_effect_list, + const bool specialise_on_final_type = false) + { + if (expression_list.empty()) + return error_node(); + else if (1 == expression_list.size()) + return expression_list[0]; + + Sequence tmp_expression_list; + + bool return_node_present = false; + + for (std::size_t i = 0; i < (expression_list.size() - 1); ++i) + { + if (is_variable_node(expression_list[i])) + continue; + else if ( + is_return_node (expression_list[i]) || + is_break_node (expression_list[i]) || + is_continue_node(expression_list[i]) + ) + { + tmp_expression_list.push_back(expression_list[i]); + + // Remove all subexpressions after first short-circuit + // node has been encountered. + + for (std::size_t j = i + 1; j < expression_list.size(); ++j) + { + free_node(node_allocator_,expression_list[j]); + } + + return_node_present = true; + + break; + } + else if ( + is_constant_node(expression_list[i]) || + is_null_node (expression_list[i]) || + !side_effect_list[i] + ) + { + free_node(node_allocator_,expression_list[i]); + continue; + } + else + tmp_expression_list.push_back(expression_list[i]); + } + + if (!return_node_present) + { + tmp_expression_list.push_back(expression_list.back()); + } + + expression_list.swap(tmp_expression_list); + + if (tmp_expression_list.size() > expression_list.size()) + { + exprtk_debug(("simplify() - Reduced subexpressions from %d to %d\n", + static_cast(tmp_expression_list.size()), + static_cast(expression_list .size()))); + } + + if ( + return_node_present || + side_effect_list.back() || + (expression_list.size() > 1) + ) + state_.activate_side_effect("simplify()"); + + if (1 == expression_list.size()) + return expression_list[0]; + else if (specialise_on_final_type && is_generally_string_node(expression_list.back())) + return expression_generator_.vararg_function(details::e_smulti,expression_list); + else + return expression_generator_.vararg_function(details::e_multi,expression_list); + } + + inline expression_node_ptr parse_multi_sequence(const std::string& source = "") + { + token_t::token_type close_bracket = token_t::e_rcrlbracket; + token_t::token_type seperator = token_t::e_eof; + + if (!token_is(token_t::e_lcrlbracket)) + { + if (token_is(token_t::e_lbracket)) + { + close_bracket = token_t::e_rbracket; + seperator = token_t::e_comma; + } + else + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR094 - Expected '" + token_t::to_str(close_bracket) + "' for call to multi-sequence" + + ((!source.empty()) ? std::string(" section of " + source): ""), + exprtk_error_location)); + + return error_node(); + } + } + else if (token_is(token_t::e_rcrlbracket)) + { + return node_allocator_.allocate >(); + } + + std::vector arg_list; + std::vector side_effect_list; + + expression_node_ptr result = error_node(); + + scoped_vec_delete sdd((*this),arg_list); + + scope_handler sh(*this); + + scoped_bool_or_restorer sbr(state_.side_effect_present); + + for ( ; ; ) + { + state_.side_effect_present = false; + + expression_node_ptr arg = parse_expression(); + + if (0 == arg) + return error_node(); + else + { + arg_list.push_back(arg); + side_effect_list.push_back(state_.side_effect_present); + } + + if (token_is(close_bracket)) + break; + + const bool is_next_close = peek_token_is(close_bracket); + + if (!token_is(seperator) && is_next_close) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR095 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source, + exprtk_error_location)); + + return error_node(); + } + + if (token_is(close_bracket)) + break; + } + + result = simplify(arg_list,side_effect_list,source.empty()); + + sdd.delete_ptr = (0 == result); + return result; + } + + inline bool parse_range(range_t& rp, const bool skip_lsqr = false) + { + // Examples of valid ranges: + // 1. [1:5] -> 1..5 + // 2. [ :5] -> 0..5 + // 3. [1: ] -> 1..end + // 4. [x:y] -> x..y where x <= y + // 5. [x+1:y/2] -> x+1..y/2 where x+1 <= y/2 + // 6. [ :y] -> 0..y where 0 <= y + // 7. [x: ] -> x..end where x <= end + + rp.clear(); + + if (!skip_lsqr && !token_is(token_t::e_lsqrbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR096 - Expected '[' for start of range", + exprtk_error_location)); + + return false; + } + + if (token_is(token_t::e_colon)) + { + rp.n0_c.first = true; + rp.n0_c.second = 0; + rp.cache.first = 0; + } + else + { + expression_node_ptr r0 = parse_expression(); + + if (0 == r0) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR097 - Failed parse begin section of range", + exprtk_error_location)); + + return false; + } + else if (is_constant_node(r0)) + { + const T r0_value = r0->value(); + + if (r0_value >= T(0)) + { + rp.n0_c.first = true; + rp.n0_c.second = static_cast(details::numeric::to_int64(r0_value)); + rp.cache.first = rp.n0_c.second; + } + + free_node(node_allocator_,r0); + + if (r0_value < T(0)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR098 - Range lower bound less than zero! Constraint: r0 >= 0", + exprtk_error_location)); + + return false; + } + } + else + { + rp.n0_e.first = true; + rp.n0_e.second = r0; + } + + if (!token_is(token_t::e_colon)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR099 - Expected ':' for break in range", + exprtk_error_location)); + + rp.free(); + + return false; + } + } + + if (token_is(token_t::e_rsqrbracket)) + { + rp.n1_c.first = true; + rp.n1_c.second = std::numeric_limits::max(); + } + else + { + expression_node_ptr r1 = parse_expression(); + + if (0 == r1) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR100 - Failed parse end section of range", + exprtk_error_location)); + + rp.free(); + + return false; + } + else if (is_constant_node(r1)) + { + const T r1_value = r1->value(); + + if (r1_value >= T(0)) + { + rp.n1_c.first = true; + rp.n1_c.second = static_cast(details::numeric::to_int64(r1_value)); + rp.cache.second = rp.n1_c.second; + } + + free_node(node_allocator_,r1); + + if (r1_value < T(0)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR101 - Range upper bound less than zero! Constraint: r1 >= 0", + exprtk_error_location)); + + return false; + } + } + else + { + rp.n1_e.first = true; + rp.n1_e.second = r1; + } + + if (!token_is(token_t::e_rsqrbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR102 - Expected ']' for start of range", + exprtk_error_location)); + + rp.free(); + + return false; + } + } + + if (rp.const_range()) + { + std::size_t r0 = 0; + std::size_t r1 = 0; + + const bool rp_result = rp(r0,r1); + + if (!rp_result || (r0 > r1)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR103 - Invalid range, Constraint: r0 <= r1", + exprtk_error_location)); + + return false; + } + } + + return true; + } + + inline void lodge_symbol(const std::string& symbol, + const symbol_type st) + { + dec_.add_symbol(symbol,st); + } + + #ifndef exprtk_disable_string_capabilities + inline expression_node_ptr parse_string() + { + const std::string symbol = current_token().value; + + typedef details::stringvar_node* strvar_node_t; + + expression_node_ptr result = error_node(); + strvar_node_t const_str_node = static_cast(0); + + scope_element& se = sem_.get_active_element(symbol); + + if (scope_element::e_string == se.type) + { + se.active = true; + result = se.str_node; + lodge_symbol(symbol, e_st_local_string); + } + else + { + if (!symtab_store_.is_conststr_stringvar(symbol)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR104 - Unknown string symbol", + exprtk_error_location)); + + return error_node(); + } + + result = symtab_store_.get_stringvar(symbol); + + if (symtab_store_.is_constant_string(symbol)) + { + const_str_node = static_cast(result); + result = expression_generator_(const_str_node->str()); + } + + lodge_symbol(symbol, e_st_string); + } + + if (peek_token_is(token_t::e_lsqrbracket)) + { + next_token(); + + if (peek_token_is(token_t::e_rsqrbracket)) + { + next_token(); + next_token(); + + if (const_str_node) + { + free_node(node_allocator_,result); + + return expression_generator_(T(const_str_node->size())); + } + else + return node_allocator_.allocate > + (static_cast*>(result)->ref()); + } + + range_t rp; + + if (!parse_range(rp)) + { + free_node(node_allocator_,result); + + return error_node(); + } + else if (const_str_node) + { + free_node(node_allocator_,result); + result = expression_generator_(const_str_node->ref(),rp); + } + else + result = expression_generator_(static_cast*> + (result)->ref(), rp); + + if (result) + rp.clear(); + } + else + next_token(); + + return result; + } + #else + inline expression_node_ptr parse_string() + { + return error_node(); + } + #endif + + #ifndef exprtk_disable_string_capabilities + inline expression_node_ptr parse_const_string() + { + const std::string const_str = current_token().value; + expression_node_ptr result = expression_generator_(const_str); + + if (peek_token_is(token_t::e_lsqrbracket)) + { + next_token(); + + if (peek_token_is(token_t::e_rsqrbracket)) + { + next_token(); + next_token(); + + free_node(node_allocator_,result); + + return expression_generator_(T(const_str.size())); + } + + range_t rp; + + if (!parse_range(rp)) + { + free_node(node_allocator_,result); + + return error_node(); + } + + free_node(node_allocator_,result); + + if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits::max())) + { + rp.n1_c.second = const_str.size() - 1; + rp.cache.second = rp.n1_c.second; + } + + if ( + (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) || + (rp.n1_c.first && (rp.n1_c.second >= const_str.size())) + ) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR105 - Overflow in range for string: '" + const_str + "'[" + + (rp.n0_c.first ? details::to_str(static_cast(rp.n0_c.second)) : "?") + ":" + + (rp.n1_c.first ? details::to_str(static_cast(rp.n1_c.second)) : "?") + "]", + exprtk_error_location)); + + return error_node(); + } + + result = expression_generator_(const_str,rp); + + if (result) + rp.clear(); + } + else + next_token(); + + return result; + } + #else + inline expression_node_ptr parse_const_string() + { + return error_node(); + } + #endif + + inline expression_node_ptr parse_vector() + { + const std::string symbol = current_token().value; + + vector_holder_ptr vec = vector_holder_ptr(0); + + const scope_element& se = sem_.get_active_element(symbol); + + if ( + !details::imatch(se.name, symbol) || + (se.depth > state_.scope_depth) || + (scope_element::e_vector != se.type) + ) + { + if (0 == (vec = symtab_store_.get_vector(symbol))) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR106 - Symbol '" + symbol+ " not a vector", + exprtk_error_location)); + + return error_node(); + } + } + else + vec = se.vec_node; + + expression_node_ptr index_expr = error_node(); + + next_token(); + + if (!token_is(token_t::e_lsqrbracket)) + { + return node_allocator_.allocate(vec); + } + else if (token_is(token_t::e_rsqrbracket)) + { + return expression_generator_(T(vec->size())); + } + else if (0 == (index_expr = parse_expression())) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR107 - Failed to parse index for vector: '" + symbol + "'", + exprtk_error_location)); + + return error_node(); + } + else if (!token_is(token_t::e_rsqrbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR108 - Expected ']' for index of vector: '" + symbol + "'", + exprtk_error_location)); + + free_node(node_allocator_,index_expr); + + return error_node(); + } + + // Perform compile-time range check + if (details::is_constant_node(index_expr)) + { + const std::size_t index = static_cast(details::numeric::to_int32(index_expr->value())); + const std::size_t vec_size = vec->size(); + + if (index >= vec_size) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR109 - Index of " + details::to_str(index) + " out of range for " + "vector '" + symbol + "' of size " + details::to_str(vec_size), + exprtk_error_location)); + + free_node(node_allocator_,index_expr); + + return error_node(); + } + } + + return expression_generator_.vector_element(symbol,vec,index_expr); + } + + inline expression_node_ptr parse_vararg_function_call(ivararg_function* vararg_function, const std::string& vararg_function_name) + { + std::vector arg_list; + + expression_node_ptr result = error_node(); + + scoped_vec_delete sdd((*this),arg_list); + + next_token(); + + if (token_is(token_t::e_lbracket)) + { + if (token_is(token_t::e_rbracket)) + { + if (!vararg_function->allow_zero_parameters()) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR110 - Zero parameter call to vararg function: " + + vararg_function_name + " not allowed", + exprtk_error_location)); + + return error_node(); + } + } + else + { + for ( ; ; ) + { + expression_node_ptr arg = parse_expression(); + + if (0 == arg) + return error_node(); + else + arg_list.push_back(arg); + + if (token_is(token_t::e_rbracket)) + break; + else if (!token_is(token_t::e_comma)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR111 - Expected ',' for call to vararg function: " + + vararg_function_name, + exprtk_error_location)); + + return error_node(); + } + } + } + } + else if (!vararg_function->allow_zero_parameters()) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR112 - Zero parameter call to vararg function: " + + vararg_function_name + " not allowed", + exprtk_error_location)); + + return error_node(); + } + + if (arg_list.size() < vararg_function->min_num_args()) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR113 - Invalid number of parameters to call to vararg function: " + + vararg_function_name + ", require at least " + + details::to_str(static_cast(vararg_function->min_num_args())) + " parameters", + exprtk_error_location)); + + return error_node(); + } + else if (arg_list.size() > vararg_function->max_num_args()) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR114 - Invalid number of parameters to call to vararg function: " + + vararg_function_name + ", require no more than " + + details::to_str(static_cast(vararg_function->max_num_args())) + " parameters", + exprtk_error_location)); + + return error_node(); + } + + result = expression_generator_.vararg_function_call(vararg_function,arg_list); + + sdd.delete_ptr = (0 == result); + + return result; + } + + class type_checker + { + public: + + enum return_type_t + { + e_overload = ' ', + e_numeric = 'T', + e_string = 'S' + }; + + struct function_prototype_t + { + return_type_t return_type; + std::string param_seq; + }; + + typedef parser parser_t; + typedef std::vector function_definition_list_t; + + type_checker(parser_t& p, + const std::string& func_name, + const std::string& func_prototypes, + const return_type_t default_return_type) + : invalid_state_(true), + parser_(p), + function_name_(func_name), + default_return_type_(default_return_type) + { + parse_function_prototypes(func_prototypes); + } + + void set_default_return_type(const std::string& return_type) + { + default_return_type_ = return_type; + } + + bool verify(const std::string& param_seq, std::size_t& pseq_index) + { + if (function_definition_list_.empty()) + return true; + + std::vector > error_list; + + for (std::size_t i = 0; i < function_definition_list_.size(); ++i) + { + details::char_t diff_value = 0; + std::size_t diff_index = 0; + + const bool result = details::sequence_match(function_definition_list_[i].param_seq, + param_seq, + diff_index, diff_value); + + if (result) + { + pseq_index = i; + return true; + } + else + error_list.push_back(std::make_pair(diff_index, diff_value)); + } + + if (1 == error_list.size()) + { + parser_. + set_error( + make_error(parser_error::e_syntax, + parser_.current_token(), + "ERR115 - Failed parameter type check for function '" + function_name_ + "', " + "Expected '" + function_definition_list_[0].param_seq + + "' call set: '" + param_seq + "'", + exprtk_error_location)); + } + else + { + // find first with largest diff_index; + std::size_t max_diff_index = 0; + + for (std::size_t i = 1; i < error_list.size(); ++i) + { + if (error_list[i].first > error_list[max_diff_index].first) + { + max_diff_index = i; + } + } + + parser_. + set_error( + make_error(parser_error::e_syntax, + parser_.current_token(), + "ERR116 - Failed parameter type check for function '" + function_name_ + "', " + "Best match: '" + function_definition_list_[max_diff_index].param_seq + + "' call set: '" + param_seq + "'", + exprtk_error_location)); + } + + return false; + } + + std::size_t paramseq_count() const + { + return function_definition_list_.size(); + } + + std::string paramseq(const std::size_t& index) const + { + return function_definition_list_[index].param_seq; + } + + return_type_t return_type(const std::size_t& index) const + { + return function_definition_list_[index].return_type; + } + + bool invalid() const + { + return !invalid_state_; + } + + bool allow_zero_parameters() const + { + + for (std::size_t i = 0; i < function_definition_list_.size(); ++i) + { + if (std::string::npos != function_definition_list_[i].param_seq.find("Z")) + { + return true; + } + } + + return false; + } + + private: + + std::vector split_param_seq(const std::string& param_seq, const details::char_t delimiter = '|') const + { + std::string::const_iterator current_begin = param_seq.begin(); + std::string::const_iterator iter = param_seq.begin(); + + std::vector result; + + while (iter != param_seq.end()) + { + if (*iter == delimiter) + { + result.push_back(std::string(current_begin, iter)); + current_begin = ++iter; + } + else + ++iter; + } + + if (current_begin != iter) + { + result.push_back(std::string(current_begin, iter)); + } + + return result; + } + + inline bool is_valid_token(std::string param_seq, + function_prototype_t& funcproto) const + { + // Determine return type + funcproto.return_type = default_return_type_; + + if (param_seq.size() > 2) + { + if (':' == param_seq[1]) + { + // Note: Only overloaded igeneric functions can have return + // type definitions. + if (type_checker::e_overload != default_return_type_) + return false; + + switch (param_seq[0]) + { + case 'T' : funcproto.return_type = type_checker::e_numeric; + break; + + case 'S' : funcproto.return_type = type_checker::e_string; + break; + + default : return false; + } + + param_seq.erase(0,2); + } + } + + if ( + (std::string::npos != param_seq.find("?*")) || + (std::string::npos != param_seq.find("**")) + ) + { + return false; + } + else if ( + (std::string::npos == param_seq.find_first_not_of("STV*?|")) || + ("Z" == param_seq) + ) + { + funcproto.param_seq = param_seq; + return true; + } + + return false; + } + + void parse_function_prototypes(const std::string& func_prototypes) + { + if (func_prototypes.empty()) + return; + + std::vector param_seq_list = split_param_seq(func_prototypes); + + typedef std::map param_seq_map_t; + param_seq_map_t param_seq_map; + + for (std::size_t i = 0; i < param_seq_list.size(); ++i) + { + function_prototype_t func_proto; + + if (!is_valid_token(param_seq_list[i], func_proto)) + { + invalid_state_ = false; + + parser_. + set_error( + make_error(parser_error::e_syntax, + parser_.current_token(), + "ERR117 - Invalid parameter sequence of '" + param_seq_list[i] + + "' for function: " + function_name_, + exprtk_error_location)); + return; + } + + param_seq_map_t::const_iterator seq_itr = param_seq_map.find(param_seq_list[i]); + + if (param_seq_map.end() != seq_itr) + { + invalid_state_ = false; + + parser_. + set_error( + make_error(parser_error::e_syntax, + parser_.current_token(), + "ERR118 - Function '" + function_name_ + "' has a parameter sequence conflict between " + + "pseq_idx[" + details::to_str(seq_itr->second) + "] and" + + "pseq_idx[" + details::to_str(i) + "] " + + "param seq: " + param_seq_list[i], + exprtk_error_location)); + return; + } + + function_definition_list_.push_back(func_proto); + } + } + + type_checker(const type_checker&); + type_checker& operator=(const type_checker&); + + bool invalid_state_; + parser_t& parser_; + std::string function_name_; + const return_type_t default_return_type_; + function_definition_list_t function_definition_list_; + }; + + inline expression_node_ptr parse_generic_function_call(igeneric_function* function, const std::string& function_name) + { + std::vector arg_list; + + scoped_vec_delete sdd((*this),arg_list); + + next_token(); + + std::string param_type_list; + + type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string); + + if (tc.invalid()) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR119 - Type checker instantiation failure for generic function: " + function_name, + exprtk_error_location)); + + return error_node(); + } + + if (token_is(token_t::e_lbracket)) + { + if (token_is(token_t::e_rbracket)) + { + if ( + !function->allow_zero_parameters() && + !tc .allow_zero_parameters() + ) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR120 - Zero parameter call to generic function: " + + function_name + " not allowed", + exprtk_error_location)); + + return error_node(); + } + } + else + { + for ( ; ; ) + { + expression_node_ptr arg = parse_expression(); + + if (0 == arg) + return error_node(); + + if (is_ivector_node(arg)) + param_type_list += 'V'; + else if (is_generally_string_node(arg)) + param_type_list += 'S'; + else // Everything else is assumed to be a scalar returning expression + param_type_list += 'T'; + + arg_list.push_back(arg); + + if (token_is(token_t::e_rbracket)) + break; + else if (!token_is(token_t::e_comma)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR121 - Expected ',' for call to generic function: " + function_name, + exprtk_error_location)); + + return error_node(); + } + } + } + } + else if ( + !function->parameter_sequence.empty() && + function->allow_zero_parameters () && + !tc .allow_zero_parameters () + ) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR122 - Zero parameter call to generic function: " + + function_name + " not allowed", + exprtk_error_location)); + + return error_node(); + } + + std::size_t param_seq_index = 0; + + if ( + state_.type_check_enabled && + !tc.verify(param_type_list, param_seq_index) + ) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR123 - Invalid input parameter sequence for call to generic function: " + function_name, + exprtk_error_location)); + + return error_node(); + } + + expression_node_ptr result = error_node(); + + if (tc.paramseq_count() <= 1) + result = expression_generator_ + .generic_function_call(function, arg_list); + else + result = expression_generator_ + .generic_function_call(function, arg_list, param_seq_index); + + sdd.delete_ptr = (0 == result); + + return result; + } + + inline bool parse_igeneric_function_params(std::string& param_type_list, + std::vector& arg_list, + const std::string function_name, + igeneric_function* function, + const type_checker& tc) + { + if (token_is(token_t::e_lbracket)) + { + if (token_is(token_t::e_rbracket)) + { + if ( + !function->allow_zero_parameters() && + !tc .allow_zero_parameters() + ) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR124 - Zero parameter call to generic function: " + + function_name + " not allowed", + exprtk_error_location)); + + return false; + } + } + else + { + for ( ; ; ) + { + expression_node_ptr arg = parse_expression(); + + if (0 == arg) + return false; + + if (is_ivector_node(arg)) + param_type_list += 'V'; + else if (is_generally_string_node(arg)) + param_type_list += 'S'; + else // Everything else is a scalar returning expression + param_type_list += 'T'; + + arg_list.push_back(arg); + + if (token_is(token_t::e_rbracket)) + break; + else if (!token_is(token_t::e_comma)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR125 - Expected ',' for call to string function: " + function_name, + exprtk_error_location)); + + return false; + } + } + } + + return true; + } + else + return false; + } + + #ifndef exprtk_disable_string_capabilities + inline expression_node_ptr parse_string_function_call(igeneric_function* function, const std::string& function_name) + { + // Move pass the function name + next_token(); + + std::string param_type_list; + + type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string); + + if ( + (!function->parameter_sequence.empty()) && + (0 == tc.paramseq_count()) + ) + { + return error_node(); + } + + std::vector arg_list; + scoped_vec_delete sdd((*this),arg_list); + + if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc)) + { + return error_node(); + } + + std::size_t param_seq_index = 0; + + if (!tc.verify(param_type_list, param_seq_index)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR126 - Invalid input parameter sequence for call to string function: " + function_name, + exprtk_error_location)); + + return error_node(); + } + + expression_node_ptr result = error_node(); + + if (tc.paramseq_count() <= 1) + result = expression_generator_ + .string_function_call(function, arg_list); + else + result = expression_generator_ + .string_function_call(function, arg_list, param_seq_index); + + sdd.delete_ptr = (0 == result); + + return result; + } + + inline expression_node_ptr parse_overload_function_call(igeneric_function* function, const std::string& function_name) + { + // Move pass the function name + next_token(); + + std::string param_type_list; + + type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_overload); + + if ( + (!function->parameter_sequence.empty()) && + (0 == tc.paramseq_count()) + ) + { + return error_node(); + } + + std::vector arg_list; + scoped_vec_delete sdd((*this),arg_list); + + if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc)) + { + return error_node(); + } + + std::size_t param_seq_index = 0; + + if (!tc.verify(param_type_list, param_seq_index)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR127 - Invalid input parameter sequence for call to overloaded function: " + function_name, + exprtk_error_location)); + + return error_node(); + } + + expression_node_ptr result = error_node(); + + if (type_checker::e_numeric == tc.return_type(param_seq_index)) + { + if (tc.paramseq_count() <= 1) + result = expression_generator_ + .generic_function_call(function, arg_list); + else + result = expression_generator_ + .generic_function_call(function, arg_list, param_seq_index); + } + else if (type_checker::e_string == tc.return_type(param_seq_index)) + { + if (tc.paramseq_count() <= 1) + result = expression_generator_ + .string_function_call(function, arg_list); + else + result = expression_generator_ + .string_function_call(function, arg_list, param_seq_index); + } + else + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR128 - Invalid return type for call to overloaded function: " + function_name, + exprtk_error_location)); + } + + sdd.delete_ptr = (0 == result); + return result; + } + #endif + + template + struct parse_special_function_impl + { + static inline expression_node_ptr process(parser& p,const details::operator_type opt_type, const std::string& sf_name) + { + expression_node_ptr branch[NumberOfParameters]; + expression_node_ptr result = error_node(); + + std::fill_n(branch,NumberOfParameters,reinterpret_cast(0)); + + scoped_delete sd(p,branch); + + p.next_token(); + + if (!p.token_is(token_t::e_lbracket)) + { + p.set_error( + make_error(parser_error::e_syntax, + p.current_token(), + "ERR129 - Expected '(' for special function '" + sf_name + "'", + exprtk_error_location)); + + return error_node(); + } + + for (std::size_t i = 0; i < NumberOfParameters; ++i) + { + branch[i] = p.parse_expression(); + + if (0 == branch[i]) + { + return p.error_node(); + } + else if (i < (NumberOfParameters - 1)) + { + if (!p.token_is(token_t::e_comma)) + { + p.set_error( + make_error(parser_error::e_syntax, + p.current_token(), + "ERR130 - Expected ',' before next parameter of special function '" + sf_name + "'", + exprtk_error_location)); + + return p.error_node(); + } + } + } + + if (!p.token_is(token_t::e_rbracket)) + { + p.set_error( + make_error(parser_error::e_syntax, + p.current_token(), + "ERR131 - Invalid number of parameters for special function '" + sf_name + "'", + exprtk_error_location)); + + return p.error_node(); + } + else + result = p.expression_generator_.special_function(opt_type,branch); + + sd.delete_ptr = (0 == result); + + return result; + } + }; + + inline expression_node_ptr parse_special_function() + { + const std::string sf_name = current_token().value; + + // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3) + if ( + !details::is_digit(sf_name[2]) || + !details::is_digit(sf_name[3]) + ) + { + set_error( + make_error(parser_error::e_token, + current_token(), + "ERR132 - Invalid special function[1]: " + sf_name, + exprtk_error_location)); + + return error_node(); + } + + const int id = (sf_name[2] - '0') * 10 + + (sf_name[3] - '0'); + + if (id >= details::e_sffinal) + { + set_error( + make_error(parser_error::e_token, + current_token(), + "ERR133 - Invalid special function[2]: " + sf_name, + exprtk_error_location)); + + return error_node(); + } + + const int sf_3_to_4 = details::e_sf48; + const details::operator_type opt_type = details::operator_type(id + 1000); + const std::size_t NumberOfParameters = (id < (sf_3_to_4 - 1000)) ? 3U : 4U; + + switch (NumberOfParameters) + { + case 3 : return parse_special_function_impl::process((*this), opt_type, sf_name); + case 4 : return parse_special_function_impl::process((*this), opt_type, sf_name); + default : return error_node(); + } + } + + inline expression_node_ptr parse_null_statement() + { + next_token(); + return node_allocator_.allocate >(); + } + + #ifndef exprtk_disable_break_continue + inline expression_node_ptr parse_break_statement() + { + if (state_.parsing_break_stmt) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR134 - Break call within a break call is not allowed", + exprtk_error_location)); + + return error_node(); + } + + scoped_bool_negator sbn(state_.parsing_break_stmt); + + if (!brkcnt_list_.empty()) + { + next_token(); + + brkcnt_list_.front() = true; + + expression_node_ptr return_expr = error_node(); + + if (token_is(token_t::e_lsqrbracket)) + { + if (0 == (return_expr = parse_expression())) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR135 - Failed to parse return expression for 'break' statement", + exprtk_error_location)); + + return error_node(); + } + else if (!token_is(token_t::e_rsqrbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR136 - Expected ']' at the completion of break's return expression", + exprtk_error_location)); + + free_node(node_allocator_,return_expr); + + return error_node(); + } + } + + state_.activate_side_effect("parse_break_statement()"); + + return node_allocator_.allocate >(return_expr); + } + else + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR137 - Invalid use of 'break', allowed only in the scope of a loop", + exprtk_error_location)); + } + + return error_node(); + } + + inline expression_node_ptr parse_continue_statement() + { + if (!brkcnt_list_.empty()) + { + next_token(); + + brkcnt_list_.front() = true; + state_.activate_side_effect("parse_continue_statement()"); + + return node_allocator_.allocate >(); + } + else + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR138 - Invalid use of 'continue', allowed only in the scope of a loop", + exprtk_error_location)); + + return error_node(); + } + } + #endif + + inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name) + { + expression_node_ptr size_expr = error_node(); + + if (!token_is(token_t::e_lsqrbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR139 - Expected '[' as part of vector size definition", + exprtk_error_location)); + + return error_node(); + } + else if (0 == (size_expr = parse_expression())) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR140 - Failed to determine size of vector '" + vec_name + "'", + exprtk_error_location)); + + return error_node(); + } + else if (!is_constant_node(size_expr)) + { + free_node(node_allocator_,size_expr); + + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR141 - Expected a literal number as size of vector '" + vec_name + "'", + exprtk_error_location)); + + return error_node(); + } + + T vector_size = size_expr->value(); + + free_node(node_allocator_,size_expr); + + const T max_vector_size = T(2000000000.0); + + if ( + (vector_size <= T(0)) || + std::not_equal_to() + (T(0),vector_size - details::numeric::trunc(vector_size)) || + (vector_size > max_vector_size) + ) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR142 - Invalid vector size. Must be an integer in the range [0,2e9], size: " + + details::to_str(details::numeric::to_int32(vector_size)), + exprtk_error_location)); + + return error_node(); + } + + std::vector vec_initilizer_list; + + scoped_vec_delete svd((*this),vec_initilizer_list); + + bool single_value_initialiser = false; + bool vec_to_vec_initialiser = false; + bool null_initialisation = false; + + if (!token_is(token_t::e_rsqrbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR143 - Expected ']' as part of vector size definition", + exprtk_error_location)); + + return error_node(); + } + else if (!token_is(token_t::e_eof)) + { + if (!token_is(token_t::e_assign)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR144 - Expected ':=' as part of vector definition", + exprtk_error_location)); + + return error_node(); + } + else if (token_is(token_t::e_lsqrbracket)) + { + expression_node_ptr initialiser = parse_expression(); + + if (0 == initialiser) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR145 - Failed to parse single vector initialiser", + exprtk_error_location)); + + return error_node(); + } + + vec_initilizer_list.push_back(initialiser); + + if (!token_is(token_t::e_rsqrbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR146 - Expected ']' to close single value vector initialiser", + exprtk_error_location)); + + return error_node(); + } + + single_value_initialiser = true; + } + else if (!token_is(token_t::e_lcrlbracket)) + { + expression_node_ptr initialiser = error_node(); + + // Is this a vector to vector assignment and initialisation? + if (token_t::e_symbol == current_token().type) + { + // Is it a locally defined vector? + scope_element& se = sem_.get_active_element(current_token().value); + + if (scope_element::e_vector == se.type) + { + if (0 != (initialiser = parse_expression())) + vec_initilizer_list.push_back(initialiser); + else + return error_node(); + } + // Are we dealing with a user defined vector? + else if (symtab_store_.is_vector(current_token().value)) + { + lodge_symbol(current_token().value, e_st_vector); + + if (0 != (initialiser = parse_expression())) + vec_initilizer_list.push_back(initialiser); + else + return error_node(); + } + // Are we dealing with a null initialisation vector definition? + else if (token_is(token_t::e_symbol,"null")) + null_initialisation = true; + } + + if (!null_initialisation) + { + if (0 == initialiser) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR147 - Expected '{' as part of vector initialiser list", + exprtk_error_location)); + + return error_node(); + } + else + vec_to_vec_initialiser = true; + } + } + else if (!token_is(token_t::e_rcrlbracket)) + { + for ( ; ; ) + { + expression_node_ptr initialiser = parse_expression(); + + if (0 == initialiser) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR148 - Expected '{' as part of vector initialiser list", + exprtk_error_location)); + + return error_node(); + } + else + vec_initilizer_list.push_back(initialiser); + + if (token_is(token_t::e_rcrlbracket)) + break; + + const bool is_next_close = peek_token_is(token_t::e_rcrlbracket); + + if (!token_is(token_t::e_comma) && is_next_close) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR149 - Expected ',' between vector initialisers", + exprtk_error_location)); + + return error_node(); + } + + if (token_is(token_t::e_rcrlbracket)) + break; + } + } + + if ( + !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) && + !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && + !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold) + ) + { + if (!token_is(token_t::e_eof)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR150 - Expected ';' at end of vector definition", + exprtk_error_location)); + + return error_node(); + } + } + + if (vec_initilizer_list.size() > vector_size) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR151 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'", + exprtk_error_location)); + + return error_node(); + } + } + + typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0); + + const std::size_t vec_size = static_cast(details::numeric::to_int32(vector_size)); + + scope_element& se = sem_.get_element(vec_name); + + if (se.name == vec_name) + { + if (se.active) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR152 - Illegal redefinition of local vector: '" + vec_name + "'", + exprtk_error_location)); + + return error_node(); + } + else if ( + (se.size == vec_size) && + (scope_element::e_vector == se.type) + ) + { + vec_holder = se.vec_node; + se.active = true; + se.depth = state_.scope_depth; + se.ref_count++; + } + } + + if (0 == vec_holder) + { + scope_element nse; + nse.name = vec_name; + nse.active = true; + nse.ref_count = 1; + nse.type = scope_element::e_vector; + nse.depth = state_.scope_depth; + nse.size = vec_size; + nse.data = new T[vec_size]; + nse.vec_node = new typename scope_element::vector_holder_t((T*)(nse.data),nse.size); + + if (!sem_.add_element(nse)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR153 - Failed to add new local vector '" + vec_name + "' to SEM", + exprtk_error_location)); + + sem_.free_element(nse); + + return error_node(); + } + + vec_holder = nse.vec_node; + + exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n", + nse.name.c_str(), + static_cast(nse.size))); + } + + state_.activate_side_effect("parse_define_vector_statement()"); + + lodge_symbol(vec_name, e_st_local_vector); + + expression_node_ptr result = error_node(); + + if (null_initialisation) + result = expression_generator_(T(0.0)); + else if (vec_to_vec_initialiser) + { + expression_node_ptr vec_node = node_allocator_.allocate(vec_holder); + + result = expression_generator_( + details::e_assign, + vec_node, + vec_initilizer_list[0]); + } + else + result = node_allocator_ + .allocate >( + (*vec_holder)[0], + vec_size, + vec_initilizer_list, + single_value_initialiser); + + svd.delete_ptr = (0 == result); + + return result; + } + + #ifndef exprtk_disable_string_capabilities + inline expression_node_ptr parse_define_string_statement(const std::string& str_name, expression_node_ptr initialisation_expression) + { + stringvar_node_t* str_node = reinterpret_cast(0); + + scope_element& se = sem_.get_element(str_name); + + if (se.name == str_name) + { + if (se.active) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR154 - Illegal redefinition of local variable: '" + str_name + "'", + exprtk_error_location)); + + free_node(node_allocator_,initialisation_expression); + + return error_node(); + } + else if (scope_element::e_string == se.type) + { + str_node = se.str_node; + se.active = true; + se.depth = state_.scope_depth; + se.ref_count++; + } + } + + if (0 == str_node) + { + scope_element nse; + nse.name = str_name; + nse.active = true; + nse.ref_count = 1; + nse.type = scope_element::e_string; + nse.depth = state_.scope_depth; + nse.data = new std::string; + nse.str_node = new stringvar_node_t(*(std::string*)(nse.data)); + + if (!sem_.add_element(nse)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR155 - Failed to add new local string variable '" + str_name + "' to SEM", + exprtk_error_location)); + + free_node(node_allocator_,initialisation_expression); + + sem_.free_element(nse); + + return error_node(); + } + + str_node = nse.str_node; + + exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n",nse.name.c_str())); + } + + lodge_symbol(str_name, e_st_local_string); + + state_.activate_side_effect("parse_define_string_statement()"); + + expression_node_ptr branch[2] = {0}; + + branch[0] = str_node; + branch[1] = initialisation_expression; + + return expression_generator_(details::e_assign,branch); + } + #else + inline expression_node_ptr parse_define_string_statement(const std::string&, expression_node_ptr) + { + return error_node(); + } + #endif + + inline bool local_variable_is_shadowed(const std::string& symbol) + { + const scope_element& se = sem_.get_element(symbol); + return (se.name == symbol) && se.active; + } + + inline expression_node_ptr parse_define_var_statement() + { + if (settings_.vardef_disabled()) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR156 - Illegal variable definition", + exprtk_error_location)); + + return error_node(); + } + else if (!details::imatch(current_token().value,"var")) + { + return error_node(); + } + else + next_token(); + + const std::string var_name = current_token().value; + + expression_node_ptr initialisation_expression = error_node(); + + if (!token_is(token_t::e_symbol)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR157 - Expected a symbol for variable definition", + exprtk_error_location)); + + return error_node(); + } + else if (details::is_reserved_symbol(var_name)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR158 - Illegal redefinition of reserved keyword: '" + var_name + "'", + exprtk_error_location)); + + return error_node(); + } + else if (symtab_store_.symbol_exists(var_name)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR159 - Illegal redefinition of variable '" + var_name + "'", + exprtk_error_location)); + + return error_node(); + } + else if (local_variable_is_shadowed(var_name)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR160 - Illegal redefinition of local variable: '" + var_name + "'", + exprtk_error_location)); + + return error_node(); + } + else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)) + { + return parse_define_vector_statement(var_name); + } + else if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) + { + return parse_uninitialised_var_statement(var_name); + } + else if (token_is(token_t::e_assign)) + { + if (0 == (initialisation_expression = parse_expression())) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR161 - Failed to parse initialisation expression", + exprtk_error_location)); + + return error_node(); + } + } + + if ( + !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) && + !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && + !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold) + ) + { + if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR162 - Expected ';' after variable definition", + exprtk_error_location)); + + free_node(node_allocator_,initialisation_expression); + + return error_node(); + } + } + + if ( + (0 != initialisation_expression) && + details::is_generally_string_node(initialisation_expression) + ) + { + return parse_define_string_statement(var_name,initialisation_expression); + } + + expression_node_ptr var_node = reinterpret_cast(0); + + scope_element& se = sem_.get_element(var_name); + + if (se.name == var_name) + { + if (se.active) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR163 - Illegal redefinition of local variable: '" + var_name + "'", + exprtk_error_location)); + + free_node(node_allocator_, initialisation_expression); + + return error_node(); + } + else if (scope_element::e_variable == se.type) + { + var_node = se.var_node; + se.active = true; + se.depth = state_.scope_depth; + se.ref_count++; + } + } + + if (0 == var_node) + { + scope_element nse; + nse.name = var_name; + nse.active = true; + nse.ref_count = 1; + nse.type = scope_element::e_variable; + nse.depth = state_.scope_depth; + nse.data = new T(T(0)); + nse.var_node = node_allocator_.allocate(*(T*)(nse.data)); + + if (!sem_.add_element(nse)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR164 - Failed to add new local variable '" + var_name + "' to SEM", + exprtk_error_location)); + + free_node(node_allocator_, initialisation_expression); + + sem_.free_element(nse); + + return error_node(); + } + + var_node = nse.var_node; + + exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n",nse.name.c_str())); + } + + state_.activate_side_effect("parse_define_var_statement()"); + + lodge_symbol(var_name, e_st_local_variable); + + expression_node_ptr branch[2] = {0}; + + branch[0] = var_node; + branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0)); + + return expression_generator_(details::e_assign,branch); + } + + inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name) + { + if ( + !token_is(token_t::e_lcrlbracket) || + !token_is(token_t::e_rcrlbracket) + ) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR165 - Expected a '{}' for uninitialised var definition", + exprtk_error_location)); + + return error_node(); + } + else if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR166 - Expected ';' after uninitialised variable definition", + exprtk_error_location)); + + return error_node(); + } + + expression_node_ptr var_node = reinterpret_cast(0); + + scope_element& se = sem_.get_element(var_name); + + if (se.name == var_name) + { + if (se.active) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR167 - Illegal redefinition of local variable: '" + var_name + "'", + exprtk_error_location)); + + return error_node(); + } + else if (scope_element::e_variable == se.type) + { + var_node = se.var_node; + se.active = true; + se.ref_count++; + } + } + + if (0 == var_node) + { + scope_element nse; + nse.name = var_name; + nse.active = true; + nse.ref_count = 1; + nse.type = scope_element::e_variable; + nse.depth = state_.scope_depth; + nse.ip_index = sem_.next_ip_index(); + nse.data = new T(T(0)); + nse.var_node = node_allocator_.allocate(*(T*)(nse.data)); + + if (!sem_.add_element(nse)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR168 - Failed to add new local variable '" + var_name + "' to SEM", + exprtk_error_location)); + + sem_.free_element(nse); + + return error_node(); + } + + exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n", + nse.name.c_str())); + } + + lodge_symbol(var_name, e_st_local_variable); + + state_.activate_side_effect("parse_uninitialised_var_statement()"); + + return expression_generator_(T(0)); + } + + inline expression_node_ptr parse_swap_statement() + { + if (!details::imatch(current_token().value,"swap")) + { + return error_node(); + } + else + next_token(); + + if (!token_is(token_t::e_lbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR169 - Expected '(' at start of swap statement", + exprtk_error_location)); + + return error_node(); + } + + expression_node_ptr variable0 = error_node(); + expression_node_ptr variable1 = error_node(); + + bool variable0_generated = false; + bool variable1_generated = false; + + const std::string var0_name = current_token().value; + + if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR170 - Expected a symbol for variable or vector element definition", + exprtk_error_location)); + + return error_node(); + } + else if (peek_token_is(token_t::e_lsqrbracket)) + { + if (0 == (variable0 = parse_vector())) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR171 - First parameter to swap is an invalid vector element: '" + var0_name + "'", + exprtk_error_location)); + + return error_node(); + } + + variable0_generated = true; + } + else + { + if (symtab_store_.is_variable(var0_name)) + { + variable0 = symtab_store_.get_variable(var0_name); + } + + scope_element& se = sem_.get_element(var0_name); + + if ( + (se.active) && + (se.name == var0_name) && + (scope_element::e_variable == se.type) + ) + { + variable0 = se.var_node; + } + + lodge_symbol(var0_name, e_st_variable); + + if (0 == variable0) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR172 - First parameter to swap is an invalid variable: '" + var0_name + "'", + exprtk_error_location)); + + return error_node(); + } + else + next_token(); + } + + if (!token_is(token_t::e_comma)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR173 - Expected ',' between parameters to swap", + exprtk_error_location)); + + if (variable0_generated) + { + free_node(node_allocator_,variable0); + } + + return error_node(); + } + + const std::string var1_name = current_token().value; + + if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR174 - Expected a symbol for variable or vector element definition", + exprtk_error_location)); + + if (variable0_generated) + { + free_node(node_allocator_,variable0); + } + + return error_node(); + } + else if (peek_token_is(token_t::e_lsqrbracket)) + { + if (0 == (variable1 = parse_vector())) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR175 - Second parameter to swap is an invalid vector element: '" + var1_name + "'", + exprtk_error_location)); + + if (variable0_generated) + { + free_node(node_allocator_,variable0); + } + + return error_node(); + } + + variable1_generated = true; + } + else + { + if (symtab_store_.is_variable(var1_name)) + { + variable1 = symtab_store_.get_variable(var1_name); + } + + scope_element& se = sem_.get_element(var1_name); + + if ( + (se.active) && + (se.name == var1_name) && + (scope_element::e_variable == se.type) + ) + { + variable1 = se.var_node; + } + + lodge_symbol(var1_name, e_st_variable); + + if (0 == variable1) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR176 - Second parameter to swap is an invalid variable: '" + var1_name + "'", + exprtk_error_location)); + + if (variable0_generated) + { + free_node(node_allocator_,variable0); + } + + return error_node(); + } + else + next_token(); + } + + if (!token_is(token_t::e_rbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR177 - Expected ')' at end of swap statement", + exprtk_error_location)); + + if (variable0_generated) + { + free_node(node_allocator_,variable0); + } + + if (variable1_generated) + { + free_node(node_allocator_,variable1); + } + + return error_node(); + } + + typedef details::variable_node* variable_node_ptr; + + variable_node_ptr v0 = variable_node_ptr(0); + variable_node_ptr v1 = variable_node_ptr(0); + + expression_node_ptr result = error_node(); + + if ( + (0 != (v0 = dynamic_cast(variable0))) && + (0 != (v1 = dynamic_cast(variable1))) + ) + { + result = node_allocator_.allocate >(v0, v1); + + if (variable0_generated) + { + free_node(node_allocator_,variable0); + } + + if (variable1_generated) + { + free_node(node_allocator_,variable1); + } + } + else + result = node_allocator_.allocate > + (variable0, variable1); + + state_.activate_side_effect("parse_swap_statement()"); + + return result; + } + + #ifndef exprtk_disable_return_statement + inline expression_node_ptr parse_return_statement() + { + if (state_.parsing_return_stmt) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR178 - Return call within a return call is not allowed", + exprtk_error_location)); + + return error_node(); + } + + scoped_bool_negator sbn(state_.parsing_return_stmt); + + std::vector arg_list; + + scoped_vec_delete sdd((*this),arg_list); + + if (!details::imatch(current_token().value,"return")) + { + return error_node(); + } + else + next_token(); + + if (!token_is(token_t::e_lsqrbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR179 - Expected '[' at start of return statement", + exprtk_error_location)); + + return error_node(); + } + else if (!token_is(token_t::e_rsqrbracket)) + { + for ( ; ; ) + { + expression_node_ptr arg = parse_expression(); + + if (0 == arg) + return error_node(); + + arg_list.push_back(arg); + + if (token_is(token_t::e_rsqrbracket)) + break; + else if (!token_is(token_t::e_comma)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR180 - Expected ',' between values during call to return", + exprtk_error_location)); + + return error_node(); + } + } + } + else if (settings_.zero_return_disabled()) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR181 - Zero parameter return statement not allowed", + exprtk_error_location)); + + return error_node(); + } + + const lexer::token prev_token = current_token(); + + if (token_is(token_t::e_rsqrbracket)) + { + if (!arg_list.empty()) + { + set_error( + make_error(parser_error::e_syntax, + prev_token, + "ERR182 - Invalid ']' found during return call", + exprtk_error_location)); + + return error_node(); + } + } + + std::string ret_param_type_list; + + for (std::size_t i = 0; i < arg_list.size(); ++i) + { + if (0 == arg_list[i]) + return error_node(); + else if (is_ivector_node(arg_list[i])) + ret_param_type_list += 'V'; + else if (is_generally_string_node(arg_list[i])) + ret_param_type_list += 'S'; + else + ret_param_type_list += 'T'; + } + + dec_.retparam_list_.push_back(ret_param_type_list); + + expression_node_ptr result = expression_generator_.return_call(arg_list); + + sdd.delete_ptr = (0 == result); + + state_.return_stmt_present = true; + + state_.activate_side_effect("parse_return_statement()"); + + return result; + } + #else + inline expression_node_ptr parse_return_statement() + { + return error_node(); + } + #endif + + inline bool post_variable_process(const std::string& symbol) + { + if ( + peek_token_is(token_t::e_lbracket ) || + peek_token_is(token_t::e_lcrlbracket) || + peek_token_is(token_t::e_lsqrbracket) + ) + { + if (!settings_.commutative_check_enabled()) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR183 - Invalid sequence of variable '"+ symbol + "' and bracket", + exprtk_error_location)); + + return false; + } + + lexer().insert_front(token_t::e_mul); + } + + return true; + } + + inline bool post_bracket_process(const typename token_t::token_type& token, expression_node_ptr& branch) + { + bool implied_mul = false; + + if (is_generally_string_node(branch)) + return true; + + const lexer::parser_helper::token_advance_mode hold = prsrhlpr_t::e_hold; + + switch (token) + { + case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket ,hold) || + token_is(token_t::e_lcrlbracket,hold) || + token_is(token_t::e_lsqrbracket,hold) ; + break; + + case token_t::e_lbracket : implied_mul = token_is(token_t::e_lbracket ,hold) || + token_is(token_t::e_lcrlbracket,hold) || + token_is(token_t::e_lsqrbracket,hold) ; + break; + + case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket ,hold) || + token_is(token_t::e_lcrlbracket,hold) || + token_is(token_t::e_lsqrbracket,hold) ; + break; + + default : return true; + } + + if (implied_mul) + { + if (!settings_.commutative_check_enabled()) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR184 - Invalid sequence of brackets", + exprtk_error_location)); + + return false; + } + else if (token_t::e_eof != current_token().type) + { + lexer().insert_front(current_token().type); + lexer().insert_front(token_t::e_mul); + next_token(); + } + } + + return true; + } + + inline expression_node_ptr parse_symtab_symbol() + { + const std::string symbol = current_token().value; + + // Are we dealing with a variable or a special constant? + expression_node_ptr variable = symtab_store_.get_variable(symbol); + + if (variable) + { + if (symtab_store_.is_constant_node(symbol)) + { + variable = expression_generator_(variable->value()); + } + + if (!post_variable_process(symbol)) + return error_node(); + + lodge_symbol(symbol, e_st_variable); + next_token(); + + return variable; + } + + // Are we dealing with a locally defined variable, vector or string? + if (!sem_.empty()) + { + scope_element& se = sem_.get_active_element(symbol); + + if (se.active && details::imatch(se.name, symbol)) + { + if (scope_element::e_variable == se.type) + { + se.active = true; + lodge_symbol(symbol, e_st_local_variable); + + if (!post_variable_process(symbol)) + return error_node(); + + next_token(); + + return se.var_node; + } + else if (scope_element::e_vector == se.type) + { + return parse_vector(); + } + #ifndef exprtk_disable_string_capabilities + else if (scope_element::e_string == se.type) + { + return parse_string(); + } + #endif + } + } + + #ifndef exprtk_disable_string_capabilities + // Are we dealing with a string variable? + if (symtab_store_.is_stringvar(symbol)) + { + return parse_string(); + } + #endif + + { + // Are we dealing with a function? + ifunction* function = symtab_store_.get_function(symbol); + + if (function) + { + lodge_symbol(symbol, e_st_function); + + expression_node_ptr func_node = + parse_function_invocation(function,symbol); + + if (func_node) + return func_node; + else + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR185 - Failed to generate node for function: '" + symbol + "'", + exprtk_error_location)); + + return error_node(); + } + } + } + + { + // Are we dealing with a vararg function? + ivararg_function* vararg_function = symtab_store_.get_vararg_function(symbol); + + if (vararg_function) + { + lodge_symbol(symbol, e_st_function); + + expression_node_ptr vararg_func_node = + parse_vararg_function_call(vararg_function, symbol); + + if (vararg_func_node) + return vararg_func_node; + else + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR186 - Failed to generate node for vararg function: '" + symbol + "'", + exprtk_error_location)); + + return error_node(); + } + } + } + + { + // Are we dealing with a vararg generic function? + igeneric_function* generic_function = symtab_store_.get_generic_function(symbol); + + if (generic_function) + { + lodge_symbol(symbol, e_st_function); + + expression_node_ptr genericfunc_node = + parse_generic_function_call(generic_function, symbol); + + if (genericfunc_node) + return genericfunc_node; + else + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR187 - Failed to generate node for generic function: '" + symbol + "'", + exprtk_error_location)); + + return error_node(); + } + } + } + + #ifndef exprtk_disable_string_capabilities + { + // Are we dealing with a vararg string returning function? + igeneric_function* string_function = symtab_store_.get_string_function(symbol); + + if (string_function) + { + lodge_symbol(symbol, e_st_function); + + expression_node_ptr stringfunc_node = + parse_string_function_call(string_function, symbol); + + if (stringfunc_node) + return stringfunc_node; + else + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR188 - Failed to generate node for string function: '" + symbol + "'", + exprtk_error_location)); + + return error_node(); + } + } + } + + { + // Are we dealing with a vararg overloaded scalar/string returning function? + igeneric_function* overload_function = symtab_store_.get_overload_function(symbol); + + if (overload_function) + { + lodge_symbol(symbol, e_st_function); + + expression_node_ptr overloadfunc_node = + parse_overload_function_call(overload_function, symbol); + + if (overloadfunc_node) + return overloadfunc_node; + else + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR189 - Failed to generate node for overload function: '" + symbol + "'", + exprtk_error_location)); + + return error_node(); + } + } + } + #endif + + // Are we dealing with a vector? + if (symtab_store_.is_vector(symbol)) + { + lodge_symbol(symbol, e_st_vector); + return parse_vector(); + } + + if (details::is_reserved_symbol(symbol)) + { + if ( + settings_.function_enabled(symbol) || + !details::is_base_function(symbol) + ) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR190 - Invalid use of reserved symbol '" + symbol + "'", + exprtk_error_location)); + + return error_node(); + } + } + + // Should we handle unknown symbols? + if (resolve_unknown_symbol_ && unknown_symbol_resolver_) + { + if (!(settings_.rsrvd_sym_usr_disabled() && details::is_reserved_symbol(symbol))) + { + symbol_table_t& symtab = symtab_store_.get_symbol_table(); + + std::string error_message; + + if (unknown_symbol_resolver::e_usrmode_default == unknown_symbol_resolver_->mode) + { + T default_value = T(0); + + typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type = unknown_symbol_resolver::e_usr_unknown_type; + + if (unknown_symbol_resolver_->process(symbol, usr_symbol_type, default_value, error_message)) + { + bool create_result = false; + + switch (usr_symbol_type) + { + case unknown_symbol_resolver::e_usr_variable_type : create_result = symtab.create_variable(symbol, default_value); + break; + + case unknown_symbol_resolver::e_usr_constant_type : create_result = symtab.add_constant(symbol, default_value); + break; + + default : create_result = false; + } + + if (create_result) + { + expression_node_ptr var = symtab_store_.get_variable(symbol); + + if (var) + { + if (symtab_store_.is_constant_node(symbol)) + { + var = expression_generator_(var->value()); + } + + lodge_symbol(symbol, e_st_variable); + + if (!post_variable_process(symbol)) + return error_node(); + + next_token(); + + return var; + } + } + } + + set_error( + make_error(parser_error::e_symtab, + current_token(), + "ERR191 - Failed to create variable: '" + symbol + "'" + + (error_message.empty() ? "" : " - " + error_message), + exprtk_error_location)); + + } + else if (unknown_symbol_resolver::e_usrmode_extended == unknown_symbol_resolver_->mode) + { + if (unknown_symbol_resolver_->process(symbol, symtab, error_message)) + { + expression_node_ptr result = parse_symtab_symbol(); + + if (result) + { + return result; + } + } + + set_error( + make_error(parser_error::e_symtab, + current_token(), + "ERR192 - Failed to resolve symbol: '" + symbol + "'" + + (error_message.empty() ? "" : " - " + error_message), + exprtk_error_location)); + } + + return error_node(); + } + } + + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR193 - Undefined symbol: '" + symbol + "'", + exprtk_error_location)); + + return error_node(); + } + + inline expression_node_ptr parse_symbol() + { + static const std::string symbol_if = "if" ; + static const std::string symbol_while = "while" ; + static const std::string symbol_repeat = "repeat" ; + static const std::string symbol_for = "for" ; + static const std::string symbol_switch = "switch" ; + static const std::string symbol_null = "null" ; + static const std::string symbol_break = "break" ; + static const std::string symbol_continue = "continue"; + static const std::string symbol_var = "var" ; + static const std::string symbol_swap = "swap" ; + static const std::string symbol_return = "return" ; + + if (valid_vararg_operation(current_token().value)) + { + return parse_vararg_function(); + } + else if (valid_base_operation(current_token().value)) + { + return parse_base_operation(); + } + else if ( + details::imatch(current_token().value, symbol_if) && + settings_.control_struct_enabled(current_token().value) + ) + { + return parse_conditional_statement(); + } + else if ( + details::imatch(current_token().value, symbol_while) && + settings_.control_struct_enabled(current_token().value) + ) + { + return parse_while_loop(); + } + else if ( + details::imatch(current_token().value, symbol_repeat) && + settings_.control_struct_enabled(current_token().value) + ) + { + return parse_repeat_until_loop(); + } + else if ( + details::imatch(current_token().value, symbol_for) && + settings_.control_struct_enabled(current_token().value) + ) + { + return parse_for_loop(); + } + else if ( + details::imatch(current_token().value, symbol_switch) && + settings_.control_struct_enabled(current_token().value) + ) + { + return parse_switch_statement(); + } + else if (details::is_valid_sf_symbol(current_token().value)) + { + return parse_special_function(); + } + else if (details::imatch(current_token().value, symbol_null)) + { + return parse_null_statement(); + } + #ifndef exprtk_disable_break_continue + else if (details::imatch(current_token().value, symbol_break)) + { + return parse_break_statement(); + } + else if (details::imatch(current_token().value, symbol_continue)) + { + return parse_continue_statement(); + } + #endif + else if (details::imatch(current_token().value, symbol_var)) + { + return parse_define_var_statement(); + } + else if (details::imatch(current_token().value, symbol_swap)) + { + return parse_swap_statement(); + } + #ifndef exprtk_disable_return_statement + else if ( + details::imatch(current_token().value, symbol_return) && + settings_.control_struct_enabled(current_token().value) + ) + { + return parse_return_statement(); + } + #endif + else if (symtab_store_.valid() || !sem_.empty()) + { + return parse_symtab_symbol(); + } + else + { + set_error( + make_error(parser_error::e_symtab, + current_token(), + "ERR194 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token().value, + exprtk_error_location)); + + return error_node(); + } + } + + inline expression_node_ptr parse_branch(precedence_level precedence = e_level00) + { + expression_node_ptr branch = error_node(); + + if (token_t::e_number == current_token().type) + { + T numeric_value = T(0); + + if (details::string_to_real(current_token().value, numeric_value)) + { + expression_node_ptr literal_exp = expression_generator_(numeric_value); + + if (0 == literal_exp) + { + set_error( + make_error(parser_error::e_numeric, + current_token(), + "ERR195 - Failed generate node for scalar: '" + current_token().value + "'", + exprtk_error_location)); + + return error_node(); + } + + next_token(); + branch = literal_exp; + } + else + { + set_error( + make_error(parser_error::e_numeric, + current_token(), + "ERR196 - Failed to convert '" + current_token().value + "' to a number", + exprtk_error_location)); + + return error_node(); + } + } + else if (token_t::e_symbol == current_token().type) + { + branch = parse_symbol(); + } + #ifndef exprtk_disable_string_capabilities + else if (token_t::e_string == current_token().type) + { + branch = parse_const_string(); + } + #endif + else if (token_t::e_lbracket == current_token().type) + { + next_token(); + + if (0 == (branch = parse_expression())) + return error_node(); + else if (!token_is(token_t::e_rbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR197 - Expected ')' instead of: '" + current_token().value + "'", + exprtk_error_location)); + + free_node(node_allocator_,branch); + + return error_node(); + } + else if (!post_bracket_process(token_t::e_lbracket,branch)) + { + free_node(node_allocator_,branch); + + return error_node(); + } + } + else if (token_t::e_lsqrbracket == current_token().type) + { + next_token(); + + if (0 == (branch = parse_expression())) + return error_node(); + else if (!token_is(token_t::e_rsqrbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR198 - Expected ']' instead of: '" + current_token().value + "'", + exprtk_error_location)); + + free_node(node_allocator_,branch); + + return error_node(); + } + else if (!post_bracket_process(token_t::e_lsqrbracket,branch)) + { + free_node(node_allocator_,branch); + + return error_node(); + } + } + else if (token_t::e_lcrlbracket == current_token().type) + { + next_token(); + + if (0 == (branch = parse_expression())) + return error_node(); + else if (!token_is(token_t::e_rcrlbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR199 - Expected '}' instead of: '" + current_token().value + "'", + exprtk_error_location)); + + free_node(node_allocator_,branch); + + return error_node(); + } + else if (!post_bracket_process(token_t::e_lcrlbracket,branch)) + { + free_node(node_allocator_,branch); + + return error_node(); + } + } + else if (token_t::e_sub == current_token().type) + { + next_token(); + branch = parse_expression(e_level11); + + if ( + branch && + !( + details::is_neg_unary_node (branch) && + simplify_unary_negation_branch(branch) + ) + ) + { + branch = expression_generator_(details::e_neg,branch); + } + } + else if (token_t::e_add == current_token().type) + { + next_token(); + branch = parse_expression(e_level13); + } + else if (token_t::e_eof == current_token().type) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR200 - Premature end of expression[1]", + exprtk_error_location)); + + return error_node(); + } + else + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR201 - Premature end of expression[2]", + exprtk_error_location)); + + return error_node(); + } + + if ( + branch && + (e_level00 == precedence) && + token_is(token_t::e_ternary,prsrhlpr_t::e_hold) + ) + { + branch = parse_ternary_conditional_statement(branch); + } + + parse_pending_string_rangesize(branch); + + return branch; + } + + template + class expression_generator + { + public: + + typedef details::expression_node* expression_node_ptr; + typedef expression_node_ptr (*synthesize_functor_t)(expression_generator&, const details::operator_type& operation, expression_node_ptr (&branch)[2]); + typedef std::map synthesize_map_t; + typedef typename exprtk::parser parser_t; + typedef const Type& vtype; + typedef const Type ctype; + + inline void init_synthesize_map() + { + #ifndef exprtk_disable_enhanced_features + synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process; + synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process; + synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process; + + #define register_synthezier(S) \ + synthesize_map_[S ::node_type::id()] = S ::process; \ + + register_synthezier(synthesize_vovov_expression0) + register_synthezier(synthesize_vovov_expression1) + register_synthezier(synthesize_vovoc_expression0) + register_synthezier(synthesize_vovoc_expression1) + register_synthezier(synthesize_vocov_expression0) + register_synthezier(synthesize_vocov_expression1) + register_synthezier(synthesize_covov_expression0) + register_synthezier(synthesize_covov_expression1) + register_synthezier(synthesize_covoc_expression0) + register_synthezier(synthesize_covoc_expression1) + register_synthezier(synthesize_cocov_expression1) + register_synthezier(synthesize_vococ_expression0) + + register_synthezier(synthesize_vovovov_expression0) + register_synthezier(synthesize_vovovoc_expression0) + register_synthezier(synthesize_vovocov_expression0) + register_synthezier(synthesize_vocovov_expression0) + register_synthezier(synthesize_covovov_expression0) + register_synthezier(synthesize_covocov_expression0) + register_synthezier(synthesize_vocovoc_expression0) + register_synthezier(synthesize_covovoc_expression0) + register_synthezier(synthesize_vococov_expression0) + + register_synthezier(synthesize_vovovov_expression1) + register_synthezier(synthesize_vovovoc_expression1) + register_synthezier(synthesize_vovocov_expression1) + register_synthezier(synthesize_vocovov_expression1) + register_synthezier(synthesize_covovov_expression1) + register_synthezier(synthesize_covocov_expression1) + register_synthezier(synthesize_vocovoc_expression1) + register_synthezier(synthesize_covovoc_expression1) + register_synthezier(synthesize_vococov_expression1) + + register_synthezier(synthesize_vovovov_expression2) + register_synthezier(synthesize_vovovoc_expression2) + register_synthezier(synthesize_vovocov_expression2) + register_synthezier(synthesize_vocovov_expression2) + register_synthezier(synthesize_covovov_expression2) + register_synthezier(synthesize_covocov_expression2) + register_synthezier(synthesize_vocovoc_expression2) + register_synthezier(synthesize_covovoc_expression2) + + register_synthezier(synthesize_vovovov_expression3) + register_synthezier(synthesize_vovovoc_expression3) + register_synthezier(synthesize_vovocov_expression3) + register_synthezier(synthesize_vocovov_expression3) + register_synthezier(synthesize_covovov_expression3) + register_synthezier(synthesize_covocov_expression3) + register_synthezier(synthesize_vocovoc_expression3) + register_synthezier(synthesize_covovoc_expression3) + register_synthezier(synthesize_vococov_expression3) + + register_synthezier(synthesize_vovovov_expression4) + register_synthezier(synthesize_vovovoc_expression4) + register_synthezier(synthesize_vovocov_expression4) + register_synthezier(synthesize_vocovov_expression4) + register_synthezier(synthesize_covovov_expression4) + register_synthezier(synthesize_covocov_expression4) + register_synthezier(synthesize_vocovoc_expression4) + register_synthezier(synthesize_covovoc_expression4) + #endif + } + + inline void set_parser(parser_t& p) + { + parser_ = &p; + } + + inline void set_uom(unary_op_map_t& unary_op_map) + { + unary_op_map_ = &unary_op_map; + } + + inline void set_bom(binary_op_map_t& binary_op_map) + { + binary_op_map_ = &binary_op_map; + } + + inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map) + { + inv_binary_op_map_ = &inv_binary_op_map; + } + + inline void set_sf3m(sf3_map_t& sf3_map) + { + sf3_map_ = &sf3_map; + } + + inline void set_sf4m(sf4_map_t& sf4_map) + { + sf4_map_ = &sf4_map; + } + + inline void set_allocator(details::node_allocator& na) + { + node_allocator_ = &na; + } + + inline void set_strength_reduction_state(const bool enabled) + { + strength_reduction_enabled_ = enabled; + } + + inline bool strength_reduction_enabled() const + { + return strength_reduction_enabled_; + } + + inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop) + { + typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation); + + if ((*binary_op_map_).end() == bop_itr) + return false; + + bop = bop_itr->second; + + return true; + } + + inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop) + { + typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation); + + if ((*unary_op_map_).end() == uop_itr) + return false; + + uop = uop_itr->second; + + return true; + } + + inline details::operator_type get_operator(const binary_functor_t& bop) const + { + return (*inv_binary_op_map_).find(bop)->second; + } + + inline expression_node_ptr operator() (const Type& v) const + { + return node_allocator_->allocate(v); + } + + #ifndef exprtk_disable_string_capabilities + inline expression_node_ptr operator() (const std::string& s) const + { + return node_allocator_->allocate(s); + } + + inline expression_node_ptr operator() (std::string& s, range_t& rp) const + { + return node_allocator_->allocate_rr(s,rp); + } + + inline expression_node_ptr operator() (const std::string& s, range_t& rp) const + { + return node_allocator_->allocate_tt(s,rp); + } + + inline expression_node_ptr operator() (expression_node_ptr branch, range_t& rp) const + { + if (is_generally_string_node(branch)) + return node_allocator_->allocate_tt(branch,rp); + else + return error_node(); + } + #endif + + inline bool unary_optimisable(const details::operator_type& operation) const + { + return (details::e_abs == operation) || (details::e_acos == operation) || + (details::e_acosh == operation) || (details::e_asin == operation) || + (details::e_asinh == operation) || (details::e_atan == operation) || + (details::e_atanh == operation) || (details::e_ceil == operation) || + (details::e_cos == operation) || (details::e_cosh == operation) || + (details::e_exp == operation) || (details::e_expm1 == operation) || + (details::e_floor == operation) || (details::e_log == operation) || + (details::e_log10 == operation) || (details::e_log2 == operation) || + (details::e_log1p == operation) || (details::e_neg == operation) || + (details::e_pos == operation) || (details::e_round == operation) || + (details::e_sin == operation) || (details::e_sinc == operation) || + (details::e_sinh == operation) || (details::e_sqrt == operation) || + (details::e_tan == operation) || (details::e_tanh == operation) || + (details::e_cot == operation) || (details::e_sec == operation) || + (details::e_csc == operation) || (details::e_r2d == operation) || + (details::e_d2r == operation) || (details::e_d2g == operation) || + (details::e_g2d == operation) || (details::e_notl == operation) || + (details::e_sgn == operation) || (details::e_erf == operation) || + (details::e_erfc == operation) || (details::e_ncdf == operation) || + (details::e_frac == operation) || (details::e_trunc == operation) ; + } + + inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc) const + { + typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id); + + if (sf3_map_->end() == itr) + return false; + else + tfunc = itr->second.first; + + return true; + } + + inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc) const + { + typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id); + + if (sf4_map_->end() == itr) + return false; + else + qfunc = itr->second.first; + + return true; + } + + inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation) const + { + typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id); + + if (sf3_map_->end() == itr) + return false; + else + operation = itr->second.second; + + return true; + } + + inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation) const + { + typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id); + + if (sf4_map_->end() == itr) + return false; + else + operation = itr->second.second; + + return true; + } + + inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[1]) + { + if (0 == branch[0]) + { + return error_node(); + } + else if (details::is_null_node(branch[0])) + { + return branch[0]; + } + else if (details::is_break_node(branch[0])) + { + return error_node(); + } + else if (details::is_continue_node(branch[0])) + { + return error_node(); + } + else if (details::is_constant_node(branch[0])) + { + return synthesize_expression(operation,branch); + } + else if (unary_optimisable(operation) && details::is_variable_node(branch[0])) + { + return synthesize_uv_expression(operation,branch); + } + else if (unary_optimisable(operation) && details::is_ivector_node(branch[0])) + { + return synthesize_uvec_expression(operation,branch); + } + else + return synthesize_unary_expression(operation,branch); + } + + inline bool is_assignment_operation(const details::operator_type& operation) const + { + return ( + (details::e_addass == operation) || + (details::e_subass == operation) || + (details::e_mulass == operation) || + (details::e_divass == operation) || + (details::e_modass == operation) + ) && + parser_->settings_.assignment_enabled(operation); + } + + #ifndef exprtk_disable_string_capabilities + inline bool valid_string_operation(const details::operator_type& operation) const + { + return (details::e_add == operation) || + (details::e_lt == operation) || + (details::e_lte == operation) || + (details::e_gt == operation) || + (details::e_gte == operation) || + (details::e_eq == operation) || + (details::e_ne == operation) || + (details::e_in == operation) || + (details::e_like == operation) || + (details::e_ilike == operation) || + (details::e_assign == operation) || + (details::e_addass == operation) || + (details::e_swap == operation) ; + } + #else + inline bool valid_string_operation(const details::operator_type&) const + { + return false; + } + #endif + + inline std::string to_str(const details::operator_type& operation) const + { + switch (operation) + { + case details::e_add : return "+" ; + case details::e_sub : return "-" ; + case details::e_mul : return "*" ; + case details::e_div : return "/" ; + case details::e_mod : return "%" ; + case details::e_pow : return "^" ; + case details::e_lt : return "<" ; + case details::e_lte : return "<=" ; + case details::e_gt : return ">" ; + case details::e_gte : return ">=" ; + case details::e_eq : return "==" ; + case details::e_ne : return "!=" ; + case details::e_and : return "and" ; + case details::e_nand : return "nand" ; + case details::e_or : return "or" ; + case details::e_nor : return "nor" ; + case details::e_xor : return "xor" ; + case details::e_xnor : return "xnor" ; + default : return "UNKNOWN"; + } + } + + inline bool operation_optimisable(const details::operator_type& operation) const + { + return (details::e_add == operation) || + (details::e_sub == operation) || + (details::e_mul == operation) || + (details::e_div == operation) || + (details::e_mod == operation) || + (details::e_pow == operation) || + (details::e_lt == operation) || + (details::e_lte == operation) || + (details::e_gt == operation) || + (details::e_gte == operation) || + (details::e_eq == operation) || + (details::e_ne == operation) || + (details::e_and == operation) || + (details::e_nand == operation) || + (details::e_or == operation) || + (details::e_nor == operation) || + (details::e_xor == operation) || + (details::e_xnor == operation) ; + } + + inline std::string branch_to_id(expression_node_ptr branch) const + { + static const std::string null_str ("(null)" ); + static const std::string const_str ("(c)" ); + static const std::string var_str ("(v)" ); + static const std::string vov_str ("(vov)" ); + static const std::string cov_str ("(cov)" ); + static const std::string voc_str ("(voc)" ); + static const std::string str_str ("(s)" ); + static const std::string strrng_str ("(rngs)" ); + static const std::string cs_str ("(cs)" ); + static const std::string cstrrng_str("(crngs)"); + + if (details::is_null_node(branch)) + return null_str; + else if (details::is_constant_node(branch)) + return const_str; + else if (details::is_variable_node(branch)) + return var_str; + else if (details::is_vov_node(branch)) + return vov_str; + else if (details::is_cov_node(branch)) + return cov_str; + else if (details::is_voc_node(branch)) + return voc_str; + else if (details::is_string_node(branch)) + return str_str; + else if (details::is_const_string_node(branch)) + return cs_str; + else if (details::is_string_range_node(branch)) + return strrng_str; + else if (details::is_const_string_range_node(branch)) + return cstrrng_str; + else if (details::is_t0ot1ot2_node(branch)) + return "(" + dynamic_cast*>(branch)->type_id() + ")"; + else if (details::is_t0ot1ot2ot3_node(branch)) + return "(" + dynamic_cast*>(branch)->type_id() + ")"; + else + return "ERROR"; + } + + inline std::string branch_to_id(expression_node_ptr (&branch)[2]) const + { + return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]); + } + + inline bool cov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + { + if (!operation_optimisable(operation)) + return false; + else + return details::is_constant_node(branch[0]) && + details::is_variable_node(branch[1]) ; + } + + inline bool voc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + { + if (!operation_optimisable(operation)) + return false; + else + return details::is_variable_node(branch[0]) && + details::is_constant_node(branch[1]) ; + } + + inline bool vov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + { + if (!operation_optimisable(operation)) + return false; + else + return details::is_variable_node(branch[0]) && + details::is_variable_node(branch[1]) ; + } + + inline bool cob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + { + if (!operation_optimisable(operation)) + return false; + else + return details::is_constant_node(branch[0]) && + !details::is_constant_node(branch[1]) ; + } + + inline bool boc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + { + if (!operation_optimisable(operation)) + return false; + else + return !details::is_constant_node(branch[0]) && + details::is_constant_node(branch[1]) ; + } + + inline bool cocob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + { + if ( + (details::e_add == operation) || + (details::e_sub == operation) || + (details::e_mul == operation) || + (details::e_div == operation) + ) + { + return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) || + (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0])) ; + } + else + return false; + } + + inline bool coboc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + { + if ( + (details::e_add == operation) || + (details::e_sub == operation) || + (details::e_mul == operation) || + (details::e_div == operation) + ) + { + return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) || + (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0])) ; + } + else + return false; + } + + inline bool uvouv_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + { + if (!operation_optimisable(operation)) + return false; + else + return details::is_uv_node(branch[0]) && + details::is_uv_node(branch[1]) ; + } + + inline bool vob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + { + if (!operation_optimisable(operation)) + return false; + else + return details::is_variable_node(branch[0]) && + !details::is_variable_node(branch[1]) ; + } + + inline bool bov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + { + if (!operation_optimisable(operation)) + return false; + else + return !details::is_variable_node(branch[0]) && + details::is_variable_node(branch[1]) ; + } + + inline bool binext_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + { + if (!operation_optimisable(operation)) + return false; + else + return !details::is_constant_node(branch[0]) || + !details::is_constant_node(branch[1]) ; + } + + inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + { + if (is_assignment_operation(operation)) + { + const bool b1_is_genstring = details::is_generally_string_node(branch[1]); + + if (details::is_string_node(branch[0])) + return !b1_is_genstring; + else + return ( + !details::is_variable_node (branch[0]) && + !details::is_vector_elem_node (branch[0]) && + !details::is_rebasevector_elem_node (branch[0]) && + !details::is_rebasevector_celem_node(branch[0]) && + !details::is_vector_node (branch[0]) + ) + || b1_is_genstring; + } + else + return false; + } + + inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2]) const + { + if ( + !details::is_constant_node(branch[1]) || + details::is_constant_node(branch[0]) || + details::is_variable_node(branch[0]) || + details::is_vector_node (branch[0]) || + details::is_generally_string_node(branch[0]) + ) + return false; + + const Type c = static_cast*>(branch[1])->value(); + + return cardinal_pow_optimisable(operation, c); + } + + inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2]) const + { + return ( + details::is_break_node (branch[0]) || + details::is_break_node (branch[1]) || + details::is_continue_node(branch[0]) || + details::is_continue_node(branch[1]) + ); + } + + inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + { + const bool b0_string = is_generally_string_node(branch[0]); + const bool b1_string = is_generally_string_node(branch[1]); + + bool result = false; + + if (b0_string != b1_string) + result = true; + else if (!valid_string_operation(operation) && b0_string && b1_string) + result = true; + + if (result) + { + parser_->set_synthesis_error("Invalid string operation"); + } + + return result; + } + + inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const + { + const bool b0_string = is_generally_string_node(branch[0]); + const bool b1_string = is_generally_string_node(branch[1]); + const bool b2_string = is_generally_string_node(branch[2]); + + bool result = false; + + if ((b0_string != b1_string) || (b1_string != b2_string)) + result = true; + else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string) + result = true; + + if (result) + { + parser_->set_synthesis_error("Invalid string operation"); + } + + return result; + } + + inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + { + const bool b0_string = is_generally_string_node(branch[0]); + const bool b1_string = is_generally_string_node(branch[1]); + + return (b0_string && b1_string && valid_string_operation(operation)); + } + + inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const + { + const bool b0_string = is_generally_string_node(branch[0]); + const bool b1_string = is_generally_string_node(branch[1]); + const bool b2_string = is_generally_string_node(branch[2]); + + return (b0_string && b1_string && b2_string && (details::e_inrange == operation)); + } + + #ifndef exprtk_disable_sc_andor + inline bool is_shortcircuit_expression(const details::operator_type& operation) const + { + return ( + (details::e_scand == operation) || + (details::e_scor == operation) + ); + } + #else + inline bool is_shortcircuit_expression(const details::operator_type&) const + { + return false; + } + #endif + + inline bool is_null_present(expression_node_ptr (&branch)[2]) const + { + return ( + details::is_null_node(branch[0]) || + details::is_null_node(branch[1]) + ); + } + + inline bool is_vector_eqineq_logic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + { + if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1])) + return false; + else + return ( + (details::e_lt == operation) || + (details::e_lte == operation) || + (details::e_gt == operation) || + (details::e_gte == operation) || + (details::e_eq == operation) || + (details::e_ne == operation) || + (details::e_equal == operation) || + (details::e_and == operation) || + (details::e_nand == operation) || + (details:: e_or == operation) || + (details:: e_nor == operation) || + (details:: e_xor == operation) || + (details::e_xnor == operation) + ); + } + + inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + { + if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1])) + return false; + else + return ( + (details::e_add == operation) || + (details::e_sub == operation) || + (details::e_mul == operation) || + (details::e_div == operation) || + (details::e_pow == operation) + ); + } + + inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[2]) + { + if ((0 == branch[0]) || (0 == branch[1])) + { + return error_node(); + } + else if (is_invalid_string_op(operation,branch)) + { + return error_node(); + } + else if (is_invalid_assignment_op(operation,branch)) + { + return error_node(); + } + else if (is_invalid_break_continue_op(branch)) + { + return error_node(); + } + else if (details::e_assign == operation) + { + return synthesize_assignment_expression(operation, branch); + } + else if (details::e_swap == operation) + { + return synthesize_swap_expression(branch); + } + else if (is_assignment_operation(operation)) + { + return synthesize_assignment_operation_expression(operation, branch); + } + else if (is_vector_eqineq_logic_operation(operation, branch)) + { + return synthesize_veceqineqlogic_operation_expression(operation, branch); + } + else if (is_vector_arithmetic_operation(operation, branch)) + { + return synthesize_vecarithmetic_operation_expression(operation, branch); + } + else if (is_shortcircuit_expression(operation)) + { + return synthesize_shortcircuit_expression(operation, branch); + } + else if (is_string_operation(operation, branch)) + { + return synthesize_string_expression(operation, branch); + } + else if (is_null_present(branch)) + { + return synthesize_null_expression(operation, branch); + } + #ifndef exprtk_disable_cardinal_pow_optimisation + else if (is_constpow_operation(operation, branch)) + { + return cardinal_pow_optimisation(branch); + } + #endif + + expression_node_ptr result = error_node(); + + #ifndef exprtk_disable_enhanced_features + if (synthesize_expression(operation, branch, result)) + { + return result; + } + else + #endif + + { + /* + Possible reductions: + 1. c o cob -> cob + 2. cob o c -> cob + 3. c o boc -> boc + 4. boc o c -> boc + */ + result = error_node(); + + if (cocob_optimisable(operation, branch)) + { + result = synthesize_cocob_expression::process((*this), operation, branch); + } + else if (coboc_optimisable(operation, branch) && (0 == result)) + { + result = synthesize_coboc_expression::process((*this), operation, branch); + } + + if (result) + return result; + } + + if (uvouv_optimisable(operation, branch)) + { + return synthesize_uvouv_expression(operation, branch); + } + else if (vob_optimisable(operation, branch)) + { + return synthesize_vob_expression::process((*this), operation, branch); + } + else if (bov_optimisable(operation, branch)) + { + return synthesize_bov_expression::process((*this), operation, branch); + } + else if (cob_optimisable(operation, branch)) + { + return synthesize_cob_expression::process((*this), operation, branch); + } + else if (boc_optimisable(operation, branch)) + { + return synthesize_boc_expression::process((*this), operation, branch); + } + #ifndef exprtk_disable_enhanced_features + else if (cov_optimisable(operation, branch)) + { + return synthesize_cov_expression::process((*this), operation, branch); + } + #endif + else if (binext_optimisable(operation, branch)) + { + return synthesize_binary_ext_expression::process((*this), operation, branch); + } + else + return synthesize_expression(operation, branch); + } + + inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[3]) + { + if ( + (0 == branch[0]) || + (0 == branch[1]) || + (0 == branch[2]) + ) + { + details::free_all_nodes(*node_allocator_,branch); + + return error_node(); + } + else if (is_invalid_string_op(operation, branch)) + { + return error_node(); + } + else if (is_string_operation(operation, branch)) + { + return synthesize_string_expression(operation, branch); + } + else + return synthesize_expression(operation, branch); + } + + inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[4]) + { + return synthesize_expression(operation,branch); + } + + inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr b0) + { + expression_node_ptr branch[1] = { b0 }; + return (*this)(operation,branch); + } + + inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr& b0, expression_node_ptr& b1) + { + expression_node_ptr result = error_node(); + + if ((0 != b0) && (0 != b1)) + { + expression_node_ptr branch[2] = { b0, b1 }; + result = expression_generator::operator()(operation, branch); + b0 = branch[0]; + b1 = branch[1]; + } + + return result; + } + + inline expression_node_ptr conditional(expression_node_ptr condition, + expression_node_ptr consequent, + expression_node_ptr alternative) const + { + if ((0 == condition) || (0 == consequent)) + { + free_node(*node_allocator_, condition); + free_node(*node_allocator_, consequent); + free_node(*node_allocator_, alternative); + + return error_node(); + } + // Can the condition be immediately evaluated? if so optimise. + else if (details::is_constant_node(condition)) + { + // True branch + if (details::is_true(condition)) + { + free_node(*node_allocator_, condition); + free_node(*node_allocator_, alternative); + + return consequent; + } + // False branch + else + { + free_node(*node_allocator_, condition); + free_node(*node_allocator_, consequent); + + if (alternative) + return alternative; + else + return node_allocator_->allocate >(); + } + } + else if ((0 != consequent) && (0 != alternative)) + { + return node_allocator_-> + allocate(condition, consequent, alternative); + } + else + return node_allocator_-> + allocate(condition, consequent); + } + + #ifndef exprtk_disable_string_capabilities + inline expression_node_ptr conditional_string(expression_node_ptr condition, + expression_node_ptr consequent, + expression_node_ptr alternative) const + { + if ((0 == condition) || (0 == consequent)) + { + free_node(*node_allocator_, condition); + free_node(*node_allocator_, consequent); + free_node(*node_allocator_, alternative); + + return error_node(); + } + // Can the condition be immediately evaluated? if so optimise. + else if (details::is_constant_node(condition)) + { + // True branch + if (details::is_true(condition)) + { + free_node(*node_allocator_, condition); + free_node(*node_allocator_, alternative); + + return consequent; + } + // False branch + else + { + free_node(*node_allocator_, condition); + free_node(*node_allocator_, consequent); + + if (alternative) + return alternative; + else + return node_allocator_-> + allocate_c >(""); + } + } + else if ((0 != consequent) && (0 != alternative)) + return node_allocator_-> + allocate(condition, consequent, alternative); + else + return error_node(); + } + #else + inline expression_node_ptr conditional_string(expression_node_ptr, + expression_node_ptr, + expression_node_ptr) const + { + return error_node(); + } + #endif + + inline expression_node_ptr while_loop(expression_node_ptr& condition, + expression_node_ptr& branch, + const bool brkcont = false) const + { + if (!brkcont && details::is_constant_node(condition)) + { + expression_node_ptr result = error_node(); + if (details::is_true(condition)) + // Infinite loops are not allowed. + result = error_node(); + else + result = node_allocator_->allocate >(); + + free_node(*node_allocator_, condition); + free_node(*node_allocator_, branch); + + return result; + } + else if (details::is_null_node(condition)) + { + free_node(*node_allocator_,condition); + + return branch; + } + else if (!brkcont) + return node_allocator_->allocate(condition,branch); + #ifndef exprtk_disable_break_continue + else + return node_allocator_->allocate(condition,branch); + #else + return error_node(); + #endif + } + + inline expression_node_ptr repeat_until_loop(expression_node_ptr& condition, + expression_node_ptr& branch, + const bool brkcont = false) const + { + if (!brkcont && details::is_constant_node(condition)) + { + if ( + details::is_true(condition) && + details::is_constant_node(branch) + ) + { + free_node(*node_allocator_,condition); + + return branch; + } + + free_node(*node_allocator_, condition); + free_node(*node_allocator_, branch); + + return error_node(); + } + else if (details::is_null_node(condition)) + { + free_node(*node_allocator_,condition); + + return branch; + } + else if (!brkcont) + return node_allocator_->allocate(condition,branch); + #ifndef exprtk_disable_break_continue + else + return node_allocator_->allocate(condition,branch); + #else + return error_node(); + #endif + } + + inline expression_node_ptr for_loop(expression_node_ptr& initialiser, + expression_node_ptr& condition, + expression_node_ptr& incrementor, + expression_node_ptr& loop_body, + bool brkcont = false) const + { + if (!brkcont && details::is_constant_node(condition)) + { + expression_node_ptr result = error_node(); + + if (details::is_true(condition)) + // Infinite loops are not allowed. + result = error_node(); + else + result = node_allocator_->allocate >(); + + free_node(*node_allocator_, initialiser); + free_node(*node_allocator_, condition); + free_node(*node_allocator_, incrementor); + free_node(*node_allocator_, loop_body); + + return result; + } + else if (details::is_null_node(condition) || (0 == condition)) + { + free_node(*node_allocator_, initialiser); + free_node(*node_allocator_, condition); + free_node(*node_allocator_, incrementor); + + return loop_body; + } + else if (!brkcont) + return node_allocator_->allocate + ( + initialiser, + condition, + incrementor, + loop_body + ); + + #ifndef exprtk_disable_break_continue + else + return node_allocator_->allocate + ( + initialiser, + condition, + incrementor, + loop_body + ); + #else + return error_node(); + #endif + } + + template class Sequence> + inline expression_node_ptr const_optimise_switch(Sequence& arg_list) + { + expression_node_ptr result = error_node(); + + for (std::size_t i = 0; i < (arg_list.size() / 2); ++i) + { + expression_node_ptr condition = arg_list[(2 * i) ]; + expression_node_ptr consequent = arg_list[(2 * i) + 1]; + + if ((0 == result) && details::is_true(condition)) + { + result = consequent; + break; + } + } + + if (0 == result) + { + result = arg_list.back(); + } + + for (std::size_t i = 0; i < arg_list.size(); ++i) + { + expression_node_ptr current_expr = arg_list[i]; + + if (current_expr && (current_expr != result)) + { + free_node(*node_allocator_,current_expr); + } + } + + return result; + } + + template class Sequence> + inline expression_node_ptr const_optimise_mswitch(Sequence& arg_list) + { + expression_node_ptr result = error_node(); + + for (std::size_t i = 0; i < (arg_list.size() / 2); ++i) + { + expression_node_ptr condition = arg_list[(2 * i) ]; + expression_node_ptr consequent = arg_list[(2 * i) + 1]; + + if (details::is_true(condition)) + { + result = consequent; + } + } + + if (0 == result) + { + T zero = T(0); + result = node_allocator_->allocate(zero); + } + + for (std::size_t i = 0; i < arg_list.size(); ++i) + { + expression_node_ptr& current_expr = arg_list[i]; + + if (current_expr && (current_expr != result)) + { + free_node(*node_allocator_,current_expr); + } + } + + return result; + } + + struct switch_nodes + { + typedef std::vector arg_list_t; + + #define case_stmt(N) \ + if (is_true(arg[(2 * N)])) { return arg[(2 * N) + 1]->value(); } \ + + struct switch_1 + { + static inline T process(const arg_list_t& arg) + { + case_stmt(0) + + return arg.back()->value(); + } + }; + + struct switch_2 + { + static inline T process(const arg_list_t& arg) + { + case_stmt(0) case_stmt(1) + + return arg.back()->value(); + } + }; + + struct switch_3 + { + static inline T process(const arg_list_t& arg) + { + case_stmt(0) case_stmt(1) + case_stmt(2) + + return arg.back()->value(); + } + }; + + struct switch_4 + { + static inline T process(const arg_list_t& arg) + { + case_stmt(0) case_stmt(1) + case_stmt(2) case_stmt(3) + + return arg.back()->value(); + } + }; + + struct switch_5 + { + static inline T process(const arg_list_t& arg) + { + case_stmt(0) case_stmt(1) + case_stmt(2) case_stmt(3) + case_stmt(4) + + return arg.back()->value(); + } + }; + + struct switch_6 + { + static inline T process(const arg_list_t& arg) + { + case_stmt(0) case_stmt(1) + case_stmt(2) case_stmt(3) + case_stmt(4) case_stmt(5) + + return arg.back()->value(); + } + }; + + struct switch_7 + { + static inline T process(const arg_list_t& arg) + { + case_stmt(0) case_stmt(1) + case_stmt(2) case_stmt(3) + case_stmt(4) case_stmt(5) + case_stmt(6) + + return arg.back()->value(); + } + }; + + #undef case_stmt + }; + + template class Sequence> + inline expression_node_ptr switch_statement(Sequence& arg_list) + { + if (arg_list.empty()) + return error_node(); + else if ( + !all_nodes_valid(arg_list) || + (arg_list.size() < 3) || + ((arg_list.size() % 2) != 1) + ) + { + details::free_all_nodes(*node_allocator_,arg_list); + + return error_node(); + } + else if (is_constant_foldable(arg_list)) + return const_optimise_switch(arg_list); + + switch ((arg_list.size() - 1) / 2) + { + #define case_stmt(N) \ + case N : \ + return node_allocator_-> \ + allocate >(arg_list); \ + + case_stmt(1) + case_stmt(2) + case_stmt(3) + case_stmt(4) + case_stmt(5) + case_stmt(6) + case_stmt(7) + #undef case_stmt + + default : return node_allocator_->allocate >(arg_list); + } + } + + template class Sequence> + inline expression_node_ptr multi_switch_statement(Sequence& arg_list) + { + if (!all_nodes_valid(arg_list)) + { + details::free_all_nodes(*node_allocator_,arg_list); + + return error_node(); + } + else if (is_constant_foldable(arg_list)) + return const_optimise_mswitch(arg_list); + else + return node_allocator_->allocate >(arg_list); + } + + #define unary_opr_switch_statements \ + case_stmt(details:: e_abs, details:: abs_op) \ + case_stmt(details:: e_acos, details:: acos_op) \ + case_stmt(details::e_acosh, details::acosh_op) \ + case_stmt(details:: e_asin, details:: asin_op) \ + case_stmt(details::e_asinh, details::asinh_op) \ + case_stmt(details:: e_atan, details:: atan_op) \ + case_stmt(details::e_atanh, details::atanh_op) \ + case_stmt(details:: e_ceil, details:: ceil_op) \ + case_stmt(details:: e_cos, details:: cos_op) \ + case_stmt(details:: e_cosh, details:: cosh_op) \ + case_stmt(details:: e_exp, details:: exp_op) \ + case_stmt(details::e_expm1, details::expm1_op) \ + case_stmt(details::e_floor, details::floor_op) \ + case_stmt(details:: e_log, details:: log_op) \ + case_stmt(details::e_log10, details::log10_op) \ + case_stmt(details:: e_log2, details:: log2_op) \ + case_stmt(details::e_log1p, details::log1p_op) \ + case_stmt(details:: e_neg, details:: neg_op) \ + case_stmt(details:: e_pos, details:: pos_op) \ + case_stmt(details::e_round, details::round_op) \ + case_stmt(details:: e_sin, details:: sin_op) \ + case_stmt(details:: e_sinc, details:: sinc_op) \ + case_stmt(details:: e_sinh, details:: sinh_op) \ + case_stmt(details:: e_sqrt, details:: sqrt_op) \ + case_stmt(details:: e_tan, details:: tan_op) \ + case_stmt(details:: e_tanh, details:: tanh_op) \ + case_stmt(details:: e_cot, details:: cot_op) \ + case_stmt(details:: e_sec, details:: sec_op) \ + case_stmt(details:: e_csc, details:: csc_op) \ + case_stmt(details:: e_r2d, details:: r2d_op) \ + case_stmt(details:: e_d2r, details:: d2r_op) \ + case_stmt(details:: e_d2g, details:: d2g_op) \ + case_stmt(details:: e_g2d, details:: g2d_op) \ + case_stmt(details:: e_notl, details:: notl_op) \ + case_stmt(details:: e_sgn, details:: sgn_op) \ + case_stmt(details:: e_erf, details:: erf_op) \ + case_stmt(details:: e_erfc, details:: erfc_op) \ + case_stmt(details:: e_ncdf, details:: ncdf_op) \ + case_stmt(details:: e_frac, details:: frac_op) \ + case_stmt(details::e_trunc, details::trunc_op) \ + + inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation, + expression_node_ptr (&branch)[1]) + { + T& v = static_cast*>(branch[0])->ref(); + + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + allocate > >(v); \ + + unary_opr_switch_statements + #undef case_stmt + default : return error_node(); + } + } + + inline expression_node_ptr synthesize_uvec_expression(const details::operator_type& operation, + expression_node_ptr (&branch)[1]) + { + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + allocate > > \ + (operation, branch[0]); \ + + unary_opr_switch_statements + #undef case_stmt + default : return error_node(); + } + } + + inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation, + expression_node_ptr (&branch)[1]) + { + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + allocate > >(branch[0]); \ + + unary_opr_switch_statements + #undef case_stmt + default : return error_node(); + } + } + + inline expression_node_ptr const_optimise_sf3(const details::operator_type& operation, + expression_node_ptr (&branch)[3]) + { + expression_node_ptr temp_node = error_node(); + + switch (operation) + { + #define case_stmt(op) \ + case details::e_sf##op : temp_node = node_allocator_-> \ + allocate > > \ + (operation, branch); \ + break; \ + + case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) + case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) + case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) + case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) + case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) + case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) + case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) + case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) + case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) + case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) + case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) + case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) + #undef case_stmt + default : return error_node(); + } + + const T v = temp_node->value(); + + details::free_node(*node_allocator_,temp_node); + + return node_allocator_->allocate(v); + } + + inline expression_node_ptr varnode_optimise_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3]) + { + typedef details::variable_node* variable_ptr; + + const Type& v0 = static_cast(branch[0])->ref(); + const Type& v1 = static_cast(branch[1])->ref(); + const Type& v2 = static_cast(branch[2])->ref(); + + switch (operation) + { + #define case_stmt(op) \ + case details::e_sf##op : return node_allocator_-> \ + allocate_rrr > > \ + (v0, v1, v2); \ + + case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) + case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) + case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) + case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) + case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) + case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) + case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) + case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) + case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) + case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) + case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) + case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) + #undef case_stmt + default : return error_node(); + } + } + + inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3]) + { + if (!all_nodes_valid(branch)) + return error_node(); + else if (is_constant_foldable(branch)) + return const_optimise_sf3(operation,branch); + else if (all_nodes_variables(branch)) + return varnode_optimise_sf3(operation,branch); + else + { + switch (operation) + { + #define case_stmt(op) \ + case details::e_sf##op : return node_allocator_-> \ + allocate > > \ + (operation, branch); \ + + case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) + case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) + case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) + case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) + case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) + case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) + case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) + case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) + case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) + case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) + case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) + case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) + #undef case_stmt + default : return error_node(); + } + } + } + + inline expression_node_ptr const_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) + { + expression_node_ptr temp_node = error_node(); + + switch (operation) + { + #define case_stmt(op) \ + case details::e_sf##op : temp_node = node_allocator_-> \ + allocate > > \ + (operation, branch); \ + break; \ + + case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) + case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) + case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) + case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) + case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) + case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) + case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) + case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) + case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) + case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) + case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) + case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) + case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) + #undef case_stmt + default : return error_node(); + } + + const T v = temp_node->value(); + + details::free_node(*node_allocator_,temp_node); + + return node_allocator_->allocate(v); + } + + inline expression_node_ptr varnode_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) + { + typedef details::variable_node* variable_ptr; + + const Type& v0 = static_cast(branch[0])->ref(); + const Type& v1 = static_cast(branch[1])->ref(); + const Type& v2 = static_cast(branch[2])->ref(); + const Type& v3 = static_cast(branch[3])->ref(); + + switch (operation) + { + #define case_stmt(op) \ + case details::e_sf##op : return node_allocator_-> \ + allocate_rrrr > > \ + (v0, v1, v2, v3); \ + + case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) + case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) + case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) + case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) + case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) + case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) + case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) + case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) + case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) + case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) + case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) + case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) + case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) + #undef case_stmt + default : return error_node(); + } + } + + inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4]) + { + if (!all_nodes_valid(branch)) + return error_node(); + else if (is_constant_foldable(branch)) + return const_optimise_sf4(operation,branch); + else if (all_nodes_variables(branch)) + return varnode_optimise_sf4(operation,branch); + switch (operation) + { + #define case_stmt(op) \ + case details::e_sf##op : return node_allocator_-> \ + allocate > > \ + (operation, branch); \ + + case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) + case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) + case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) + case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) + case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) + case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) + case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) + case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) + case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) + case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) + case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) + case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) + case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) + #undef case_stmt + default : return error_node(); + } + } + + template class Sequence> + inline expression_node_ptr const_optimise_varargfunc(const details::operator_type& operation, Sequence& arg_list) + { + expression_node_ptr temp_node = error_node(); + + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : temp_node = node_allocator_-> \ + allocate > > \ + (arg_list); \ + break; \ + + case_stmt(details::e_sum , details::vararg_add_op ) + case_stmt(details::e_prod , details::vararg_mul_op ) + case_stmt(details::e_avg , details::vararg_avg_op ) + case_stmt(details::e_min , details::vararg_min_op ) + case_stmt(details::e_max , details::vararg_max_op ) + case_stmt(details::e_mand , details::vararg_mand_op ) + case_stmt(details::e_mor , details::vararg_mor_op ) + case_stmt(details::e_multi , details::vararg_multi_op) + #undef case_stmt + default : return error_node(); + } + + const T v = temp_node->value(); + + details::free_node(*node_allocator_,temp_node); + + return node_allocator_->allocate(v); + } + + inline bool special_one_parameter_vararg(const details::operator_type& operation) const + { + return ( + (details::e_sum == operation) || + (details::e_prod == operation) || + (details::e_avg == operation) || + (details::e_min == operation) || + (details::e_max == operation) + ); + } + + template class Sequence> + inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, Sequence& arg_list) + { + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + allocate > >(arg_list); \ + + case_stmt(details::e_sum , details::vararg_add_op ) + case_stmt(details::e_prod , details::vararg_mul_op ) + case_stmt(details::e_avg , details::vararg_avg_op ) + case_stmt(details::e_min , details::vararg_min_op ) + case_stmt(details::e_max , details::vararg_max_op ) + case_stmt(details::e_mand , details::vararg_mand_op ) + case_stmt(details::e_mor , details::vararg_mor_op ) + case_stmt(details::e_multi , details::vararg_multi_op) + #undef case_stmt + default : return error_node(); + } + } + + template class Sequence> + inline expression_node_ptr vectorize_func(const details::operator_type& operation, Sequence& arg_list) + { + if (1 == arg_list.size()) + { + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + allocate > >(arg_list[0]); \ + + case_stmt(details::e_sum , details::vec_add_op) + case_stmt(details::e_prod , details::vec_mul_op) + case_stmt(details::e_avg , details::vec_avg_op) + case_stmt(details::e_min , details::vec_min_op) + case_stmt(details::e_max , details::vec_max_op) + #undef case_stmt + default : return error_node(); + } + } + else + return error_node(); + } + + template class Sequence> + inline expression_node_ptr vararg_function(const details::operator_type& operation, Sequence& arg_list) + { + if (!all_nodes_valid(arg_list)) + { + details::free_all_nodes(*node_allocator_,arg_list); + + return error_node(); + } + else if (is_constant_foldable(arg_list)) + return const_optimise_varargfunc(operation,arg_list); + else if ((arg_list.size() == 1) && details::is_ivector_node(arg_list[0])) + return vectorize_func(operation,arg_list); + else if ((arg_list.size() == 1) && special_one_parameter_vararg(operation)) + return arg_list[0]; + else if (all_nodes_variables(arg_list)) + return varnode_optimise_varargfunc(operation,arg_list); + + #ifndef exprtk_disable_string_capabilities + if (details::e_smulti == operation) + { + return node_allocator_-> + allocate > >(arg_list); + } + else + #endif + { + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + allocate > >(arg_list); \ + + case_stmt(details::e_sum , details::vararg_add_op ) + case_stmt(details::e_prod , details::vararg_mul_op ) + case_stmt(details::e_avg , details::vararg_avg_op ) + case_stmt(details::e_min , details::vararg_min_op ) + case_stmt(details::e_max , details::vararg_max_op ) + case_stmt(details::e_mand , details::vararg_mand_op ) + case_stmt(details::e_mor , details::vararg_mor_op ) + case_stmt(details::e_multi , details::vararg_multi_op) + #undef case_stmt + default : return error_node(); + } + } + } + + template + inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N]) + { + typedef typename details::function_N_node function_N_node_t; + expression_node_ptr result = synthesize_expression(f,b); + + if (0 == result) + return error_node(); + else + { + // Can the function call be completely optimised? + if (details::is_constant_node(result)) + return result; + else if (!all_nodes_valid(b)) + return error_node(); + else if (N != f->param_count) + { + details::free_all_nodes(*node_allocator_,b); + + return error_node(); + } + + function_N_node_t* func_node_ptr = static_cast(result); + + if (func_node_ptr->init_branches(b)) + return result; + else + { + details::free_all_nodes(*node_allocator_,b); + + return error_node(); + } + } + } + + inline expression_node_ptr function(ifunction_t* f) + { + typedef typename details::function_N_node function_N_node_t; + return node_allocator_->allocate(f); + } + + inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf, + std::vector& arg_list) + { + if (!all_nodes_valid(arg_list)) + { + details::free_all_nodes(*node_allocator_,arg_list); + + return error_node(); + } + + typedef details::vararg_function_node alloc_type; + + expression_node_ptr result = node_allocator_->allocate(vaf,arg_list); + + if ( + !arg_list.empty() && + !vaf->has_side_effects() && + is_constant_foldable(arg_list) + ) + { + const Type v = result->value(); + details::free_node(*node_allocator_,result); + result = node_allocator_->allocate(v); + } + + parser_->state_.activate_side_effect("vararg_function_call()"); + + return result; + } + + inline expression_node_ptr generic_function_call(igeneric_function_t* gf, + std::vector& arg_list, + const std::size_t& param_seq_index = std::numeric_limits::max()) + { + if (!all_nodes_valid(arg_list)) + { + details::free_all_nodes(*node_allocator_,arg_list); + return error_node(); + } + + typedef details::generic_function_node alloc_type1; + typedef details::multimode_genfunction_node alloc_type2; + + const std::size_t no_psi = std::numeric_limits::max(); + + expression_node_ptr result = error_node(); + + if (no_psi == param_seq_index) + result = node_allocator_->allocate(arg_list,gf); + else + result = node_allocator_->allocate(gf, param_seq_index, arg_list); + + alloc_type1* genfunc_node_ptr = static_cast(result); + + if ( + !arg_list.empty() && + !gf->has_side_effects() && + parser_->state_.type_check_enabled && + is_constant_foldable(arg_list) + ) + { + genfunc_node_ptr->init_branches(); + + const Type v = result->value(); + + details::free_node(*node_allocator_,result); + + return node_allocator_->allocate(v); + } + else if (genfunc_node_ptr->init_branches()) + { + parser_->state_.activate_side_effect("generic_function_call()"); + + return result; + } + else + { + details::free_node(*node_allocator_, result); + details::free_all_nodes(*node_allocator_, arg_list); + + return error_node(); + } + } + + #ifndef exprtk_disable_string_capabilities + inline expression_node_ptr string_function_call(igeneric_function_t* gf, + std::vector& arg_list, + const std::size_t& param_seq_index = std::numeric_limits::max()) + { + if (!all_nodes_valid(arg_list)) + { + details::free_all_nodes(*node_allocator_,arg_list); + return error_node(); + } + + typedef details::string_function_node alloc_type1; + typedef details::multimode_strfunction_node alloc_type2; + + const std::size_t no_psi = std::numeric_limits::max(); + + expression_node_ptr result = error_node(); + + if (no_psi == param_seq_index) + result = node_allocator_->allocate(gf,arg_list); + else + result = node_allocator_->allocate(gf, param_seq_index, arg_list); + + alloc_type1* strfunc_node_ptr = static_cast(result); + + if ( + !arg_list.empty() && + !gf->has_side_effects() && + is_constant_foldable(arg_list) + ) + { + strfunc_node_ptr->init_branches(); + + const Type v = result->value(); + + details::free_node(*node_allocator_,result); + + return node_allocator_->allocate(v); + } + else if (strfunc_node_ptr->init_branches()) + { + parser_->state_.activate_side_effect("string_function_call()"); + + return result; + } + else + { + details::free_node (*node_allocator_,result ); + details::free_all_nodes(*node_allocator_,arg_list); + + return error_node(); + } + } + #endif + + #ifndef exprtk_disable_return_statement + inline expression_node_ptr return_call(std::vector& arg_list) + { + if (!all_nodes_valid(arg_list)) + { + details::free_all_nodes(*node_allocator_,arg_list); + return error_node(); + } + + typedef details::return_node alloc_type; + + expression_node_ptr result = node_allocator_-> + allocate_rr(arg_list,parser_->results_ctx()); + + alloc_type* return_node_ptr = static_cast(result); + + if (return_node_ptr->init_branches()) + { + parser_->state_.activate_side_effect("return_call()"); + + return result; + } + else + { + details::free_node (*node_allocator_,result ); + details::free_all_nodes(*node_allocator_,arg_list); + + return error_node(); + } + } + + inline expression_node_ptr return_envelope(expression_node_ptr body, + results_context_t* rc, + bool*& return_invoked) + { + typedef details::return_envelope_node alloc_type; + + expression_node_ptr result = node_allocator_-> + allocate_cr(body,(*rc)); + + return_invoked = static_cast(result)->retinvk_ptr(); + + return result; + } + #else + inline expression_node_ptr return_call(std::vector&) + { + return error_node(); + } + + inline expression_node_ptr return_envelope(expression_node_ptr, + results_context_t*, + bool*&) + { + return error_node(); + } + #endif + + inline expression_node_ptr vector_element(const std::string& symbol, + vector_holder_ptr vector_base, + expression_node_ptr index) + { + expression_node_ptr result = error_node(); + + if (details::is_constant_node(index)) + { + std::size_t i = static_cast(details::numeric::to_int64(index->value())); + + details::free_node(*node_allocator_,index); + + if (vector_base->rebaseable()) + { + return node_allocator_->allocate(i,vector_base); + } + + scope_element& se = parser_->sem_.get_element(symbol,i); + + if (se.index == i) + { + result = se.var_node; + } + else + { + scope_element nse; + nse.name = symbol; + nse.active = true; + nse.ref_count = 1; + nse.type = scope_element::e_vecelem; + nse.index = i; + nse.depth = parser_->state_.scope_depth; + nse.data = 0; + nse.var_node = node_allocator_->allocate((*(*vector_base)[i])); + + if (!parser_->sem_.add_element(nse)) + { + parser_->set_synthesis_error("Failed to add new local vector element to SEM [1]"); + + parser_->sem_.free_element(nse); + + result = error_node(); + } + + exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n",nse.name.c_str())); + + parser_->state_.activate_side_effect("vector_element()"); + + result = nse.var_node; + } + } + else if (vector_base->rebaseable()) + result = node_allocator_->allocate(index,vector_base); + else + result = node_allocator_->allocate(index,vector_base); + + return result; + } + + private: + + template + inline bool is_constant_foldable(NodePtr (&b)[N]) const + { + for (std::size_t i = 0; i < N; ++i) + { + if (0 == b[i]) + return false; + else if (!details::is_constant_node(b[i])) + return false; + } + + return true; + } + + template class Sequence> + inline bool is_constant_foldable(const Sequence& b) const + { + for (std::size_t i = 0; i < b.size(); ++i) + { + if (0 == b[i]) + return false; + else if (!details::is_constant_node(b[i])) + return false; + } + + return true; + } + + void lodge_assignment(symbol_type cst, expression_node_ptr node) + { + parser_->state_.activate_side_effect("lodge_assignment()"); + + if (!parser_->dec_.collect_assignments()) + return; + + std::string symbol_name; + + switch (cst) + { + case e_st_variable : symbol_name = parser_->symtab_store_ + .get_variable_name(node); + break; + + #ifndef exprtk_disable_string_capabilities + case e_st_string : symbol_name = parser_->symtab_store_ + .get_stringvar_name(node); + break; + #endif + + case e_st_vector : { + typedef details::vector_holder vector_holder_t; + + vector_holder_t& vh = static_cast(node)->vec_holder(); + + symbol_name = parser_->symtab_store_.get_vector_name(&vh); + } + break; + + case e_st_vecelem : { + typedef details::vector_holder vector_holder_t; + + vector_holder_t& vh = static_cast(node)->vec_holder(); + + symbol_name = parser_->symtab_store_.get_vector_name(&vh); + + cst = e_st_vector; + } + break; + + default : return; + } + + if (!symbol_name.empty()) + { + parser_->dec_.add_assignment(symbol_name,cst); + } + } + + inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) + { + if (details::is_variable_node(branch[0])) + { + lodge_assignment(e_st_variable,branch[0]); + + return synthesize_expression(operation,branch); + } + else if (details::is_vector_elem_node(branch[0])) + { + lodge_assignment(e_st_vecelem,branch[0]); + + return synthesize_expression(operation, branch); + } + else if (details::is_rebasevector_elem_node(branch[0])) + { + lodge_assignment(e_st_vecelem,branch[0]); + + return synthesize_expression(operation, branch); + } + else if (details::is_rebasevector_celem_node(branch[0])) + { + lodge_assignment(e_st_vecelem,branch[0]); + + return synthesize_expression(operation, branch); + } + #ifndef exprtk_disable_string_capabilities + else if (details::is_string_node(branch[0])) + { + lodge_assignment(e_st_string,branch[0]); + + return synthesize_expression(operation, branch); + } + else if (details::is_string_range_node(branch[0])) + { + lodge_assignment(e_st_string,branch[0]); + + return synthesize_expression(operation, branch); + } + #endif + else if (details::is_vector_node(branch[0])) + { + lodge_assignment(e_st_vector,branch[0]); + + if (details::is_ivector_node(branch[1])) + return synthesize_expression(operation, branch); + else + return synthesize_expression(operation, branch); + } + else + { + parser_->set_synthesis_error("Invalid assignment operation.[1]"); + + return error_node(); + } + } + + inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + if (details::is_variable_node(branch[0])) + { + lodge_assignment(e_st_variable,branch[0]); + + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + template allocate_rrr > > \ + (operation, branch[0], branch[1]); \ + + case_stmt(details::e_addass,details::add_op) + case_stmt(details::e_subass,details::sub_op) + case_stmt(details::e_mulass,details::mul_op) + case_stmt(details::e_divass,details::div_op) + case_stmt(details::e_modass,details::mod_op) + #undef case_stmt + default : return error_node(); + } + } + else if (details::is_vector_elem_node(branch[0])) + { + lodge_assignment(e_st_vecelem,branch[0]); + + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + template allocate_rrr > > \ + (operation, branch[0], branch[1]); \ + + case_stmt(details::e_addass,details::add_op) + case_stmt(details::e_subass,details::sub_op) + case_stmt(details::e_mulass,details::mul_op) + case_stmt(details::e_divass,details::div_op) + case_stmt(details::e_modass,details::mod_op) + #undef case_stmt + default : return error_node(); + } + } + else if (details::is_rebasevector_elem_node(branch[0])) + { + lodge_assignment(e_st_vecelem,branch[0]); + + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + template allocate_rrr > > \ + (operation, branch[0], branch[1]); \ + + case_stmt(details::e_addass,details::add_op) + case_stmt(details::e_subass,details::sub_op) + case_stmt(details::e_mulass,details::mul_op) + case_stmt(details::e_divass,details::div_op) + case_stmt(details::e_modass,details::mod_op) + #undef case_stmt + default : return error_node(); + } + } + else if (details::is_rebasevector_celem_node(branch[0])) + { + lodge_assignment(e_st_vecelem,branch[0]); + + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + template allocate_rrr > > \ + (operation, branch[0], branch[1]); \ + + case_stmt(details::e_addass,details::add_op) + case_stmt(details::e_subass,details::sub_op) + case_stmt(details::e_mulass,details::mul_op) + case_stmt(details::e_divass,details::div_op) + case_stmt(details::e_modass,details::mod_op) + #undef case_stmt + default : return error_node(); + } + } + else if (details::is_vector_node(branch[0])) + { + lodge_assignment(e_st_vector,branch[0]); + + if (details::is_ivector_node(branch[1])) + { + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + template allocate_rrr > > \ + (operation, branch[0], branch[1]); \ + + case_stmt(details::e_addass,details::add_op) + case_stmt(details::e_subass,details::sub_op) + case_stmt(details::e_mulass,details::mul_op) + case_stmt(details::e_divass,details::div_op) + case_stmt(details::e_modass,details::mod_op) + #undef case_stmt + default : return error_node(); + } + } + else + { + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + template allocate_rrr > > \ + (operation, branch[0], branch[1]); \ + + case_stmt(details::e_addass,details::add_op) + case_stmt(details::e_subass,details::sub_op) + case_stmt(details::e_mulass,details::mul_op) + case_stmt(details::e_divass,details::div_op) + case_stmt(details::e_modass,details::mod_op) + #undef case_stmt + default : return error_node(); + } + } + } + #ifndef exprtk_disable_string_capabilities + else if ( + (details::e_addass == operation) && + details::is_string_node(branch[0]) + ) + { + typedef details::assignment_string_node addass_t; + + lodge_assignment(e_st_string,branch[0]); + + return synthesize_expression(operation,branch); + } + #endif + else + { + parser_->set_synthesis_error("Invalid assignment operation[2]"); + + return error_node(); + } + } + + inline expression_node_ptr synthesize_veceqineqlogic_operation_expression(const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + const bool is_b0_ivec = details::is_ivector_node(branch[0]); + const bool is_b1_ivec = details::is_ivector_node(branch[1]); + + #define batch_eqineq_logic_case \ + case_stmt(details:: e_lt, details:: lt_op) \ + case_stmt(details:: e_lte, details:: lte_op) \ + case_stmt(details:: e_gt, details:: gt_op) \ + case_stmt(details:: e_gte, details:: gte_op) \ + case_stmt(details:: e_eq, details:: eq_op) \ + case_stmt(details:: e_ne, details:: ne_op) \ + case_stmt(details::e_equal, details::equal_op) \ + case_stmt(details:: e_and, details:: and_op) \ + case_stmt(details:: e_nand, details:: nand_op) \ + case_stmt(details:: e_or, details:: or_op) \ + case_stmt(details:: e_nor, details:: nor_op) \ + case_stmt(details:: e_xor, details:: xor_op) \ + case_stmt(details:: e_xnor, details:: xnor_op) \ + + if (is_b0_ivec && is_b1_ivec) + { + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + template allocate_rrr > > \ + (operation, branch[0], branch[1]); \ + + batch_eqineq_logic_case + #undef case_stmt + default : return error_node(); + } + } + else if (is_b0_ivec && !is_b1_ivec) + { + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + template allocate_rrr > > \ + (operation, branch[0], branch[1]); \ + + batch_eqineq_logic_case + #undef case_stmt + default : return error_node(); + } + } + else if (!is_b0_ivec && is_b1_ivec) + { + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + template allocate_rrr > > \ + (operation, branch[0], branch[1]); \ + + batch_eqineq_logic_case + #undef case_stmt + default : return error_node(); + } + } + else + return error_node(); + + #undef batch_eqineq_logic_case + } + + inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + const bool is_b0_ivec = details::is_ivector_node(branch[0]); + const bool is_b1_ivec = details::is_ivector_node(branch[1]); + + #define vector_ops \ + case_stmt(details::e_add,details::add_op) \ + case_stmt(details::e_sub,details::sub_op) \ + case_stmt(details::e_mul,details::mul_op) \ + case_stmt(details::e_div,details::div_op) \ + case_stmt(details::e_mod,details::mod_op) \ + + if (is_b0_ivec && is_b1_ivec) + { + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + template allocate_rrr > > \ + (operation, branch[0], branch[1]); \ + + vector_ops + case_stmt(details::e_pow,details:: pow_op) + #undef case_stmt + default : return error_node(); + } + } + else if (is_b0_ivec && !is_b1_ivec) + { + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + template allocate_rrr > > \ + (operation, branch[0], branch[1]); \ + + vector_ops + case_stmt(details::e_pow,details:: pow_op) + #undef case_stmt + default : return error_node(); + } + } + else if (!is_b0_ivec && is_b1_ivec) + { + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + template allocate_rrr > > \ + (operation, branch[0], branch[1]); \ + + vector_ops + #undef case_stmt + default : return error_node(); + } + } + else + return error_node(); + + #undef vector_ops + } + + inline expression_node_ptr synthesize_swap_expression(expression_node_ptr (&branch)[2]) + { + const bool v0_is_ivar = details::is_ivariable_node(branch[0]); + const bool v1_is_ivar = details::is_ivariable_node(branch[1]); + + const bool v0_is_ivec = details::is_ivector_node (branch[0]); + const bool v1_is_ivec = details::is_ivector_node (branch[1]); + + #ifndef exprtk_disable_string_capabilities + const bool v0_is_str = details::is_generally_string_node(branch[0]); + const bool v1_is_str = details::is_generally_string_node(branch[1]); + #endif + + expression_node_ptr result = error_node(); + + if (v0_is_ivar && v1_is_ivar) + { + typedef details::variable_node* variable_node_ptr; + + variable_node_ptr v0 = variable_node_ptr(0); + variable_node_ptr v1 = variable_node_ptr(0); + + if ( + (0 != (v0 = dynamic_cast(branch[0]))) && + (0 != (v1 = dynamic_cast(branch[1]))) + ) + { + result = node_allocator_->allocate >(v0,v1); + } + else + result = node_allocator_->allocate >(branch[0],branch[1]); + } + else if (v0_is_ivec && v1_is_ivec) + { + result = node_allocator_->allocate >(branch[0],branch[1]); + } + #ifndef exprtk_disable_string_capabilities + else if (v0_is_str && v1_is_str) + { + if (is_string_node(branch[0]) && is_string_node(branch[1])) + result = node_allocator_->allocate > + (branch[0], branch[1]); + else + result = node_allocator_->allocate > + (branch[0], branch[1]); + } + #endif + else + { + parser_->set_synthesis_error("Only variables, strings, vectors or vector elements can be swapped"); + + return error_node(); + } + + parser_->state_.activate_side_effect("synthesize_swap_expression()"); + + return result; + } + + #ifndef exprtk_disable_sc_andor + inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) + { + expression_node_ptr result = error_node(); + + if (details::is_constant_node(branch[0])) + { + if ( + (details::e_scand == operation) && + std::equal_to()(T(0),branch[0]->value()) + ) + result = node_allocator_->allocate_c(T(0)); + else if ( + (details::e_scor == operation) && + std::not_equal_to()(T(0),branch[0]->value()) + ) + result = node_allocator_->allocate_c(T(1)); + } + + if (details::is_constant_node(branch[1]) && (0 == result)) + { + if ( + (details::e_scand == operation) && + std::equal_to()(T(0),branch[1]->value()) + ) + result = node_allocator_->allocate_c(T(0)); + else if ( + (details::e_scor == operation) && + std::not_equal_to()(T(0),branch[1]->value()) + ) + result = node_allocator_->allocate_c(T(1)); + } + + if (result) + { + free_node(*node_allocator_, branch[0]); + free_node(*node_allocator_, branch[1]); + + return result; + } + else if (details::e_scand == operation) + { + return synthesize_expression(operation, branch); + } + else if (details::e_scor == operation) + { + return synthesize_expression(operation, branch); + } + else + return error_node(); + } + #else + inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2]) + { + return error_node(); + } + #endif + + #define basic_opr_switch_statements \ + case_stmt(details::e_add, details::add_op) \ + case_stmt(details::e_sub, details::sub_op) \ + case_stmt(details::e_mul, details::mul_op) \ + case_stmt(details::e_div, details::div_op) \ + case_stmt(details::e_mod, details::mod_op) \ + case_stmt(details::e_pow, details::pow_op) \ + + #define extended_opr_switch_statements \ + case_stmt(details:: e_lt, details:: lt_op) \ + case_stmt(details:: e_lte, details:: lte_op) \ + case_stmt(details:: e_gt, details:: gt_op) \ + case_stmt(details:: e_gte, details:: gte_op) \ + case_stmt(details:: e_eq, details:: eq_op) \ + case_stmt(details:: e_ne, details:: ne_op) \ + case_stmt(details:: e_and, details:: and_op) \ + case_stmt(details::e_nand, details::nand_op) \ + case_stmt(details:: e_or, details:: or_op) \ + case_stmt(details:: e_nor, details:: nor_op) \ + case_stmt(details:: e_xor, details:: xor_op) \ + case_stmt(details::e_xnor, details::xnor_op) \ + + #ifndef exprtk_disable_cardinal_pow_optimisation + template class IPowNode> + inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& p) + { + switch (p) + { + #define case_stmt(cp) \ + case cp : return node_allocator_-> \ + allocate > >(v); \ + + case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4) + case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8) + case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12) + case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16) + case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20) + case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24) + case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28) + case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32) + case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36) + case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40) + case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44) + case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48) + case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52) + case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56) + case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60) + #undef case_stmt + default : return error_node(); + } + } + + inline expression_node_ptr cardinal_pow_optimisation(const T& v, const T& c) + { + const bool not_recipricol = (c >= T(0)); + const unsigned int p = static_cast(details::numeric::to_int32(details::numeric::abs(c))); + + if (0 == p) + return node_allocator_->allocate_c(T(1)); + else if (std::equal_to()(T(2),c)) + { + return node_allocator_-> + template allocate_rr > >(v,v); + } + else + { + if (not_recipricol) + return cardinal_pow_optimisation_impl(v,p); + else + return cardinal_pow_optimisation_impl(v,p); + } + } + + inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c) const + { + return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c); + } + + inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr (&branch)[2]) + { + const Type c = static_cast*>(branch[1])->value(); + const bool not_recipricol = (c >= T(0)); + const unsigned int p = static_cast(details::numeric::to_int32(details::numeric::abs(c))); + + node_allocator_->free(branch[1]); + + if (0 == p) + { + details::free_all_nodes(*node_allocator_, branch); + + return node_allocator_->allocate_c(T(1)); + } + else if (not_recipricol) + return cardinal_pow_optimisation_impl(branch[0],p); + else + return cardinal_pow_optimisation_impl(branch[0],p); + } + #else + inline expression_node_ptr cardinal_pow_optimisation(T&, const T&) + { + return error_node(); + } + + inline bool cardinal_pow_optimisable(const details::operator_type&, const T&) + { + return false; + } + + inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2]) + { + return error_node(); + } + #endif + + struct synthesize_binary_ext_expression + { + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + const bool left_neg = is_neg_unary_node(branch[0]); + const bool right_neg = is_neg_unary_node(branch[1]); + + if (left_neg && right_neg) + { + if ( + (details::e_add == operation) || + (details::e_sub == operation) || + (details::e_mul == operation) || + (details::e_div == operation) + ) + { + if ( + !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) || + !expr_gen.parser_->simplify_unary_negation_branch(branch[1]) + ) + { + details::free_all_nodes(*expr_gen.node_allocator_,branch); + + return error_node(); + } + } + + switch (operation) + { + // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1)) + case details::e_add : return expr_gen(details::e_neg, + expr_gen.node_allocator_-> + template allocate > > + (branch[0],branch[1])); + + // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1) + case details::e_sub : return expr_gen.node_allocator_-> + template allocate > > + (branch[1],branch[0]); + + default : break; + } + } + else if (left_neg && !right_neg) + { + if ( + (details::e_add == operation) || + (details::e_sub == operation) || + (details::e_mul == operation) || + (details::e_div == operation) + ) + { + if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0])) + { + details::free_all_nodes(*expr_gen.node_allocator_,branch); + + return error_node(); + } + + switch (operation) + { + // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1) + case details::e_add : return expr_gen.node_allocator_-> + template allocate > > + (branch[1], branch[0]); + + // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1)) + case details::e_sub : return expr_gen(details::e_neg, + expr_gen.node_allocator_-> + template allocate > > + (branch[0], branch[1])); + + // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1)) + case details::e_mul : return expr_gen(details::e_neg, + expr_gen.node_allocator_-> + template allocate > > + (branch[0], branch[1])); + + // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1)) + case details::e_div : return expr_gen(details::e_neg, + expr_gen.node_allocator_-> + template allocate > > + (branch[0], branch[1])); + + default : return error_node(); + } + } + } + else if (!left_neg && right_neg) + { + if ( + (details::e_add == operation) || + (details::e_sub == operation) || + (details::e_mul == operation) || + (details::e_div == operation) + ) + { + if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1])) + { + details::free_all_nodes(*expr_gen.node_allocator_,branch); + + return error_node(); + } + + switch (operation) + { + // f(x + 1) + -g(y + 1) --> f(x + 1) - g(y + 1) + case details::e_add : return expr_gen.node_allocator_-> + template allocate > > + (branch[0], branch[1]); + + // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1) + case details::e_sub : return expr_gen.node_allocator_-> + template allocate > > + (branch[0], branch[1]); + + // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1)) + case details::e_mul : return expr_gen(details::e_neg, + expr_gen.node_allocator_-> + template allocate > > + (branch[0], branch[1])); + + // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1)) + case details::e_div : return expr_gen(details::e_neg, + expr_gen.node_allocator_-> + template allocate > > + (branch[0], branch[1])); + + default : return error_node(); + } + } + } + + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : return expr_gen.node_allocator_-> \ + template allocate > > \ + (branch[0], branch[1]); \ + + basic_opr_switch_statements + extended_opr_switch_statements + #undef case_stmt + default : return error_node(); + } + } + }; + + struct synthesize_vob_expression + { + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + const Type& v = static_cast*>(branch[0])->ref(); + + #ifndef exprtk_disable_enhanced_features + if (details::is_sf3ext_node(branch[1])) + { + expression_node_ptr result = error_node(); + + const bool synthesis_result = synthesize_sf4ext_expression::template compile_right + (expr_gen, v, operation, branch[1], result); + + if (synthesis_result) + { + free_node(*expr_gen.node_allocator_,branch[1]); + return result; + } + } + #endif + + if ( + (details::e_mul == operation) || + (details::e_div == operation) + ) + { + if (details::is_uv_node(branch[1])) + { + typedef details::uv_base_node* uvbn_ptr_t; + + details::operator_type o = static_cast(branch[1])->operation(); + + if (details::e_neg == o) + { + const Type& v1 = static_cast(branch[1])->v(); + + free_node(*expr_gen.node_allocator_,branch[1]); + + switch (operation) + { + case details::e_mul : return expr_gen(details::e_neg, + expr_gen.node_allocator_-> + template allocate_rr > >(v,v1)); + + case details::e_div : return expr_gen(details::e_neg, + expr_gen.node_allocator_-> + template allocate_rr > >(v,v1)); + + default : break; + } + } + } + } + + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : return expr_gen.node_allocator_-> \ + template allocate_rc > > \ + (v, branch[1]); \ + + basic_opr_switch_statements + extended_opr_switch_statements + #undef case_stmt + default : return error_node(); + } + } + }; + + struct synthesize_bov_expression + { + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + const Type& v = static_cast*>(branch[1])->ref(); + + #ifndef exprtk_disable_enhanced_features + if (details::is_sf3ext_node(branch[0])) + { + expression_node_ptr result = error_node(); + + const bool synthesis_result = synthesize_sf4ext_expression::template compile_left + (expr_gen, v, operation, branch[0], result); + + if (synthesis_result) + { + free_node(*expr_gen.node_allocator_, branch[0]); + + return result; + } + } + #endif + + if ( + (details::e_add == operation) || + (details::e_sub == operation) || + (details::e_mul == operation) || + (details::e_div == operation) + ) + { + if (details::is_uv_node(branch[0])) + { + typedef details::uv_base_node* uvbn_ptr_t; + + details::operator_type o = static_cast(branch[0])->operation(); + + if (details::e_neg == o) + { + const Type& v0 = static_cast(branch[0])->v(); + + free_node(*expr_gen.node_allocator_,branch[0]); + + switch (operation) + { + case details::e_add : return expr_gen.node_allocator_-> + template allocate_rr > >(v,v0); + + case details::e_sub : return expr_gen(details::e_neg, + expr_gen.node_allocator_-> + template allocate_rr > >(v0,v)); + + case details::e_mul : return expr_gen(details::e_neg, + expr_gen.node_allocator_-> + template allocate_rr > >(v0,v)); + + case details::e_div : return expr_gen(details::e_neg, + expr_gen.node_allocator_-> + template allocate_rr > >(v0,v)); + default : break; + } + } + } + } + + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : return expr_gen.node_allocator_-> \ + template allocate_cr > > \ + (branch[0], v); \ + + basic_opr_switch_statements + extended_opr_switch_statements + #undef case_stmt + default : return error_node(); + } + } + }; + + struct synthesize_cob_expression + { + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + const Type c = static_cast*>(branch[0])->value(); + + free_node(*expr_gen.node_allocator_,branch[0]); + + if (std::equal_to()(T(0),c) && (details::e_mul == operation)) + { + free_node(*expr_gen.node_allocator_,branch[1]); + + return expr_gen(T(0)); + } + else if (std::equal_to()(T(0),c) && (details::e_div == operation)) + { + free_node(*expr_gen.node_allocator_, branch[1]); + + return expr_gen(T(0)); + } + else if (std::equal_to()(T(0),c) && (details::e_add == operation)) + return branch[1]; + else if (std::equal_to()(T(1),c) && (details::e_mul == operation)) + return branch[1]; + + if (details::is_cob_node(branch[1])) + { + // Simplify expressions of the form: + // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x) + // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x + if ( + (operation == details::e_mul) || + (operation == details::e_add) + ) + { + details::cob_base_node* cobnode = static_cast*>(branch[1]); + + if (operation == cobnode->operation()) + { + switch (operation) + { + case details::e_add : cobnode->set_c(c + cobnode->c()); break; + case details::e_mul : cobnode->set_c(c * cobnode->c()); break; + default : return error_node(); + } + + return cobnode; + } + } + + if (operation == details::e_mul) + { + details::cob_base_node* cobnode = static_cast*>(branch[1]); + details::operator_type cob_opr = cobnode->operation(); + + if ( + (details::e_div == cob_opr) || + (details::e_mul == cob_opr) + ) + { + switch (cob_opr) + { + case details::e_div : cobnode->set_c(c * cobnode->c()); break; + case details::e_mul : cobnode->set_c(cobnode->c() / c); break; + default : return error_node(); + } + + return cobnode; + } + } + else if (operation == details::e_div) + { + details::cob_base_node* cobnode = static_cast*>(branch[1]); + details::operator_type cob_opr = cobnode->operation(); + + if ( + (details::e_div == cob_opr) || + (details::e_mul == cob_opr) + ) + { + details::expression_node* new_cobnode = error_node(); + + switch (cob_opr) + { + case details::e_div : new_cobnode = expr_gen.node_allocator_-> + template allocate_tt > > + (c / cobnode->c(), cobnode->move_branch(0)); + break; + + case details::e_mul : new_cobnode = expr_gen.node_allocator_-> + template allocate_tt > > + (c / cobnode->c(), cobnode->move_branch(0)); + break; + + default : return error_node(); + } + + free_node(*expr_gen.node_allocator_,branch[1]); + + return new_cobnode; + } + } + } + #ifndef exprtk_disable_enhanced_features + else if (details::is_sf3ext_node(branch[1])) + { + expression_node_ptr result = error_node(); + + if (synthesize_sf4ext_expression::template compile_right(expr_gen,c,operation,branch[1],result)) + { + free_node(*expr_gen.node_allocator_,branch[1]); + + return result; + } + } + #endif + + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : return expr_gen.node_allocator_-> \ + template allocate_tt > > \ + (c, branch[1]); \ + + basic_opr_switch_statements + extended_opr_switch_statements + #undef case_stmt + default : return error_node(); + } + } + }; + + struct synthesize_boc_expression + { + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + const Type c = static_cast*>(branch[1])->value(); + + details::free_node(*(expr_gen.node_allocator_), branch[1]); + + if (std::equal_to()(T(0),c) && (details::e_mul == operation)) + { + free_node(*expr_gen.node_allocator_, branch[0]); + + return expr_gen(T(0)); + } + else if (std::equal_to()(T(0),c) && (details::e_div == operation)) + { + free_node(*expr_gen.node_allocator_, branch[0]); + + return expr_gen(std::numeric_limits::quiet_NaN()); + } + else if (std::equal_to()(T(0),c) && (details::e_add == operation)) + return branch[0]; + else if (std::equal_to()(T(1),c) && (details::e_mul == operation)) + return branch[0]; + + if (details::is_boc_node(branch[0])) + { + // Simplify expressions of the form: + // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320 + // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45 + if ( + (operation == details::e_mul) || + (operation == details::e_add) + ) + { + details::boc_base_node* bocnode = static_cast*>(branch[0]); + + if (operation == bocnode->operation()) + { + switch (operation) + { + case details::e_add : bocnode->set_c(c + bocnode->c()); break; + case details::e_mul : bocnode->set_c(c * bocnode->c()); break; + default : return error_node(); + } + + return bocnode; + } + } + else if (operation == details::e_div) + { + details::boc_base_node* bocnode = static_cast*>(branch[0]); + details::operator_type boc_opr = bocnode->operation(); + + if ( + (details::e_div == boc_opr) || + (details::e_mul == boc_opr) + ) + { + switch (boc_opr) + { + case details::e_div : bocnode->set_c(c * bocnode->c()); break; + case details::e_mul : bocnode->set_c(bocnode->c() / c); break; + default : return error_node(); + } + + return bocnode; + } + } + else if (operation == details::e_pow) + { + // (v ^ c0) ^ c1 --> v ^(c0 * c1) + details::boc_base_node* bocnode = static_cast*>(branch[0]); + details::operator_type boc_opr = bocnode->operation(); + + if (details::e_pow == boc_opr) + { + bocnode->set_c(bocnode->c() * c); + + return bocnode; + } + } + } + + #ifndef exprtk_disable_enhanced_features + if (details::is_sf3ext_node(branch[0])) + { + expression_node_ptr result = error_node(); + + const bool synthesis_result = synthesize_sf4ext_expression::template compile_left + (expr_gen, c, operation, branch[0], result); + + if (synthesis_result) + { + free_node(*expr_gen.node_allocator_, branch[0]); + + return result; + } + } + #endif + + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : return expr_gen.node_allocator_-> \ + template allocate_cr > > \ + (branch[0], c); \ + + basic_opr_switch_statements + extended_opr_switch_statements + #undef case_stmt + default : return error_node(); + } + } + }; + + struct synthesize_cocob_expression + { + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + expression_node_ptr result = error_node(); + + // (cob) o c --> cob + if (details::is_cob_node(branch[0])) + { + details::cob_base_node* cobnode = static_cast*>(branch[0]); + + const Type c = static_cast*>(branch[1])->value(); + + if (std::equal_to()(T(0),c) && (details::e_mul == operation)) + { + free_node(*expr_gen.node_allocator_, branch[0]); + free_node(*expr_gen.node_allocator_, branch[1]); + + return expr_gen(T(0)); + } + else if (std::equal_to()(T(0),c) && (details::e_div == operation)) + { + free_node(*expr_gen.node_allocator_, branch[0]); + free_node(*expr_gen.node_allocator_, branch[1]); + + return expr_gen(T(std::numeric_limits::quiet_NaN())); + } + else if (std::equal_to()(T(0),c) && (details::e_add == operation)) + { + free_node(*expr_gen.node_allocator_, branch[1]); + + return branch[0]; + } + else if (std::equal_to()(T(1),c) && (details::e_mul == operation)) + { + free_node(*expr_gen.node_allocator_, branch[1]); + + return branch[0]; + } + else if (std::equal_to()(T(1),c) && (details::e_div == operation)) + { + free_node(*expr_gen.node_allocator_, branch[1]); + + return branch[0]; + } + + const bool op_addsub = (details::e_add == cobnode->operation()) || + (details::e_sub == cobnode->operation()) ; + + if (op_addsub) + { + switch (operation) + { + case details::e_add : cobnode->set_c(cobnode->c() + c); break; + case details::e_sub : cobnode->set_c(cobnode->c() - c); break; + default : return error_node(); + } + + result = cobnode; + } + else if (details::e_mul == cobnode->operation()) + { + switch (operation) + { + case details::e_mul : cobnode->set_c(cobnode->c() * c); break; + case details::e_div : cobnode->set_c(cobnode->c() / c); break; + default : return error_node(); + } + + result = cobnode; + } + else if (details::e_div == cobnode->operation()) + { + if (details::e_mul == operation) + { + cobnode->set_c(cobnode->c() * c); + result = cobnode; + } + else if (details::e_div == operation) + { + result = expr_gen.node_allocator_-> + template allocate_tt > > + (cobnode->c() / c, cobnode->move_branch(0)); + + free_node(*expr_gen.node_allocator_, branch[0]); + } + } + + if (result) + { + free_node(*expr_gen.node_allocator_,branch[1]); + } + } + + // c o (cob) --> cob + else if (details::is_cob_node(branch[1])) + { + details::cob_base_node* cobnode = static_cast*>(branch[1]); + + const Type c = static_cast*>(branch[0])->value(); + + if (std::equal_to()(T(0),c) && (details::e_mul == operation)) + { + free_node(*expr_gen.node_allocator_, branch[0]); + free_node(*expr_gen.node_allocator_, branch[1]); + + return expr_gen(T(0)); + } + else if (std::equal_to()(T(0),c) && (details::e_div == operation)) + { + free_node(*expr_gen.node_allocator_, branch[0]); + free_node(*expr_gen.node_allocator_, branch[1]); + + return expr_gen(T(0)); + } + else if (std::equal_to()(T(0),c) && (details::e_add == operation)) + { + free_node(*expr_gen.node_allocator_, branch[0]); + + return branch[1]; + } + else if (std::equal_to()(T(1),c) && (details::e_mul == operation)) + { + free_node(*expr_gen.node_allocator_, branch[0]); + + return branch[1]; + } + + if (details::e_add == cobnode->operation()) + { + if (details::e_add == operation) + { + cobnode->set_c(c + cobnode->c()); + result = cobnode; + } + else if (details::e_sub == operation) + { + result = expr_gen.node_allocator_-> + template allocate_tt > > + (c - cobnode->c(), cobnode->move_branch(0)); + + free_node(*expr_gen.node_allocator_,branch[1]); + } + } + else if (details::e_sub == cobnode->operation()) + { + if (details::e_add == operation) + { + cobnode->set_c(c + cobnode->c()); + result = cobnode; + } + else if (details::e_sub == operation) + { + result = expr_gen.node_allocator_-> + template allocate_tt > > + (c - cobnode->c(), cobnode->move_branch(0)); + + free_node(*expr_gen.node_allocator_,branch[1]); + } + } + else if (details::e_mul == cobnode->operation()) + { + if (details::e_mul == operation) + { + cobnode->set_c(c * cobnode->c()); + result = cobnode; + } + else if (details::e_div == operation) + { + result = expr_gen.node_allocator_-> + template allocate_tt > > + (c / cobnode->c(), cobnode->move_branch(0)); + + free_node(*expr_gen.node_allocator_,branch[1]); + } + } + else if (details::e_div == cobnode->operation()) + { + if (details::e_mul == operation) + { + cobnode->set_c(c * cobnode->c()); + result = cobnode; + } + else if (details::e_div == operation) + { + result = expr_gen.node_allocator_-> + template allocate_tt > > + (c / cobnode->c(), cobnode->move_branch(0)); + + free_node(*expr_gen.node_allocator_,branch[1]); + } + } + + if (result) + { + free_node(*expr_gen.node_allocator_,branch[0]); + } + } + + return result; + } + }; + + struct synthesize_coboc_expression + { + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + expression_node_ptr result = error_node(); + + // (boc) o c --> boc + if (details::is_boc_node(branch[0])) + { + details::boc_base_node* bocnode = static_cast*>(branch[0]); + + const Type c = static_cast*>(branch[1])->value(); + + if (details::e_add == bocnode->operation()) + { + switch (operation) + { + case details::e_add : bocnode->set_c(bocnode->c() + c); break; + case details::e_sub : bocnode->set_c(bocnode->c() - c); break; + default : return error_node(); + } + + result = bocnode; + } + else if (details::e_mul == bocnode->operation()) + { + switch (operation) + { + case details::e_mul : bocnode->set_c(bocnode->c() * c); break; + case details::e_div : bocnode->set_c(bocnode->c() / c); break; + default : return error_node(); + } + + result = bocnode; + } + else if (details::e_sub == bocnode->operation()) + { + if (details::e_add == operation) + { + result = expr_gen.node_allocator_-> + template allocate_tt > > + (bocnode->move_branch(0), c - bocnode->c()); + + free_node(*expr_gen.node_allocator_,branch[0]); + } + else if (details::e_sub == operation) + { + bocnode->set_c(bocnode->c() + c); + result = bocnode; + } + } + else if (details::e_div == bocnode->operation()) + { + switch (operation) + { + case details::e_div : bocnode->set_c(bocnode->c() * c); break; + case details::e_mul : bocnode->set_c(bocnode->c() / c); break; + default : return error_node(); + } + + result = bocnode; + } + + if (result) + { + free_node(*expr_gen.node_allocator_, branch[1]); + } + } + + // c o (boc) --> boc + else if (details::is_boc_node(branch[1])) + { + details::boc_base_node* bocnode = static_cast*>(branch[1]); + + const Type c = static_cast*>(branch[0])->value(); + + if (details::e_add == bocnode->operation()) + { + if (details::e_add == operation) + { + bocnode->set_c(c + bocnode->c()); + result = bocnode; + } + else if (details::e_sub == operation) + { + result = expr_gen.node_allocator_-> + template allocate_tt > > + (c - bocnode->c(), bocnode->move_branch(0)); + + free_node(*expr_gen.node_allocator_,branch[1]); + } + } + else if (details::e_sub == bocnode->operation()) + { + if (details::e_add == operation) + { + result = expr_gen.node_allocator_-> + template allocate_tt > > + (bocnode->move_branch(0), c - bocnode->c()); + + free_node(*expr_gen.node_allocator_,branch[1]); + } + else if (details::e_sub == operation) + { + result = expr_gen.node_allocator_-> + template allocate_tt > > + (c + bocnode->c(), bocnode->move_branch(0)); + + free_node(*expr_gen.node_allocator_,branch[1]); + } + } + else if (details::e_mul == bocnode->operation()) + { + if (details::e_mul == operation) + { + bocnode->set_c(c * bocnode->c()); + result = bocnode; + } + else if (details::e_div == operation) + { + result = expr_gen.node_allocator_-> + template allocate_tt > > + (c / bocnode->c(), bocnode->move_branch(0)); + + free_node(*expr_gen.node_allocator_,branch[1]); + } + } + else if (details::e_div == bocnode->operation()) + { + if (details::e_mul == operation) + { + bocnode->set_c(bocnode->c() / c); + result = bocnode; + } + else if (details::e_div == operation) + { + result = expr_gen.node_allocator_-> + template allocate_tt > > + (c * bocnode->c(), bocnode->move_branch(0)); + + free_node(*expr_gen.node_allocator_,branch[1]); + } + } + + if (result) + { + free_node(*expr_gen.node_allocator_,branch[0]); + } + } + + return result; + } + }; + + #ifndef exprtk_disable_enhanced_features + inline bool synthesize_expression(const details::operator_type& operation, + expression_node_ptr (&branch)[2], + expression_node_ptr& result) + { + result = error_node(); + + if (!operation_optimisable(operation)) + return false; + + const std::string node_id = branch_to_id(branch); + + const typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id); + + if (synthesize_map_.end() != itr) + { + result = itr->second((*this), operation, branch); + + return true; + } + else + return false; + } + + struct synthesize_vov_expression + { + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + const Type& v1 = static_cast*>(branch[0])->ref(); + const Type& v2 = static_cast*>(branch[1])->ref(); + + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : return expr_gen.node_allocator_-> \ + template allocate_rr > > \ + (v1, v2); \ + + basic_opr_switch_statements + extended_opr_switch_statements + #undef case_stmt + default : return error_node(); + } + } + }; + + struct synthesize_cov_expression + { + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + const Type c = static_cast*> (branch[0])->value(); + const Type& v = static_cast*>(branch[1])->ref (); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + + if (std::equal_to()(T(0),c) && (details::e_mul == operation)) + return expr_gen(T(0)); + else if (std::equal_to()(T(0),c) && (details::e_div == operation)) + return expr_gen(T(0)); + else if (std::equal_to()(T(0),c) && (details::e_add == operation)) + return static_cast*>(branch[1]); + else if (std::equal_to()(T(1),c) && (details::e_mul == operation)) + return static_cast*>(branch[1]); + + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : return expr_gen.node_allocator_-> \ + template allocate_cr > > \ + (c, v); \ + + basic_opr_switch_statements + extended_opr_switch_statements + #undef case_stmt + default : return error_node(); + } + } + }; + + struct synthesize_voc_expression + { + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + const Type& v = static_cast*>(branch[0])->ref (); + const Type c = static_cast*> (branch[1])->value(); + + details::free_node(*(expr_gen.node_allocator_), branch[1]); + + if (expr_gen.cardinal_pow_optimisable(operation,c)) + { + if (std::equal_to()(T(1),c)) + return branch[0]; + else + return expr_gen.cardinal_pow_optimisation(v,c); + } + else if (std::equal_to()(T(0),c) && (details::e_mul == operation)) + return expr_gen(T(0)); + else if (std::equal_to()(T(0),c) && (details::e_div == operation)) + return expr_gen(std::numeric_limits::quiet_NaN()); + else if (std::equal_to()(T(0),c) && (details::e_add == operation)) + return static_cast*>(branch[0]); + else if (std::equal_to()(T(1),c) && (details::e_mul == operation)) + return static_cast*>(branch[0]); + else if (std::equal_to()(T(1),c) && (details::e_div == operation)) + return static_cast*>(branch[0]); + + switch (operation) + { + #define case_stmt(op0,op1) \ + case op0 : return expr_gen.node_allocator_-> \ + template allocate_rc > > \ + (v, c); \ + + basic_opr_switch_statements + extended_opr_switch_statements + #undef case_stmt + default : return error_node(); + } + } + }; + + struct synthesize_sf3ext_expression + { + template + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& sf3opr, + T0 t0, T1 t1, T2 t2) + { + switch (sf3opr) + { + #define case_stmt(op) \ + case details::e_sf##op : return details::T0oT1oT2_sf3ext >:: \ + allocate(*(expr_gen.node_allocator_), t0, t1, t2); \ + + case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) + case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) + case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) + case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) + case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) + case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) + case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) + case_stmt(28) case_stmt(29) case_stmt(30) + #undef case_stmt + default : return error_node(); + } + } + + template + static inline bool compile(expression_generator& expr_gen, const std::string& id, + T0 t0, T1 t1, T2 t2, + expression_node_ptr& result) + { + details::operator_type sf3opr; + + if (!expr_gen.sf3_optimisable(id,sf3opr)) + return false; + else + result = synthesize_sf3ext_expression::template process + (expr_gen, sf3opr, t0, t1, t2); + + return true; + } + }; + + struct synthesize_sf4ext_expression + { + template + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& sf4opr, + T0 t0, T1 t1, T2 t2, T3 t3) + { + switch (sf4opr) + { + #define case_stmt0(op) \ + case details::e_sf##op : return details::T0oT1oT2oT3_sf4ext >:: \ + allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \ + + + #define case_stmt1(op) \ + case details::e_sf4ext##op : return details::T0oT1oT2oT3_sf4ext >:: \ + allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \ + + case_stmt0(48) case_stmt0(49) case_stmt0(50) case_stmt0(51) + case_stmt0(52) case_stmt0(53) case_stmt0(54) case_stmt0(55) + case_stmt0(56) case_stmt0(57) case_stmt0(58) case_stmt0(59) + case_stmt0(60) case_stmt0(61) case_stmt0(62) case_stmt0(63) + case_stmt0(64) case_stmt0(65) case_stmt0(66) case_stmt0(67) + case_stmt0(68) case_stmt0(69) case_stmt0(70) case_stmt0(71) + case_stmt0(72) case_stmt0(73) case_stmt0(74) case_stmt0(75) + case_stmt0(76) case_stmt0(77) case_stmt0(78) case_stmt0(79) + case_stmt0(80) case_stmt0(81) case_stmt0(82) case_stmt0(83) + + case_stmt1(00) case_stmt1(01) case_stmt1(02) case_stmt1(03) + case_stmt1(04) case_stmt1(05) case_stmt1(06) case_stmt1(07) + case_stmt1(08) case_stmt1(09) case_stmt1(10) case_stmt1(11) + case_stmt1(12) case_stmt1(13) case_stmt1(14) case_stmt1(15) + case_stmt1(16) case_stmt1(17) case_stmt1(18) case_stmt1(19) + case_stmt1(20) case_stmt1(21) case_stmt1(22) case_stmt1(23) + case_stmt1(24) case_stmt1(25) case_stmt1(26) case_stmt1(27) + case_stmt1(28) case_stmt1(29) case_stmt1(30) case_stmt1(31) + case_stmt1(32) case_stmt1(33) case_stmt1(34) case_stmt1(35) + case_stmt1(36) case_stmt1(37) case_stmt1(38) case_stmt1(39) + case_stmt1(40) case_stmt1(41) case_stmt1(42) case_stmt1(43) + case_stmt1(44) case_stmt1(45) case_stmt1(46) case_stmt1(47) + case_stmt1(48) case_stmt1(49) case_stmt1(50) case_stmt1(51) + case_stmt1(52) case_stmt1(53) case_stmt1(54) case_stmt1(55) + case_stmt1(56) case_stmt1(57) case_stmt1(58) case_stmt1(59) + case_stmt1(60) case_stmt1(61) + + #undef case_stmt0 + #undef case_stmt1 + default : return error_node(); + } + } + + template + static inline bool compile(expression_generator& expr_gen, const std::string& id, + T0 t0, T1 t1, T2 t2, T3 t3, + expression_node_ptr& result) + { + details::operator_type sf4opr; + + if (!expr_gen.sf4_optimisable(id,sf4opr)) + return false; + else + result = synthesize_sf4ext_expression::template process + (expr_gen, sf4opr, t0, t1, t2, t3); + + return true; + } + + // T o (sf3ext) + template + static inline bool compile_right(expression_generator& expr_gen, + ExternalType t, + const details::operator_type& operation, + expression_node_ptr& sf3node, + expression_node_ptr& result) + { + if (!details::is_sf3ext_node(sf3node)) + return false; + + typedef details::T0oT1oT2_base_node* sf3ext_base_ptr; + + sf3ext_base_ptr n = static_cast(sf3node); + const std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")"; + + switch (n->type()) + { + case details::expression_node::e_covoc : return compile_right_impl + + (expr_gen, id, t, sf3node, result); + + case details::expression_node::e_covov : return compile_right_impl + + (expr_gen, id, t, sf3node, result); + + case details::expression_node::e_vocov : return compile_right_impl + + (expr_gen, id, t, sf3node, result); + + case details::expression_node::e_vovoc : return compile_right_impl + + (expr_gen, id, t, sf3node, result); + + case details::expression_node::e_vovov : return compile_right_impl + + (expr_gen, id, t, sf3node, result); + + default : return false; + } + } + + // (sf3ext) o T + template + static inline bool compile_left(expression_generator& expr_gen, + ExternalType t, + const details::operator_type& operation, + expression_node_ptr& sf3node, + expression_node_ptr& result) + { + if (!details::is_sf3ext_node(sf3node)) + return false; + + typedef details::T0oT1oT2_base_node* sf3ext_base_ptr; + + sf3ext_base_ptr n = static_cast(sf3node); + + const std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t"; + + switch (n->type()) + { + case details::expression_node::e_covoc : return compile_left_impl + + (expr_gen, id, t, sf3node, result); + + case details::expression_node::e_covov : return compile_left_impl + + (expr_gen, id, t, sf3node, result); + + case details::expression_node::e_vocov : return compile_left_impl + + (expr_gen, id, t, sf3node, result); + + case details::expression_node::e_vovoc : return compile_left_impl + + (expr_gen, id, t, sf3node, result); + + case details::expression_node::e_vovov : return compile_left_impl + + (expr_gen, id, t, sf3node, result); + + default : return false; + } + } + + template + static inline bool compile_right_impl(expression_generator& expr_gen, + const std::string& id, + ExternalType t, + expression_node_ptr& node, + expression_node_ptr& result) + { + SF3TypeNode* n = dynamic_cast(node); + + if (n) + { + T0 t0 = n->t0(); + T1 t1 = n->t1(); + T2 t2 = n->t2(); + + return synthesize_sf4ext_expression::template compile + (expr_gen, id, t, t0, t1, t2, result); + } + else + return false; + } + + template + static inline bool compile_left_impl(expression_generator& expr_gen, + const std::string& id, + ExternalType t, + expression_node_ptr& node, + expression_node_ptr& result) + { + SF3TypeNode* n = dynamic_cast(node); + + if (n) + { + T0 t0 = n->t0(); + T1 t1 = n->t1(); + T2 t2 = n->t2(); + + return synthesize_sf4ext_expression::template compile + (expr_gen, id, t0, t1, t2, t, result); + } + else + return false; + } + }; + + struct synthesize_vovov_expression0 + { + typedef typename vovov_t::type0 node_type; + typedef typename vovov_t::sf3_type sf3_type; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // (v0 o0 v1) o1 (v2) + const details::vov_base_node* vov = static_cast*>(branch[0]); + const Type& v0 = vov->v0(); + const Type& v1 = vov->v1(); + const Type& v2 = static_cast*>(branch[1])->ref(); + const details::operator_type o0 = vov->operation(); + const details::operator_type o1 = operation; + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + + expression_node_ptr result = error_node(); + + if (expr_gen.parser_->settings_.strength_reduction_enabled()) + { + // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2) + if ((details::e_div == o0) && (details::e_div == o1)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "t/(t*t)", v0, v1, v2, result); + + exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n")); + + return (synthesis_result) ? result : error_node(); + } + } + + const bool synthesis_result = + synthesize_sf3ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + else if (!expr_gen.valid_operator(o1,f1)) + return error_node(); + else + return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, const details::operator_type o1) + { + return details::build_string() + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t"; + } + }; + + struct synthesize_vovov_expression1 + { + typedef typename vovov_t::type1 node_type; + typedef typename vovov_t::sf3_type sf3_type; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // (v0) o0 (v1 o1 v2) + const details::vov_base_node* vov = static_cast*>(branch[1]); + const Type& v0 = static_cast*>(branch[0])->ref(); + const Type& v1 = vov->v0(); + const Type& v2 = vov->v1(); + const details::operator_type o0 = operation; + const details::operator_type o1 = vov->operation(); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + if (expr_gen.parser_->settings_.strength_reduction_enabled()) + { + // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1 + if ((details::e_div == o0) && (details::e_div == o1)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t*t)/t", v0, v2, v1, result); + + exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n")); + + return (synthesis_result) ? result : error_node(); + } + } + + const bool synthesis_result = + synthesize_sf3ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + else if (!expr_gen.valid_operator(o1,f1)) + return error_node(); + else + return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, const details::operator_type o1) + { + return details::build_string() + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)"; + } + }; + + struct synthesize_vovoc_expression0 + { + typedef typename vovoc_t::type0 node_type; + typedef typename vovoc_t::sf3_type sf3_type; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // (v0 o0 v1) o1 (c) + const details::vov_base_node* vov = static_cast*>(branch[0]); + const Type& v0 = vov->v0(); + const Type& v1 = vov->v1(); + const Type c = static_cast*>(branch[1])->value(); + const details::operator_type o0 = vov->operation(); + const details::operator_type o1 = operation; + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + if (expr_gen.parser_->settings_.strength_reduction_enabled()) + { + // (v0 / v1) / c --> (vovoc) v0 / (v1 * c) + if ((details::e_div == o0) && (details::e_div == o1)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "t/(t*t)", v0, v1, c, result); + + exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n")); + + return (synthesis_result) ? result : error_node(); + } + } + + const bool synthesis_result = + synthesize_sf3ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + else if (!expr_gen.valid_operator(o1,f1)) + return error_node(); + else + return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, const details::operator_type o1) + { + return details::build_string() + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t"; + } + }; + + struct synthesize_vovoc_expression1 + { + typedef typename vovoc_t::type1 node_type; + typedef typename vovoc_t::sf3_type sf3_type; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // (v0) o0 (v1 o1 c) + const details::voc_base_node* voc = static_cast*>(branch[1]); + const Type& v0 = static_cast*>(branch[0])->ref(); + const Type& v1 = voc->v(); + const Type c = voc->c(); + const details::operator_type o0 = operation; + const details::operator_type o1 = voc->operation(); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + if (expr_gen.parser_->settings_.strength_reduction_enabled()) + { + // v0 / (v1 / c) --> (vocov) (v0 * c) / v1 + if ((details::e_div == o0) && (details::e_div == o1)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t*t)/t", v0, c, v1, result); + + exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n")); + + return (synthesis_result) ? result : error_node(); + } + } + + const bool synthesis_result = + synthesize_sf3ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + else if (!expr_gen.valid_operator(o1,f1)) + return error_node(); + else + return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, const details::operator_type o1) + { + return details::build_string() + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)"; + } + }; + + struct synthesize_vocov_expression0 + { + typedef typename vocov_t::type0 node_type; + typedef typename vocov_t::sf3_type sf3_type; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // (v0 o0 c) o1 (v1) + const details::voc_base_node* voc = static_cast*>(branch[0]); + const Type& v0 = voc->v(); + const Type c = voc->c(); + const Type& v1 = static_cast*>(branch[1])->ref(); + const details::operator_type o0 = voc->operation(); + const details::operator_type o1 = operation; + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + + expression_node_ptr result = error_node(); + + if (expr_gen.parser_->settings_.strength_reduction_enabled()) + { + // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c) + if ((details::e_div == o0) && (details::e_div == o1)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "t/(t*t)", v0, v1, c, result); + + exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n")); + + return (synthesis_result) ? result : error_node(); + } + } + + const bool synthesis_result = + synthesize_sf3ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + else if (!expr_gen.valid_operator(o1,f1)) + return error_node(); + else + return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, const details::operator_type o1) + { + return details::build_string() + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t"; + } + }; + + struct synthesize_vocov_expression1 + { + typedef typename vocov_t::type1 node_type; + typedef typename vocov_t::sf3_type sf3_type; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // (v0) o0 (c o1 v1) + const details::cov_base_node* cov = static_cast*>(branch[1]); + const Type& v0 = static_cast*>(branch[0])->ref(); + const Type c = cov->c(); + const Type& v1 = cov->v(); + const details::operator_type o0 = operation; + const details::operator_type o1 = cov->operation(); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + if (expr_gen.parser_->settings_.strength_reduction_enabled()) + { + // v0 / (c / v1) --> (vovoc) (v0 * v1) / c + if ((details::e_div == o0) && (details::e_div == o1)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t*t)/t", v0, v1, c, result); + + exprtk_debug(("v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n")); + + return (synthesis_result) ? result : error_node(); + } + } + + const bool synthesis_result = + synthesize_sf3ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + else if (!expr_gen.valid_operator(o1,f1)) + return error_node(); + else + return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, const details::operator_type o1) + { + return details::build_string() + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)"; + } + }; + + struct synthesize_covov_expression0 + { + typedef typename covov_t::type0 node_type; + typedef typename covov_t::sf3_type sf3_type; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // (c o0 v0) o1 (v1) + const details::cov_base_node* cov = static_cast*>(branch[0]); + const Type c = cov->c(); + const Type& v0 = cov->v(); + const Type& v1 = static_cast*>(branch[1])->ref(); + const details::operator_type o0 = cov->operation(); + const details::operator_type o1 = operation; + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + + expression_node_ptr result = error_node(); + + if (expr_gen.parser_->settings_.strength_reduction_enabled()) + { + // (c / v0) / v1 --> (covov) c / (v0 * v1) + if ((details::e_div == o0) && (details::e_div == o1)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "t/(t*t)", c, v0, v1, result); + + exprtk_debug(("(c / v0) / v1 --> (covov) c / (v0 * v1)\n")); + + return (synthesis_result) ? result : error_node(); + } + } + + const bool synthesis_result = + synthesize_sf3ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + else if (!expr_gen.valid_operator(o1,f1)) + return error_node(); + else + return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, const details::operator_type o1) + { + return details::build_string() + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t"; + } + }; + + struct synthesize_covov_expression1 + { + typedef typename covov_t::type1 node_type; + typedef typename covov_t::sf3_type sf3_type; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // (c) o0 (v0 o1 v1) + const details::vov_base_node* vov = static_cast*>(branch[1]); + const Type c = static_cast*>(branch[0])->value(); + const Type& v0 = vov->v0(); + const Type& v1 = vov->v1(); + const details::operator_type o0 = operation; + const details::operator_type o1 = vov->operation(); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + if (expr_gen.parser_->settings_.strength_reduction_enabled()) + { + // c / (v0 / v1) --> (covov) (c * v1) / v0 + if ((details::e_div == o0) && (details::e_div == o1)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t*t)/t", c, v1, v0, result); + + exprtk_debug(("c / (v0 / v1) --> (covov) (c * v1) / v0\n")); + + return (synthesis_result) ? result : error_node(); + } + } + + const bool synthesis_result = + synthesize_sf3ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + else if (!expr_gen.valid_operator(o1,f1)) + return error_node(); + else + return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1); + } + + static inline std::string id(expression_generator& expr_gen, const details::operator_type o0, const details::operator_type o1) + { + return details::build_string() + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)"; + } + }; + + struct synthesize_covoc_expression0 + { + typedef typename covoc_t::type0 node_type; + typedef typename covoc_t::sf3_type sf3_type; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // (c0 o0 v) o1 (c1) + const details::cov_base_node* cov = static_cast*>(branch[0]); + const Type c0 = cov->c(); + const Type& v = cov->v(); + const Type c1 = static_cast*>(branch[1])->value(); + const details::operator_type o0 = cov->operation(); + const details::operator_type o1 = operation; + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + if (expr_gen.parser_->settings_.strength_reduction_enabled()) + { + // (c0 + v) + c1 --> (cov) (c0 + c1) + v + if ((details::e_add == o0) && (details::e_add == o1)) + { + exprtk_debug(("(c0 + v) + c1 --> (cov) (c0 + c1) + v\n")); + + return expr_gen.node_allocator_-> + template allocate_cr > >(c0 + c1, v); + } + // (c0 + v) - c1 --> (cov) (c0 - c1) + v + else if ((details::e_add == o0) && (details::e_sub == o1)) + { + exprtk_debug(("(c0 + v) - c1 --> (cov) (c0 - c1) + v\n")); + + return expr_gen.node_allocator_-> + template allocate_cr > >(c0 - c1, v); + } + // (c0 - v) + c1 --> (cov) (c0 + c1) - v + else if ((details::e_sub == o0) && (details::e_add == o1)) + { + exprtk_debug(("(c0 - v) + c1 --> (cov) (c0 + c1) - v\n")); + + return expr_gen.node_allocator_-> + template allocate_cr > >(c0 + c1, v); + } + // (c0 - v) - c1 --> (cov) (c0 - c1) - v + else if ((details::e_sub == o0) && (details::e_sub == o1)) + { + exprtk_debug(("(c0 - v) - c1 --> (cov) (c0 - c1) - v\n")); + + return expr_gen.node_allocator_-> + template allocate_cr > >(c0 - c1, v); + } + // (c0 * v) * c1 --> (cov) (c0 * c1) * v + else if ((details::e_mul == o0) && (details::e_mul == o1)) + { + exprtk_debug(("(c0 * v) * c1 --> (cov) (c0 * c1) * v\n")); + + return expr_gen.node_allocator_-> + template allocate_cr > >(c0 * c1, v); + } + // (c0 * v) / c1 --> (cov) (c0 / c1) * v + else if ((details::e_mul == o0) && (details::e_div == o1)) + { + exprtk_debug(("(c0 * v) / c1 --> (cov) (c0 / c1) * v\n")); + + return expr_gen.node_allocator_-> + template allocate_cr > >(c0 / c1, v); + } + // (c0 / v) * c1 --> (cov) (c0 * c1) / v + else if ((details::e_div == o0) && (details::e_mul == o1)) + { + exprtk_debug(("(c0 / v) * c1 --> (cov) (c0 * c1) / v\n")); + + return expr_gen.node_allocator_-> + template allocate_cr > >(c0 * c1, v); + } + // (c0 / v) / c1 --> (cov) (c0 / c1) / v + else if ((details::e_div == o0) && (details::e_div == o1)) + { + exprtk_debug(("(c0 / v) / c1 --> (cov) (c0 / c1) / v\n")); + + return expr_gen.node_allocator_-> + template allocate_cr > >(c0 / c1, v); + } + } + + const bool synthesis_result = + synthesize_sf3ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + else if (!expr_gen.valid_operator(o1,f1)) + return error_node(); + else + return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, const details::operator_type o1) + { + return details::build_string() + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t"; + } + }; + + struct synthesize_covoc_expression1 + { + typedef typename covoc_t::type1 node_type; + typedef typename covoc_t::sf3_type sf3_type; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // (c0) o0 (v o1 c1) + const details::voc_base_node* voc = static_cast*>(branch[1]); + const Type c0 = static_cast*>(branch[0])->value(); + const Type& v = voc->v(); + const Type c1 = voc->c(); + const details::operator_type o0 = operation; + const details::operator_type o1 = voc->operation(); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + if (expr_gen.parser_->settings_.strength_reduction_enabled()) + { + // (c0) + (v + c1) --> (cov) (c0 + c1) + v + if ((details::e_add == o0) && (details::e_add == o1)) + { + exprtk_debug(("(c0) + (v + c1) --> (cov) (c0 + c1) + v\n")); + + return expr_gen.node_allocator_-> + template allocate_cr > >(c0 + c1, v); + } + // (c0) + (v - c1) --> (cov) (c0 - c1) + v + else if ((details::e_add == o0) && (details::e_sub == o1)) + { + exprtk_debug(("(c0) + (v - c1) --> (cov) (c0 - c1) + v\n")); + + return expr_gen.node_allocator_-> + template allocate_cr > >(c0 - c1, v); + } + // (c0) - (v + c1) --> (cov) (c0 - c1) - v + else if ((details::e_sub == o0) && (details::e_add == o1)) + { + exprtk_debug(("(c0) - (v + c1) --> (cov) (c0 - c1) - v\n")); + + return expr_gen.node_allocator_-> + template allocate_cr > >(c0 - c1, v); + } + // (c0) - (v - c1) --> (cov) (c0 + c1) - v + else if ((details::e_sub == o0) && (details::e_sub == o1)) + { + exprtk_debug(("(c0) - (v - c1) --> (cov) (c0 + c1) - v\n")); + + return expr_gen.node_allocator_-> + template allocate_cr > >(c0 + c1, v); + } + // (c0) * (v * c1) --> (voc) v * (c0 * c1) + else if ((details::e_mul == o0) && (details::e_mul == o1)) + { + exprtk_debug(("(c0) * (v * c1) --> (voc) v * (c0 * c1)\n")); + + return expr_gen.node_allocator_-> + template allocate_cr > >(c0 * c1, v); + } + // (c0) * (v / c1) --> (cov) (c0 / c1) * v + else if ((details::e_mul == o0) && (details::e_div == o1)) + { + exprtk_debug(("(c0) * (v / c1) --> (cov) (c0 / c1) * v\n")); + + return expr_gen.node_allocator_-> + template allocate_cr > >(c0 / c1, v); + } + // (c0) / (v * c1) --> (cov) (c0 / c1) / v + else if ((details::e_div == o0) && (details::e_mul == o1)) + { + exprtk_debug(("(c0) / (v * c1) --> (cov) (c0 / c1) / v\n")); + + return expr_gen.node_allocator_-> + template allocate_cr > >(c0 / c1, v); + } + // (c0) / (v / c1) --> (cov) (c0 * c1) / v + else if ((details::e_div == o0) && (details::e_div == o1)) + { + exprtk_debug(("(c0) / (v / c1) --> (cov) (c0 * c1) / v\n")); + + return expr_gen.node_allocator_-> + template allocate_cr > >(c0 * c1, v); + } + } + + const bool synthesis_result = + synthesize_sf3ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + else if (!expr_gen.valid_operator(o1,f1)) + return error_node(); + else + return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, const details::operator_type o1) + { + return details::build_string() + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)"; + } + }; + + struct synthesize_cocov_expression0 + { + typedef typename cocov_t::type0 node_type; + static inline expression_node_ptr process(expression_generator&, const details::operator_type&, expression_node_ptr (&)[2]) + { + // (c0 o0 c1) o1 (v) - Not possible. + return error_node(); + } + }; + + struct synthesize_cocov_expression1 + { + typedef typename cocov_t::type1 node_type; + typedef typename cocov_t::sf3_type sf3_type; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // (c0) o0 (c1 o1 v) + const details::cov_base_node* cov = static_cast*>(branch[1]); + const Type c0 = static_cast*>(branch[0])->value(); + const Type c1 = cov->c(); + const Type& v = cov->v(); + const details::operator_type o0 = operation; + const details::operator_type o1 = cov->operation(); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + if (expr_gen.parser_->settings_.strength_reduction_enabled()) + { + // (c0) + (c1 + v) --> (cov) (c0 + c1) + v + if ((details::e_add == o0) && (details::e_add == o1)) + { + exprtk_debug(("(c0) + (c1 + v) --> (cov) (c0 + c1) + v\n")); + + return expr_gen.node_allocator_-> + template allocate_cr > >(c0 + c1, v); + } + // (c0) + (c1 - v) --> (cov) (c0 + c1) - v + else if ((details::e_add == o0) && (details::e_sub == o1)) + { + exprtk_debug(("(c0) + (c1 - v) --> (cov) (c0 + c1) - v\n")); + + return expr_gen.node_allocator_-> + template allocate_cr > >(c0 + c1, v); + } + // (c0) - (c1 + v) --> (cov) (c0 - c1) - v + else if ((details::e_sub == o0) && (details::e_add == o1)) + { + exprtk_debug(("(c0) - (c1 + v) --> (cov) (c0 - c1) - v\n")); + + return expr_gen.node_allocator_-> + template allocate_cr > >(c0 - c1, v); + } + // (c0) - (c1 - v) --> (cov) (c0 - c1) + v + else if ((details::e_sub == o0) && (details::e_sub == o1)) + { + exprtk_debug(("(c0) - (c1 - v) --> (cov) (c0 - c1) + v\n")); + + return expr_gen.node_allocator_-> + template allocate_cr > >(c0 - c1, v); + } + // (c0) * (c1 * v) --> (cov) (c0 * c1) * v + else if ((details::e_mul == o0) && (details::e_mul == o1)) + { + exprtk_debug(("(c0) * (c1 * v) --> (cov) (c0 * c1) * v\n")); + + return expr_gen.node_allocator_-> + template allocate_cr > >(c0 * c1, v); + } + // (c0) * (c1 / v) --> (cov) (c0 * c1) / v + else if ((details::e_mul == o0) && (details::e_div == o1)) + { + exprtk_debug(("(c0) * (c1 / v) --> (cov) (c0 * c1) / v\n")); + + return expr_gen.node_allocator_-> + template allocate_cr > >(c0 * c1, v); + } + // (c0) / (c1 * v) --> (cov) (c0 / c1) / v + else if ((details::e_div == o0) && (details::e_mul == o1)) + { + exprtk_debug(("(c0) / (c1 * v) --> (cov) (c0 / c1) / v\n")); + + return expr_gen.node_allocator_-> + template allocate_cr > >(c0 / c1, v); + } + // (c0) / (c1 / v) --> (cov) (c0 / c1) * v + else if ((details::e_div == o0) && (details::e_div == o1)) + { + exprtk_debug(("(c0) / (c1 / v) --> (cov) (c0 / c1) * v\n")); + + return expr_gen.node_allocator_-> + template allocate_cr > >(c0 / c1, v); + } + } + + const bool synthesis_result = + synthesize_sf3ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1), c0, c1, v, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + else if (!expr_gen.valid_operator(o1,f1)) + return error_node(); + else + return node_type::allocate(*(expr_gen.node_allocator_), c0, c1, v, f0, f1); + } + + static inline std::string id(expression_generator& expr_gen, const details::operator_type o0, const details::operator_type o1) + { + return details::build_string() + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)"; + } + }; + + struct synthesize_vococ_expression0 + { + typedef typename vococ_t::type0 node_type; + typedef typename vococ_t::sf3_type sf3_type; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // (v o0 c0) o1 (c1) + const details::voc_base_node* voc = static_cast*>(branch[0]); + const Type& v = voc->v(); + const Type& c0 = voc->c(); + const Type& c1 = static_cast*>(branch[1])->value(); + const details::operator_type o0 = voc->operation(); + const details::operator_type o1 = operation; + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + if (expr_gen.parser_->settings_.strength_reduction_enabled()) + { + // (v + c0) + c1 --> (voc) v + (c0 + c1) + if ((details::e_add == o0) && (details::e_add == o1)) + { + exprtk_debug(("(v + c0) + c1 --> (voc) v + (c0 + c1)\n")); + + return expr_gen.node_allocator_-> + template allocate_rc > >(v, c0 + c1); + } + // (v + c0) - c1 --> (voc) v + (c0 - c1) + else if ((details::e_add == o0) && (details::e_sub == o1)) + { + exprtk_debug(("(v + c0) - c1 --> (voc) v + (c0 - c1)\n")); + + return expr_gen.node_allocator_-> + template allocate_rc > >(v, c0 - c1); + } + // (v - c0) + c1 --> (voc) v - (c0 + c1) + else if ((details::e_sub == o0) && (details::e_add == o1)) + { + exprtk_debug(("(v - c0) + c1 --> (voc) v - (c0 + c1)\n")); + + return expr_gen.node_allocator_-> + template allocate_rc > >(v, c1 - c0); + } + // (v - c0) - c1 --> (voc) v - (c0 + c1) + else if ((details::e_sub == o0) && (details::e_sub == o1)) + { + exprtk_debug(("(v - c0) - c1 --> (voc) v - (c0 + c1)\n")); + + return expr_gen.node_allocator_-> + template allocate_rc > >(v, c0 + c1); + } + // (v * c0) * c1 --> (voc) v * (c0 * c1) + else if ((details::e_mul == o0) && (details::e_mul == o1)) + { + exprtk_debug(("(v * c0) * c1 --> (voc) v * (c0 * c1)\n")); + + return expr_gen.node_allocator_-> + template allocate_rc > >(v, c0 * c1); + } + // (v * c0) / c1 --> (voc) v * (c0 / c1) + else if ((details::e_mul == o0) && (details::e_div == o1)) + { + exprtk_debug(("(v * c0) / c1 --> (voc) v * (c0 / c1)\n")); + + return expr_gen.node_allocator_-> + template allocate_rc > >(v, c0 / c1); + } + // (v / c0) * c1 --> (voc) v * (c1 / c0) + else if ((details::e_div == o0) && (details::e_mul == o1)) + { + exprtk_debug(("(v / c0) * c1 --> (voc) v * (c1 / c0)\n")); + + return expr_gen.node_allocator_-> + template allocate_rc > >(v, c1 / c0); + } + // (v / c0) / c1 --> (voc) v / (c0 * c1) + else if ((details::e_div == o0) && (details::e_div == o1)) + { + exprtk_debug(("(v / c0) / c1 --> (voc) v / (c0 * c1)\n")); + + return expr_gen.node_allocator_-> + template allocate_rc > >(v, c0 * c1); + } + // (v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1) + else if ((details::e_pow == o0) && (details::e_pow == o1)) + { + exprtk_debug(("(v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\n")); + + return expr_gen.node_allocator_-> + template allocate_rc > >(v, c0 * c1); + } + } + + const bool synthesis_result = + synthesize_sf3ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1), v, c0, c1, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + else if (!expr_gen.valid_operator(o1,f1)) + return error_node(); + else + return node_type::allocate(*(expr_gen.node_allocator_), v, c0, c1, f0, f1); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, const details::operator_type o1) + { + return details::build_string() + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t"; + } + }; + + struct synthesize_vococ_expression1 + { + typedef typename vococ_t::type0 node_type; + + static inline expression_node_ptr process(expression_generator&, const details::operator_type&, expression_node_ptr (&)[2]) + { + // (v) o0 (c0 o1 c1) - Not possible. + exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n")); + return error_node(); + } + }; + + struct synthesize_vovovov_expression0 + { + typedef typename vovovov_t::type0 node_type; + typedef typename vovovov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // (v0 o0 v1) o1 (v2 o2 v3) + const details::vov_base_node* vov0 = static_cast*>(branch[0]); + const details::vov_base_node* vov1 = static_cast*>(branch[1]); + const Type& v0 = vov0->v0(); + const Type& v1 = vov0->v1(); + const Type& v2 = vov1->v0(); + const Type& v3 = vov1->v1(); + const details::operator_type o0 = vov0->operation(); + const details::operator_type o1 = operation; + const details::operator_type o2 = vov1->operation(); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = reinterpret_cast(0); + binary_functor_t f2 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + if (expr_gen.parser_->settings_.strength_reduction_enabled()) + { + // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3) + if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) + { + const bool synthesis_result = + synthesize_sf4ext_expression:: + template compile(expr_gen, "(t*t)/(t*t)", v0, v2, v1, v3, result); + + exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2) + else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) + { + const bool synthesis_result = + synthesize_sf4ext_expression:: + template compile(expr_gen, "(t*t)/(t*t)", v0, v3, v1, v2, result); + + exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2) + else if ((details::e_add == o0) && (details::e_div == o1) && (details::e_div == o2)) + { + const bool synthesis_result = + synthesize_sf4ext_expression:: + template compile(expr_gen, "(t+t)*(t/t)", v0, v1, v3, v2, result); + + exprtk_debug(("(v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 - v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2) + else if ((details::e_sub == o0) && (details::e_div == o1) && (details::e_div == o2)) + { + const bool synthesis_result = + synthesize_sf4ext_expression:: + template compile(expr_gen, "(t-t)*(t/t)", v0, v1, v3, v2, result); + + exprtk_debug(("(v0 - v1) / (v2 / v3) --> (vovovov) (v0 - v1) * (v3 / v2)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2 + else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) + { + const bool synthesis_result = + synthesize_sf4ext_expression:: + template compile(expr_gen, "((t*t)*t)/t", v0, v1, v3, v2, result); + + exprtk_debug(("(v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2\n")); + + return (synthesis_result) ? result : error_node(); + } + } + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + else if (!expr_gen.valid_operator(o1,f1)) + return error_node(); + else if (!expr_gen.valid_operator(o2,f2)) + return error_node(); + else + return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t)"; + } + }; + + struct synthesize_vovovoc_expression0 + { + typedef typename vovovoc_t::type0 node_type; + typedef typename vovovoc_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // (v0 o0 v1) o1 (v2 o2 c) + const details::vov_base_node* vov = static_cast*>(branch[0]); + const details::voc_base_node* voc = static_cast*>(branch[1]); + const Type& v0 = vov->v0(); + const Type& v1 = vov->v1(); + const Type& v2 = voc->v (); + const Type c = voc->c (); + const details::operator_type o0 = vov->operation(); + const details::operator_type o1 = operation; + const details::operator_type o2 = voc->operation(); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = reinterpret_cast(0); + binary_functor_t f2 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + if (expr_gen.parser_->settings_.strength_reduction_enabled()) + { + // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c) + if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) + { + const bool synthesis_result = + synthesize_sf4ext_expression:: + template compile(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result); + + exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2) + if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) + { + const bool synthesis_result = + synthesize_sf4ext_expression:: + template compile(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result); + + exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n")); + + return (synthesis_result) ? result : error_node(); + } + } + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + else if (!expr_gen.valid_operator(o1,f1)) + return error_node(); + else if (!expr_gen.valid_operator(o2,f2)) + return error_node(); + else + return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t)"; + } + }; + + struct synthesize_vovocov_expression0 + { + typedef typename vovocov_t::type0 node_type; + typedef typename vovocov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // (v0 o0 v1) o1 (c o2 v2) + const details::vov_base_node* vov = static_cast*>(branch[0]); + const details::cov_base_node* cov = static_cast*>(branch[1]); + const Type& v0 = vov->v0(); + const Type& v1 = vov->v1(); + const Type& v2 = cov->v (); + const Type c = cov->c (); + const details::operator_type o0 = vov->operation(); + const details::operator_type o1 = operation; + const details::operator_type o2 = cov->operation(); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = reinterpret_cast(0); + binary_functor_t f2 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + if (expr_gen.parser_->settings_.strength_reduction_enabled()) + { + // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2) + if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) + { + const bool synthesis_result = + synthesize_sf4ext_expression:: + template compile(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result); + + exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c) + if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) + { + const bool synthesis_result = + synthesize_sf4ext_expression:: + template compile(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result); + + exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n")); + + return (synthesis_result) ? result : error_node(); + } + } + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + else if (!expr_gen.valid_operator(o1,f1)) + return error_node(); + else if (!expr_gen.valid_operator(o2,f2)) + return error_node(); + else + return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t)"; + } + }; + + struct synthesize_vocovov_expression0 + { + typedef typename vocovov_t::type0 node_type; + typedef typename vocovov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // (v0 o0 c) o1 (v1 o2 v2) + const details::voc_base_node* voc = static_cast*>(branch[0]); + const details::vov_base_node* vov = static_cast*>(branch[1]); + const Type c = voc->c (); + const Type& v0 = voc->v (); + const Type& v1 = vov->v0(); + const Type& v2 = vov->v1(); + const details::operator_type o0 = voc->operation(); + const details::operator_type o1 = operation; + const details::operator_type o2 = vov->operation(); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = reinterpret_cast(0); + binary_functor_t f2 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + if (expr_gen.parser_->settings_.strength_reduction_enabled()) + { + // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2) + if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) + { + const bool synthesis_result = + synthesize_sf4ext_expression:: + template compile(expr_gen, "(t*t)/(t*t)", v0, v1, c, v2, result); + + exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1) + if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) + { + const bool synthesis_result = + synthesize_sf4ext_expression:: + template compile(expr_gen, "(t*t)/(t*t)", v0, v2, c, v1, result); + + exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n")); + + return (synthesis_result) ? result : error_node(); + } + } + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + else if (!expr_gen.valid_operator(o1,f1)) + return error_node(); + else if (!expr_gen.valid_operator(o2,f2)) + return error_node(); + else + return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t)"; + } + }; + + struct synthesize_covovov_expression0 + { + typedef typename covovov_t::type0 node_type; + typedef typename covovov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // (c o0 v0) o1 (v1 o2 v2) + const details::cov_base_node* cov = static_cast*>(branch[0]); + const details::vov_base_node* vov = static_cast*>(branch[1]); + const Type c = cov->c (); + const Type& v0 = cov->v (); + const Type& v1 = vov->v0(); + const Type& v2 = vov->v1(); + const details::operator_type o0 = cov->operation(); + const details::operator_type o1 = operation; + const details::operator_type o2 = vov->operation(); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = reinterpret_cast(0); + binary_functor_t f2 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + if (expr_gen.parser_->settings_.strength_reduction_enabled()) + { + // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2) + if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) + { + const bool synthesis_result = + synthesize_sf4ext_expression:: + template compile(expr_gen, "(t*t)/(t*t)", c, v1, v0, v2, result); + + exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1) + if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) + { + const bool synthesis_result = + synthesize_sf4ext_expression:: + template compile(expr_gen, "(t*t)/(t*t)", c, v2, v0, v1, result); + + exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n")); + + return (synthesis_result) ? result : error_node(); + } + } + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + else if (!expr_gen.valid_operator(o1,f1)) + return error_node(); + else if (!expr_gen.valid_operator(o2,f2)) + return error_node(); + else + return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t)"; + } + }; + + struct synthesize_covocov_expression0 + { + typedef typename covocov_t::type0 node_type; + typedef typename covocov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // (c0 o0 v0) o1 (c1 o2 v1) + const details::cov_base_node* cov0 = static_cast*>(branch[0]); + const details::cov_base_node* cov1 = static_cast*>(branch[1]); + const Type c0 = cov0->c(); + const Type& v0 = cov0->v(); + const Type c1 = cov1->c(); + const Type& v1 = cov1->v(); + const details::operator_type o0 = cov0->operation(); + const details::operator_type o1 = operation; + const details::operator_type o2 = cov1->operation(); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = reinterpret_cast(0); + binary_functor_t f2 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + if (expr_gen.parser_->settings_.strength_reduction_enabled()) + { + // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1 + if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); + + exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n")); + + return (synthesis_result) ? result : error_node(); + } + // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1 + else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); + + exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n")); + + return (synthesis_result) ? result : error_node(); + } + // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1 + else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t-t)+t", (c0 - c1), v0, v1, result); + + exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n")); + + return (synthesis_result) ? result : error_node(); + } + // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 + else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); + + exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n")); + + return (synthesis_result) ? result : error_node(); + } + // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1) + else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); + + exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1) + else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result); + + exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0 + else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t*t)/t", (c0 / c1), v1, v0, result); + + exprtk_debug(("(c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\n")); + + return (synthesis_result) ? result : error_node(); + } + // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1) + else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "t*(t*t)", (c0 / c1), v0, v1, result); + + exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1) + else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result); + + exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1) + else if ( + (std::equal_to()(c0,c1)) && + (details::e_mul == o0) && + (details::e_mul == o2) && + ( + (details::e_add == o1) || + (details::e_sub == o1) + ) + ) + { + std::string specfunc; + + switch (o1) + { + case details::e_add : specfunc = "t*(t+t)"; break; + case details::e_sub : specfunc = "t*(t-t)"; break; + default : return error_node(); + } + + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, specfunc, c0, v0, v1, result); + + exprtk_debug(("(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n")); + + return (synthesis_result) ? result : error_node(); + } + } + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + else if (!expr_gen.valid_operator(o1,f1)) + return error_node(); + else if (!expr_gen.valid_operator(o2,f2)) + return error_node(); + else + return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t)"; + } + }; + + struct synthesize_vocovoc_expression0 + { + typedef typename vocovoc_t::type0 node_type; + typedef typename vocovoc_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // (v0 o0 c0) o1 (v1 o2 c1) + const details::voc_base_node* voc0 = static_cast*>(branch[0]); + const details::voc_base_node* voc1 = static_cast*>(branch[1]); + const Type c0 = voc0->c(); + const Type& v0 = voc0->v(); + const Type c1 = voc1->c(); + const Type& v1 = voc1->v(); + const details::operator_type o0 = voc0->operation(); + const details::operator_type o1 = operation; + const details::operator_type o2 = voc1->operation(); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = reinterpret_cast(0); + binary_functor_t f2 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + if (expr_gen.parser_->settings_.strength_reduction_enabled()) + { + // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1 + if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); + + exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1 + else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); + + exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1 + else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t+t)-t", (c1 - c0), v0, v1, result); + + exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1 + else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); + + exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1) + else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); + + exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1 + else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t*t)*t", Type(1) / (c0 * c1), v0, v1, result); + + exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1 + else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result); + + exprtk_debug(("(v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1) + else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "t*(t/t)", (c0 * c1), v0, v1, result); + + exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1 + else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "t*(t/t)", Type(1) / (c0 * c1), v0, v1, result); + + exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1) + else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2)) + { + const bool synthesis_result = + synthesize_sf4ext_expression:: + template compile(expr_gen, "(t*t)*(t+t)", v0, T(1) / c0, v1, c1, result); + + exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1) + else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2)) + { + const bool synthesis_result = + synthesize_sf4ext_expression:: + template compile(expr_gen, "(t*t)*(t-t)", v0, T(1) / c0, v1, c1, result); + + exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1) + else if ( + (std::equal_to()(c0,c1)) && + (details::e_mul == o0) && + (details::e_mul == o2) && + ( + (details::e_add == o1) || + (details::e_sub == o1) + ) + ) + { + std::string specfunc; + + switch (o1) + { + case details::e_add : specfunc = "t*(t+t)"; break; + case details::e_sub : specfunc = "t*(t-t)"; break; + default : return error_node(); + } + + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, specfunc, c0, v0, v1, result); + + exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c + else if ( + (std::equal_to()(c0,c1)) && + (details::e_div == o0) && + (details::e_div == o2) && + ( + (details::e_add == o1) || + (details::e_sub == o1) + ) + ) + { + std::string specfunc; + + switch (o1) + { + case details::e_add : specfunc = "(t+t)/t"; break; + case details::e_sub : specfunc = "(t-t)/t"; break; + default : return error_node(); + } + + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, specfunc, v0, v1, c0, result); + + exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n")); + + return (synthesis_result) ? result : error_node(); + } + } + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + else if (!expr_gen.valid_operator(o1,f1)) + return error_node(); + else if (!expr_gen.valid_operator(o2,f2)) + return error_node(); + else + return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t)"; + } + }; + + struct synthesize_covovoc_expression0 + { + typedef typename covovoc_t::type0 node_type; + typedef typename covovoc_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // (c0 o0 v0) o1 (v1 o2 c1) + const details::cov_base_node* cov = static_cast*>(branch[0]); + const details::voc_base_node* voc = static_cast*>(branch[1]); + const Type c0 = cov->c(); + const Type& v0 = cov->v(); + const Type c1 = voc->c(); + const Type& v1 = voc->v(); + const details::operator_type o0 = cov->operation(); + const details::operator_type o1 = operation; + const details::operator_type o2 = voc->operation(); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = reinterpret_cast(0); + binary_functor_t f2 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + if (expr_gen.parser_->settings_.strength_reduction_enabled()) + { + // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1 + if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); + + exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n")); + + return (synthesis_result) ? result : error_node(); + } + // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1 + else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); + + exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n")); + + return (synthesis_result) ? result : error_node(); + } + // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1 + else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "t-(t+t)", (c0 + c1), v0, v1, result); + + exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n")); + + return (synthesis_result) ? result : error_node(); + } + // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1 + else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); + + exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n")); + + return (synthesis_result) ? result : error_node(); + } + // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1) + else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); + + exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0) + else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "t*(t/t)", (c0 / c1), v1, v0, result); + + exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1) + else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result); + + exprtk_debug(("(c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1) + else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t*t)/t", (c0 * c1), v0, v1, result); + + exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1) + else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result); + + exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1) + else if ( + (std::equal_to()(c0,c1)) && + (details::e_mul == o0) && + (details::e_mul == o2) && + ( + (details::e_add == o1) || + (details::e_sub == o1) + ) + ) + { + std::string specfunc; + + switch (o1) + { + case details::e_add : specfunc = "t*(t+t)"; break; + case details::e_sub : specfunc = "t*(t-t)"; break; + default : return error_node(); + } + + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen,specfunc, c0, v0, v1, result); + + exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n")); + + return (synthesis_result) ? result : error_node(); + } + } + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + else if (!expr_gen.valid_operator(o1,f1)) + return error_node(); + else if (!expr_gen.valid_operator(o2,f2)) + return error_node(); + else + return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t)"; + } + }; + + struct synthesize_vococov_expression0 + { + typedef typename vococov_t::type0 node_type; + typedef typename vococov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // (v0 o0 c0) o1 (c1 o2 v1) + const details::voc_base_node* voc = static_cast*>(branch[0]); + const details::cov_base_node* cov = static_cast*>(branch[1]); + const Type c0 = voc->c(); + const Type& v0 = voc->v(); + const Type c1 = cov->c(); + const Type& v1 = cov->v(); + const details::operator_type o0 = voc->operation(); + const details::operator_type o1 = operation; + const details::operator_type o2 = cov->operation(); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = reinterpret_cast(0); + binary_functor_t f2 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + if (expr_gen.parser_->settings_.strength_reduction_enabled()) + { + // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1 + if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); + + exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1 + else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); + + exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0) + else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t+t)-t", v0, v1, (c1 + c0), result); + + exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 + else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); + + exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1) + else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); + + exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1) + else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result); + + exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1) + else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t*t)*t", (c0 / c1), v0, v1, result); + + exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1) + else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t*t)/t", Type(1) / (c0 * c1), v0, v1, result); + + exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1)) + else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) + { + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, "(t*t)*t", v0, v1, Type(1) / (c0 * c1), result); + + exprtk_debug(("(v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\n")); + + return (synthesis_result) ? result : error_node(); + } + // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1) + else if ( + (std::equal_to()(c0,c1)) && + (details::e_mul == o0) && + (details::e_mul == o2) && + ( + (details::e_add == o1) || (details::e_sub == o1) + ) + ) + { + std::string specfunc; + + switch (o1) + { + case details::e_add : specfunc = "t*(t+t)"; break; + case details::e_sub : specfunc = "t*(t-t)"; break; + default : return error_node(); + } + + const bool synthesis_result = + synthesize_sf3ext_expression:: + template compile(expr_gen, specfunc, c0, v0, v1, result); + + exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n")); + + return (synthesis_result) ? result : error_node(); + } + } + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + else if (!expr_gen.valid_operator(o1,f1)) + return error_node(); + else if (!expr_gen.valid_operator(o2,f2)) + return error_node(); + else + return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t)"; + } + }; + + struct synthesize_vovovov_expression1 + { + typedef typename vovovov_t::type1 node_type; + typedef typename vovovov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // v0 o0 (v1 o1 (v2 o2 v3)) + typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; + + const lcl_vovov_t* vovov = static_cast(branch[1]); + const Type& v0 = static_cast*>(branch[0])->ref(); + const Type& v1 = vovov->t0(); + const Type& v2 = vovov->t1(); + const Type& v3 = vovov->t2(); + const details::operator_type o0 = operation; + const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); + const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = vovov->f0(); + binary_functor_t f2 = vovov->f1(); + + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + if (synthesize_sf4ext_expression::template compile(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result)) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + + exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n")); + + return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t))"; + } + }; + + struct synthesize_vovovoc_expression1 + { + typedef typename vovovoc_t::type1 node_type; + typedef typename vovovoc_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // v0 o0 (v1 o1 (v2 o2 c)) + typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; + + const lcl_vovoc_t* vovoc = static_cast(branch[1]); + const Type& v0 = static_cast*>(branch[0])->ref(); + const Type& v1 = vovoc->t0(); + const Type& v2 = vovoc->t1(); + const Type c = vovoc->t2(); + const details::operator_type o0 = operation; + const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); + const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = vovoc->f0(); + binary_functor_t f2 = vovoc->f1(); + + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + + exprtk_debug(("v0 o0 (v1 o1 (v2 o2 c))\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t))"; + } + }; + + struct synthesize_vovocov_expression1 + { + typedef typename vovocov_t::type1 node_type; + typedef typename vovocov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // v0 o0 (v1 o1 (c o2 v2)) + typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; + + const lcl_vocov_t* vocov = static_cast(branch[1]); + const Type& v0 = static_cast*>(branch[0])->ref(); + const Type& v1 = vocov->t0(); + const Type c = vocov->t1(); + const Type& v2 = vocov->t2(); + const details::operator_type o0 = operation; + const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); + const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = vocov->f0(); + binary_functor_t f2 = vocov->f1(); + + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); + + if (synthesis_result) + return result; + if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + + exprtk_debug(("v0 o0 (v1 o1 (c o2 v2))\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t))"; + } + }; + + struct synthesize_vocovov_expression1 + { + typedef typename vocovov_t::type1 node_type; + typedef typename vocovov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // v0 o0 (c o1 (v1 o2 v2)) + typedef typename synthesize_covov_expression1::node_type lcl_covov_t; + + const lcl_covov_t* covov = static_cast(branch[1]); + const Type& v0 = static_cast*>(branch[0])->ref(); + const Type c = covov->t0(); + const Type& v1 = covov->t1(); + const Type& v2 = covov->t2(); + const details::operator_type o0 = operation; + const details::operator_type o1 = expr_gen.get_operator(covov->f0()); + const details::operator_type o2 = expr_gen.get_operator(covov->f1()); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = covov->f0(); + binary_functor_t f2 = covov->f1(); + + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + + exprtk_debug(("v0 o0 (c o1 (v1 o2 v2))\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t))"; + } + }; + + struct synthesize_covovov_expression1 + { + typedef typename covovov_t::type1 node_type; + typedef typename covovov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // c o0 (v0 o1 (v1 o2 v2)) + typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; + + const lcl_vovov_t* vovov = static_cast(branch[1]); + const Type c = static_cast*>(branch[0])->value(); + const Type& v0 = vovov->t0(); + const Type& v1 = vovov->t1(); + const Type& v2 = vovov->t2(); + const details::operator_type o0 = operation; + const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); + const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = vovov->f0(); + binary_functor_t f2 = vovov->f1(); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); + + if (synthesis_result) + return result; + if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + + exprtk_debug(("c o0 (v0 o1 (v1 o2 v2))\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t))"; + } + }; + + struct synthesize_covocov_expression1 + { + typedef typename covocov_t::type1 node_type; + typedef typename covocov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // c0 o0 (v0 o1 (c1 o2 v1)) + typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; + + const lcl_vocov_t* vocov = static_cast(branch[1]); + const Type c0 = static_cast*>(branch[0])->value(); + const Type& v0 = vocov->t0(); + const Type c1 = vocov->t1(); + const Type& v1 = vocov->t2(); + const details::operator_type o0 = operation; + const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); + const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = vocov->f0(); + binary_functor_t f2 = vocov->f1(); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + + exprtk_debug(("c0 o0 (v0 o1 (c1 o2 v1))\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t))"; + } + }; + + struct synthesize_vocovoc_expression1 + { + typedef typename vocovoc_t::type1 node_type; + typedef typename vocovoc_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // v0 o0 (c0 o1 (v1 o2 c2)) + typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t; + + const lcl_covoc_t* covoc = static_cast(branch[1]); + const Type& v0 = static_cast*>(branch[0])->ref(); + const Type c0 = covoc->t0(); + const Type& v1 = covoc->t1(); + const Type c1 = covoc->t2(); + const details::operator_type o0 = operation; + const details::operator_type o1 = expr_gen.get_operator(covoc->f0()); + const details::operator_type o2 = expr_gen.get_operator(covoc->f1()); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = covoc->f0(); + binary_functor_t f2 = covoc->f1(); + + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + + exprtk_debug(("v0 o0 (c0 o1 (v1 o2 c2))\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t))"; + } + }; + + struct synthesize_covovoc_expression1 + { + typedef typename covovoc_t::type1 node_type; + typedef typename covovoc_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // c0 o0 (v0 o1 (v1 o2 c1)) + typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; + + const lcl_vovoc_t* vovoc = static_cast(branch[1]); + const Type c0 = static_cast*>(branch[0])->value(); + const Type& v0 = vovoc->t0(); + const Type& v1 = vovoc->t1(); + const Type c1 = vovoc->t2(); + const details::operator_type o0 = operation; + const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); + const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = vovoc->f0(); + binary_functor_t f2 = vovoc->f1(); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + + exprtk_debug(("c0 o0 (v0 o1 (v1 o2 c1))\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t))"; + } + }; + + struct synthesize_vococov_expression1 + { + typedef typename vococov_t::type1 node_type; + typedef typename vococov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // v0 o0 (c0 o1 (c1 o2 v1)) + typedef typename synthesize_cocov_expression1::node_type lcl_cocov_t; + + const lcl_cocov_t* cocov = static_cast(branch[1]); + const Type& v0 = static_cast*>(branch[0])->ref(); + const Type c0 = cocov->t0(); + const Type c1 = cocov->t1(); + const Type& v1 = cocov->t2(); + const details::operator_type o0 = operation; + const details::operator_type o1 = expr_gen.get_operator(cocov->f0()); + const details::operator_type o2 = expr_gen.get_operator(cocov->f1()); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = cocov->f0(); + binary_functor_t f2 = cocov->f1(); + + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + + exprtk_debug(("v0 o0 (c0 o1 (c1 o2 v1))\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t))"; + } + }; + + struct synthesize_vovovov_expression2 + { + typedef typename vovovov_t::type2 node_type; + typedef typename vovovov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // v0 o0 ((v1 o1 v2) o2 v3) + typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; + + const lcl_vovov_t* vovov = static_cast(branch[1]); + const Type& v0 = static_cast*>(branch[0])->ref(); + const Type& v1 = vovov->t0(); + const Type& v2 = vovov->t1(); + const Type& v3 = vovov->t2(); + const details::operator_type o0 = operation; + const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); + const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = vovov->f0(); + binary_functor_t f2 = vovov->f1(); + + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + + exprtk_debug(("v0 o0 ((v1 o1 v2) o2 v3)\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "t" << expr_gen.to_str(o0) + << "((t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t)"; + } + }; + + struct synthesize_vovovoc_expression2 + { + typedef typename vovovoc_t::type2 node_type; + typedef typename vovovoc_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // v0 o0 ((v1 o1 v2) o2 c) + typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; + + const lcl_vovoc_t* vovoc = static_cast(branch[1]); + const Type& v0 = static_cast*>(branch[0])->ref(); + const Type& v1 = vovoc->t0(); + const Type& v2 = vovoc->t1(); + const Type c = vovoc->t2(); + const details::operator_type o0 = operation; + const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); + const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = vovoc->f0(); + binary_functor_t f2 = vovoc->f1(); + + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + + exprtk_debug(("v0 o0 ((v1 o1 v2) o2 c)\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "t" << expr_gen.to_str(o0) + << "((t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t)"; + } + }; + + struct synthesize_vovocov_expression2 + { + typedef typename vovocov_t::type2 node_type; + typedef typename vovocov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // v0 o0 ((v1 o1 c) o2 v2) + typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; + + const lcl_vocov_t* vocov = static_cast(branch[1]); + const Type& v0 = static_cast*>(branch[0])->ref(); + const Type& v1 = vocov->t0(); + const Type c = vocov->t1(); + const Type& v2 = vocov->t2(); + const details::operator_type o0 = operation; + const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); + const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = vocov->f0(); + binary_functor_t f2 = vocov->f1(); + + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + + exprtk_debug(("v0 o0 ((v1 o1 c) o2 v2)\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "t" << expr_gen.to_str(o0) + << "((t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t)"; + } + }; + + struct synthesize_vocovov_expression2 + { + typedef typename vocovov_t::type2 node_type; + typedef typename vocovov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // v0 o0 ((c o1 v1) o2 v2) + typedef typename synthesize_covov_expression0::node_type lcl_covov_t; + + const lcl_covov_t* covov = static_cast(branch[1]); + const Type& v0 = static_cast*>(branch[0])->ref(); + const Type c = covov->t0(); + const Type& v1 = covov->t1(); + const Type& v2 = covov->t2(); + const details::operator_type o0 = operation; + const details::operator_type o1 = expr_gen.get_operator(covov->f0()); + const details::operator_type o2 = expr_gen.get_operator(covov->f1()); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = covov->f0(); + binary_functor_t f2 = covov->f1(); + + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + + exprtk_debug(("v0 o0 ((c o1 v1) o2 v2)\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "t" << expr_gen.to_str(o0) + << "((t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t)"; + } + }; + + struct synthesize_covovov_expression2 + { + typedef typename covovov_t::type2 node_type; + typedef typename covovov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // c o0 ((v1 o1 v2) o2 v3) + typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; + + const lcl_vovov_t* vovov = static_cast(branch[1]); + const Type c = static_cast*>(branch[0])->value(); + const Type& v0 = vovov->t0(); + const Type& v1 = vovov->t1(); + const Type& v2 = vovov->t2(); + const details::operator_type o0 = operation; + const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); + const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = vovov->f0(); + binary_functor_t f2 = vovov->f1(); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + + exprtk_debug(("c o0 ((v1 o1 v2) o2 v3)\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "t" << expr_gen.to_str(o0) + << "((t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t)"; + } + }; + + struct synthesize_covocov_expression2 + { + typedef typename covocov_t::type2 node_type; + typedef typename covocov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // c0 o0 ((v0 o1 c1) o2 v1) + typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; + + const lcl_vocov_t* vocov = static_cast(branch[1]); + const Type c0 = static_cast*>(branch[0])->value(); + const Type& v0 = vocov->t0(); + const Type c1 = vocov->t1(); + const Type& v1 = vocov->t2(); + const details::operator_type o0 = operation; + const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); + const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = vocov->f0(); + binary_functor_t f2 = vocov->f1(); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + + exprtk_debug(("c0 o0 ((v0 o1 c1) o2 v1)\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "t" << expr_gen.to_str(o0) + << "((t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t)"; + } + }; + + struct synthesize_vocovoc_expression2 + { + typedef typename vocovoc_t::type2 node_type; + typedef typename vocovoc_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // v0 o0 ((c0 o1 v1) o2 c1) + typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t; + + const lcl_covoc_t* covoc = static_cast(branch[1]); + const Type& v0 = static_cast*>(branch[0])->ref(); + const Type c0 = covoc->t0(); + const Type& v1 = covoc->t1(); + const Type c1 = covoc->t2(); + const details::operator_type o0 = operation; + const details::operator_type o1 = expr_gen.get_operator(covoc->f0()); + const details::operator_type o2 = expr_gen.get_operator(covoc->f1()); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = covoc->f0(); + binary_functor_t f2 = covoc->f1(); + + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + + exprtk_debug(("v0 o0 ((c0 o1 v1) o2 c1)\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "t" << expr_gen.to_str(o0) + << "((t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t)"; + } + }; + + struct synthesize_covovoc_expression2 + { + typedef typename covovoc_t::type2 node_type; + typedef typename covovoc_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // c0 o0 ((v0 o1 v1) o2 c1) + typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; + + const lcl_vovoc_t* vovoc = static_cast(branch[1]); + const Type c0 = static_cast*>(branch[0])->value(); + const Type& v0 = vovoc->t0(); + const Type& v1 = vovoc->t1(); + const Type c1 = vovoc->t2(); + const details::operator_type o0 = operation; + const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); + const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); + + binary_functor_t f0 = reinterpret_cast(0); + binary_functor_t f1 = vovoc->f0(); + binary_functor_t f2 = vovoc->f1(); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o0,f0)) + return error_node(); + + exprtk_debug(("c0 o0 ((v0 o1 v1) o2 c1)\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "t" << expr_gen.to_str(o0) + << "((t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t)"; + } + }; + + struct synthesize_vococov_expression2 + { + typedef typename vococov_t::type2 node_type; + static inline expression_node_ptr process(expression_generator&, const details::operator_type&, expression_node_ptr (&)[2]) + { + // v0 o0 ((c0 o1 c1) o2 v1) - Not possible + exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n")); + return error_node(); + } + + static inline std::string id(expression_generator&, + const details::operator_type, const details::operator_type, const details::operator_type) + { + return "INVALID"; + } + }; + + struct synthesize_vovovov_expression3 + { + typedef typename vovovov_t::type3 node_type; + typedef typename vovovov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // ((v0 o0 v1) o1 v2) o2 v3 + typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; + + const lcl_vovov_t* vovov = static_cast(branch[0]); + const Type& v0 = vovov->t0(); + const Type& v1 = vovov->t1(); + const Type& v2 = vovov->t2(); + const Type& v3 = static_cast*>(branch[1])->ref(); + const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); + const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); + const details::operator_type o2 = operation; + + binary_functor_t f0 = vovov->f0(); + binary_functor_t f1 = vovov->f1(); + binary_functor_t f2 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o2,f2)) + return error_node(); + + exprtk_debug(("((v0 o0 v1) o1 v2) o2 v3\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "((t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; + } + }; + + struct synthesize_vovovoc_expression3 + { + typedef typename vovovoc_t::type3 node_type; + typedef typename vovovoc_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // ((v0 o0 v1) o1 v2) o2 c + typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; + + const lcl_vovov_t* vovov = static_cast(branch[0]); + const Type& v0 = vovov->t0(); + const Type& v1 = vovov->t1(); + const Type& v2 = vovov->t2(); + const Type c = static_cast*>(branch[1])->value(); + const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); + const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); + const details::operator_type o2 = operation; + + binary_functor_t f0 = vovov->f0(); + binary_functor_t f1 = vovov->f1(); + binary_functor_t f2 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o2,f2)) + return error_node(); + + exprtk_debug(("((v0 o0 v1) o1 v2) o2 c\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "((t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; + } + }; + + struct synthesize_vovocov_expression3 + { + typedef typename vovocov_t::type3 node_type; + typedef typename vovocov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // ((v0 o0 v1) o1 c) o2 v2 + typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; + + const lcl_vovoc_t* vovoc = static_cast(branch[0]); + const Type& v0 = vovoc->t0(); + const Type& v1 = vovoc->t1(); + const Type c = vovoc->t2(); + const Type& v2 = static_cast*>(branch[1])->ref(); + const details::operator_type o0 = expr_gen.get_operator(vovoc->f0()); + const details::operator_type o1 = expr_gen.get_operator(vovoc->f1()); + const details::operator_type o2 = operation; + + binary_functor_t f0 = vovoc->f0(); + binary_functor_t f1 = vovoc->f1(); + binary_functor_t f2 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o2,f2)) + return error_node(); + + exprtk_debug(("((v0 o0 v1) o1 c) o2 v2\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "((t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; + } + }; + + struct synthesize_vocovov_expression3 + { + typedef typename vocovov_t::type3 node_type; + typedef typename vocovov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // ((v0 o0 c) o1 v1) o2 v2 + typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; + + const lcl_vocov_t* vocov = static_cast(branch[0]); + const Type& v0 = vocov->t0(); + const Type c = vocov->t1(); + const Type& v1 = vocov->t2(); + const Type& v2 = static_cast*>(branch[1])->ref(); + const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); + const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); + const details::operator_type o2 = operation; + + binary_functor_t f0 = vocov->f0(); + binary_functor_t f1 = vocov->f1(); + binary_functor_t f2 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o2,f2)) + return error_node(); + + exprtk_debug(("((v0 o0 c) o1 v1) o2 v2\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "((t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; + } + }; + + struct synthesize_covovov_expression3 + { + typedef typename covovov_t::type3 node_type; + typedef typename covovov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // ((c o0 v0) o1 v1) o2 v2 + typedef typename synthesize_covov_expression0::node_type lcl_covov_t; + + const lcl_covov_t* covov = static_cast(branch[0]); + const Type c = covov->t0(); + const Type& v0 = covov->t1(); + const Type& v1 = covov->t2(); + const Type& v2 = static_cast*>(branch[1])->ref(); + const details::operator_type o0 = expr_gen.get_operator(covov->f0()); + const details::operator_type o1 = expr_gen.get_operator(covov->f1()); + const details::operator_type o2 = operation; + + binary_functor_t f0 = covov->f0(); + binary_functor_t f1 = covov->f1(); + binary_functor_t f2 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o2,f2)) + return error_node(); + + exprtk_debug(("((c o0 v0) o1 v1) o2 v2\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "((t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; + } + }; + + struct synthesize_covocov_expression3 + { + typedef typename covocov_t::type3 node_type; + typedef typename covocov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // ((c0 o0 v0) o1 c1) o2 v1 + typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t; + + const lcl_covoc_t* covoc = static_cast(branch[0]); + const Type c0 = covoc->t0(); + const Type& v0 = covoc->t1(); + const Type c1 = covoc->t2(); + const Type& v1 = static_cast*>(branch[1])->ref(); + const details::operator_type o0 = expr_gen.get_operator(covoc->f0()); + const details::operator_type o1 = expr_gen.get_operator(covoc->f1()); + const details::operator_type o2 = operation; + + binary_functor_t f0 = covoc->f0(); + binary_functor_t f1 = covoc->f1(); + binary_functor_t f2 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o2,f2)) + return error_node(); + + exprtk_debug(("((c0 o0 v0) o1 c1) o2 v1\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "((t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; + } + }; + + struct synthesize_vocovoc_expression3 + { + typedef typename vocovoc_t::type3 node_type; + typedef typename vocovoc_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // ((v0 o0 c0) o1 v1) o2 c1 + typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; + + const lcl_vocov_t* vocov = static_cast(branch[0]); + const Type& v0 = vocov->t0(); + const Type c0 = vocov->t1(); + const Type& v1 = vocov->t2(); + const Type c1 = static_cast*>(branch[1])->value(); + const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); + const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); + const details::operator_type o2 = operation; + + binary_functor_t f0 = vocov->f0(); + binary_functor_t f1 = vocov->f1(); + binary_functor_t f2 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o2,f2)) + return error_node(); + + exprtk_debug(("((v0 o0 c0) o1 v1) o2 c1\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "((t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; + } + }; + + struct synthesize_covovoc_expression3 + { + typedef typename covovoc_t::type3 node_type; + typedef typename covovoc_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // ((c0 o0 v0) o1 v1) o2 c1 + typedef typename synthesize_covov_expression0::node_type lcl_covov_t; + + const lcl_covov_t* covov = static_cast(branch[0]); + const Type c0 = covov->t0(); + const Type& v0 = covov->t1(); + const Type& v1 = covov->t2(); + const Type c1 = static_cast*>(branch[1])->value(); + const details::operator_type o0 = expr_gen.get_operator(covov->f0()); + const details::operator_type o1 = expr_gen.get_operator(covov->f1()); + const details::operator_type o2 = operation; + + binary_functor_t f0 = covov->f0(); + binary_functor_t f1 = covov->f1(); + binary_functor_t f2 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o2,f2)) + return error_node(); + + exprtk_debug(("((c0 o0 v0) o1 v1) o2 c1\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "((t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; + } + }; + + struct synthesize_vococov_expression3 + { + typedef typename vococov_t::type3 node_type; + typedef typename vococov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // ((v0 o0 c0) o1 c1) o2 v1 + typedef typename synthesize_vococ_expression0::node_type lcl_vococ_t; + + const lcl_vococ_t* vococ = static_cast(branch[0]); + const Type& v0 = vococ->t0(); + const Type c0 = vococ->t1(); + const Type c1 = vococ->t2(); + const Type& v1 = static_cast*>(branch[1])->ref(); + const details::operator_type o0 = expr_gen.get_operator(vococ->f0()); + const details::operator_type o1 = expr_gen.get_operator(vococ->f1()); + const details::operator_type o2 = operation; + + binary_functor_t f0 = vococ->f0(); + binary_functor_t f1 = vococ->f1(); + binary_functor_t f2 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o2,f2)) + return error_node(); + + exprtk_debug(("((v0 o0 c0) o1 c1) o2 v1\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "((t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; + } + }; + + struct synthesize_vovovov_expression4 + { + typedef typename vovovov_t::type4 node_type; + typedef typename vovovov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // (v0 o0 (v1 o1 v2)) o2 v3 + typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; + + const lcl_vovov_t* vovov = static_cast(branch[0]); + const Type& v0 = vovov->t0(); + const Type& v1 = vovov->t1(); + const Type& v2 = vovov->t2(); + const Type& v3 = static_cast*>(branch[1])->ref(); + const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); + const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); + const details::operator_type o2 = operation; + + binary_functor_t f0 = vovov->f0(); + binary_functor_t f1 = vovov->f1(); + binary_functor_t f2 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o2,f2)) + return error_node(); + + exprtk_debug(("(v0 o0 (v1 o1 v2)) o2 v3\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "(t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; + } + }; + + struct synthesize_vovovoc_expression4 + { + typedef typename vovovoc_t::type4 node_type; + typedef typename vovovoc_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // ((v0 o0 (v1 o1 v2)) o2 c) + typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; + + const lcl_vovov_t* vovov = static_cast(branch[0]); + const Type& v0 = vovov->t0(); + const Type& v1 = vovov->t1(); + const Type& v2 = vovov->t2(); + const Type c = static_cast*>(branch[1])->value(); + const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); + const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); + const details::operator_type o2 = operation; + + binary_functor_t f0 = vovov->f0(); + binary_functor_t f1 = vovov->f1(); + binary_functor_t f2 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o2,f2)) + return error_node(); + + exprtk_debug(("((v0 o0 (v1 o1 v2)) o2 c)\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "(t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; + } + }; + + struct synthesize_vovocov_expression4 + { + typedef typename vovocov_t::type4 node_type; + typedef typename vovocov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // ((v0 o0 (v1 o1 c)) o2 v1) + typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; + + const lcl_vovoc_t* vovoc = static_cast(branch[0]); + const Type& v0 = vovoc->t0(); + const Type& v1 = vovoc->t1(); + const Type c = vovoc->t2(); + const Type& v2 = static_cast*>(branch[1])->ref(); + const details::operator_type o0 = expr_gen.get_operator(vovoc->f0()); + const details::operator_type o1 = expr_gen.get_operator(vovoc->f1()); + const details::operator_type o2 = operation; + + binary_functor_t f0 = vovoc->f0(); + binary_functor_t f1 = vovoc->f1(); + binary_functor_t f2 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o2,f2)) + return error_node(); + + exprtk_debug(("((v0 o0 (v1 o1 c)) o2 v1)\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "(t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; + } + }; + + struct synthesize_vocovov_expression4 + { + typedef typename vocovov_t::type4 node_type; + typedef typename vocovov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // ((v0 o0 (c o1 v1)) o2 v2) + typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; + + const lcl_vocov_t* vocov = static_cast(branch[0]); + const Type& v0 = vocov->t0(); + const Type c = vocov->t1(); + const Type& v1 = vocov->t2(); + const Type& v2 = static_cast*>(branch[1])->ref(); + const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); + const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); + const details::operator_type o2 = operation; + + binary_functor_t f0 = vocov->f0(); + binary_functor_t f1 = vocov->f1(); + binary_functor_t f2 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o2,f2)) + return error_node(); + + exprtk_debug(("((v0 o0 (c o1 v1)) o2 v2)\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "(t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; + } + }; + + struct synthesize_covovov_expression4 + { + typedef typename covovov_t::type4 node_type; + typedef typename covovov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // ((c o0 (v0 o1 v1)) o2 v2) + typedef typename synthesize_covov_expression1::node_type lcl_covov_t; + + const lcl_covov_t* covov = static_cast(branch[0]); + const Type c = covov->t0(); + const Type& v0 = covov->t1(); + const Type& v1 = covov->t2(); + const Type& v2 = static_cast*>(branch[1])->ref(); + const details::operator_type o0 = expr_gen.get_operator(covov->f0()); + const details::operator_type o1 = expr_gen.get_operator(covov->f1()); + const details::operator_type o2 = operation; + + binary_functor_t f0 = covov->f0(); + binary_functor_t f1 = covov->f1(); + binary_functor_t f2 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o2,f2)) + return error_node(); + + exprtk_debug(("((c o0 (v0 o1 v1)) o2 v2)\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "(t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; + } + }; + + struct synthesize_covocov_expression4 + { + typedef typename covocov_t::type4 node_type; + typedef typename covocov_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // ((c0 o0 (v0 o1 c1)) o2 v1) + typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t; + + const lcl_covoc_t* covoc = static_cast(branch[0]); + const Type c0 = covoc->t0(); + const Type& v0 = covoc->t1(); + const Type c1 = covoc->t2(); + const Type& v1 = static_cast*>(branch[1])->ref(); + const details::operator_type o0 = expr_gen.get_operator(covoc->f0()); + const details::operator_type o1 = expr_gen.get_operator(covoc->f1()); + const details::operator_type o2 = operation; + + binary_functor_t f0 = covoc->f0(); + binary_functor_t f1 = covoc->f1(); + binary_functor_t f2 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o2,f2)) + return error_node(); + + exprtk_debug(("((c0 o0 (v0 o1 c1)) o2 v1)\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "(t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; + } + }; + + struct synthesize_vocovoc_expression4 + { + typedef typename vocovoc_t::type4 node_type; + typedef typename vocovoc_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // ((v0 o0 (c0 o1 v1)) o2 c1) + typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; + + const lcl_vocov_t* vocov = static_cast(branch[0]); + const Type& v0 = vocov->t0(); + const Type c0 = vocov->t1(); + const Type& v1 = vocov->t2(); + const Type c1 = static_cast*>(branch[1])->value(); + const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); + const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); + const details::operator_type o2 = operation; + + binary_functor_t f0 = vocov->f0(); + binary_functor_t f1 = vocov->f1(); + binary_functor_t f2 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o2,f2)) + return error_node(); + + exprtk_debug(("((v0 o0 (c0 o1 v1)) o2 c1)\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "(t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; + } + }; + + struct synthesize_covovoc_expression4 + { + typedef typename covovoc_t::type4 node_type; + typedef typename covovoc_t::sf4_type sf4_type; + typedef typename node_type::T0 T0; + typedef typename node_type::T1 T1; + typedef typename node_type::T2 T2; + typedef typename node_type::T3 T3; + + static inline expression_node_ptr process(expression_generator& expr_gen, + const details::operator_type& operation, + expression_node_ptr (&branch)[2]) + { + // ((c0 o0 (v0 o1 v1)) o2 c1) + typedef typename synthesize_covov_expression1::node_type lcl_covov_t; + + const lcl_covov_t* covov = static_cast(branch[0]); + const Type c0 = covov->t0(); + const Type& v0 = covov->t1(); + const Type& v1 = covov->t2(); + const Type c1 = static_cast*>(branch[1])->value(); + const details::operator_type o0 = expr_gen.get_operator(covov->f0()); + const details::operator_type o1 = expr_gen.get_operator(covov->f1()); + const details::operator_type o2 = operation; + + binary_functor_t f0 = covov->f0(); + binary_functor_t f1 = covov->f1(); + binary_functor_t f2 = reinterpret_cast(0); + + details::free_node(*(expr_gen.node_allocator_),branch[0]); + details::free_node(*(expr_gen.node_allocator_),branch[1]); + + expression_node_ptr result = error_node(); + + const bool synthesis_result = + synthesize_sf4ext_expression::template compile + (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); + + if (synthesis_result) + return result; + else if (!expr_gen.valid_operator(o2,f2)) + return error_node(); + + exprtk_debug(("((c0 o0 (v0 o1 v1)) o2 c1)\n")); + + return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); + } + + static inline std::string id(expression_generator& expr_gen, + const details::operator_type o0, + const details::operator_type o1, + const details::operator_type o2) + { + return details::build_string() + << "(t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; + } + }; + + struct synthesize_vococov_expression4 + { + typedef typename vococov_t::type4 node_type; + static inline expression_node_ptr process(expression_generator&, const details::operator_type&, expression_node_ptr (&)[2]) + { + // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible + exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n")); + return error_node(); + } + + static inline std::string id(expression_generator&, + const details::operator_type, const details::operator_type, const details::operator_type) + { + return "INVALID"; + } + }; + #endif + + inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) + { + // Definition: uv o uv + details::operator_type o0 = static_cast*>(branch[0])->operation(); + details::operator_type o1 = static_cast*>(branch[1])->operation(); + const Type& v0 = static_cast*>(branch[0])->v(); + const Type& v1 = static_cast*>(branch[1])->v(); + unary_functor_t u0 = reinterpret_cast (0); + unary_functor_t u1 = reinterpret_cast (0); + binary_functor_t f = reinterpret_cast(0); + + if (!valid_operator(o0,u0)) + return error_node(); + else if (!valid_operator(o1,u1)) + return error_node(); + else if (!valid_operator(operation,f)) + return error_node(); + + expression_node_ptr result = error_node(); + + if ( + (details::e_neg == o0) && + (details::e_neg == o1) + ) + { + switch (operation) + { + // (-v0 + -v1) --> -(v0 + v1) + case details::e_add : result = (*this)(details::e_neg, + node_allocator_-> + allocate_rr > >(v0, v1)); + exprtk_debug(("(-v0 + -v1) --> -(v0 + v1)\n")); + break; + + // (-v0 - -v1) --> (v1 - v0) + case details::e_sub : result = node_allocator_-> + allocate_rr > >(v1, v0); + exprtk_debug(("(-v0 - -v1) --> (v1 - v0)\n")); + break; + + // (-v0 * -v1) --> (v0 * v1) + case details::e_mul : result = node_allocator_-> + allocate_rr > >(v0, v1); + exprtk_debug(("(-v0 * -v1) --> (v0 * v1)\n")); + break; + + // (-v0 / -v1) --> (v0 / v1) + case details::e_div : result = node_allocator_-> + allocate_rr > >(v0, v1); + exprtk_debug(("(-v0 / -v1) --> (v0 / v1)\n")); + break; + + default : break; + } + } + + if (0 == result) + { + result = node_allocator_-> + allocate_rrrrr >(v0, v1, u0, u1, f); + } + + details::free_all_nodes(*node_allocator_,branch); + return result; + } + + #undef basic_opr_switch_statements + #undef extended_opr_switch_statements + #undef unary_opr_switch_statements + + #ifndef exprtk_disable_string_capabilities + + #define string_opr_switch_statements \ + case_stmt(details:: e_lt ,details:: lt_op) \ + case_stmt(details:: e_lte ,details:: lte_op) \ + case_stmt(details:: e_gt ,details:: gt_op) \ + case_stmt(details:: e_gte ,details:: gte_op) \ + case_stmt(details:: e_eq ,details:: eq_op) \ + case_stmt(details:: e_ne ,details:: ne_op) \ + case_stmt(details::e_in ,details:: in_op) \ + case_stmt(details::e_like ,details:: like_op) \ + case_stmt(details::e_ilike,details::ilike_op) \ + + template + inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr, + T0 s0, T1 s1, + range_t rp0) + { + switch (opr) + { + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + allocate_ttt >,T0,T1> \ + (s0, s1, rp0); \ + + string_opr_switch_statements + #undef case_stmt + default : return error_node(); + } + } + + template + inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr, + T0 s0, T1 s1, + range_t rp1) + { + switch (opr) + { + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + allocate_ttt >,T0,T1> \ + (s0, s1, rp1); \ + + string_opr_switch_statements + #undef case_stmt + default : return error_node(); + } + } + + template + inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr, + T0 s0, T1 s1, + range_t rp0, range_t rp1) + { + switch (opr) + { + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + allocate_tttt >,T0,T1> \ + (s0, s1, rp0, rp1); \ + + string_opr_switch_statements + #undef case_stmt + default : return error_node(); + } + } + + template + inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1) + { + switch (opr) + { + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + allocate_tt >,T0,T1>(s0, s1); \ + + string_opr_switch_statements + #undef case_stmt + default : return error_node(); + } + } + + inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) + { + std::string& s0 = static_cast*>(branch[0])->ref(); + std::string& s1 = static_cast*>(branch[1])->ref(); + + return synthesize_sos_expression_impl(opr, s0, s1); + } + + inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) + { + std::string& s0 = static_cast*>(branch[0])->ref (); + std::string& s1 = static_cast*> (branch[1])->ref (); + range_t rp0 = static_cast*>(branch[0])->range(); + + static_cast*>(branch[0])->range_ref().clear(); + + free_node(*node_allocator_,branch[0]); + + return synthesize_str_xrox_expression_impl(opr, s0, s1, rp0); + } + + inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) + { + std::string& s0 = static_cast*> (branch[0])->ref (); + std::string& s1 = static_cast*>(branch[1])->ref (); + range_t rp1 = static_cast*>(branch[1])->range(); + + static_cast*>(branch[1])->range_ref().clear(); + + free_node(*node_allocator_,branch[1]); + + return synthesize_str_xoxr_expression_impl(opr, s0, s1, rp1); + } + + inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) + { + std::string& s0 = static_cast*> (branch[0])->ref (); + std::string s1 = static_cast*>(branch[1])->str (); + range_t rp1 = static_cast*>(branch[1])->range(); + + static_cast*>(branch[1])->range_ref().clear(); + + free_node(*node_allocator_,branch[1]); + + return synthesize_str_xoxr_expression_impl(opr, s0, s1, rp1); + } + + inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) + { + std::string& s0 = static_cast*>(branch[0])->ref (); + std::string& s1 = static_cast*>(branch[1])->ref (); + range_t rp0 = static_cast*>(branch[0])->range(); + range_t rp1 = static_cast*>(branch[1])->range(); + + static_cast*>(branch[0])->range_ref().clear(); + static_cast*>(branch[1])->range_ref().clear(); + + details::free_node(*node_allocator_,branch[0]); + details::free_node(*node_allocator_,branch[1]); + + return synthesize_str_xroxr_expression_impl(opr, s0, s1, rp0, rp1); + } + + inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) + { + std::string& s0 = static_cast< details::stringvar_node*>(branch[0])->ref(); + std::string s1 = static_cast*>(branch[1])->str(); + + details::free_node(*node_allocator_,branch[1]); + + return synthesize_sos_expression_impl(opr, s0, s1); + } + + inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) + { + std::string s0 = static_cast*>(branch[0])->str(); + std::string& s1 = static_cast< details::stringvar_node*>(branch[1])->ref(); + + details::free_node(*node_allocator_,branch[0]); + + return synthesize_sos_expression_impl(opr, s0, s1); + } + + inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) + { + std::string s0 = static_cast*>(branch[0])->str (); + std::string& s1 = static_cast*> (branch[1])->ref (); + range_t rp1 = static_cast*> (branch[1])->range(); + + static_cast*>(branch[1])->range_ref().clear(); + + details::free_node(*node_allocator_,branch[0]); + details::free_node(*node_allocator_,branch[1]); + + return synthesize_str_xoxr_expression_impl(opr, s0, s1, rp1); + } + + inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) + { + std::string& s0 = static_cast*> (branch[0])->ref (); + std::string s1 = static_cast*>(branch[1])->str (); + range_t rp0 = static_cast*> (branch[0])->range(); + + static_cast*>(branch[0])->range_ref().clear(); + + details::free_node(*node_allocator_,branch[0]); + details::free_node(*node_allocator_,branch[1]); + + return synthesize_str_xrox_expression_impl(opr, s0, s1, rp0); + } + + inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) + { + std::string& s0 = static_cast*> (branch[0])->ref (); + std::string s1 = static_cast*>(branch[1])->str (); + range_t rp0 = static_cast*> (branch[0])->range(); + range_t rp1 = static_cast*>(branch[1])->range(); + + static_cast*> (branch[0])->range_ref().clear(); + static_cast*>(branch[1])->range_ref().clear(); + + details::free_node(*node_allocator_,branch[0]); + details::free_node(*node_allocator_,branch[1]); + + return synthesize_str_xroxr_expression_impl(opr, s0, s1, rp0, rp1); + } + + inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) + { + const std::string s0 = static_cast*>(branch[0])->str(); + const std::string s1 = static_cast*>(branch[1])->str(); + + expression_node_ptr result = error_node(); + + if (details::e_add == opr) + result = node_allocator_->allocate_c >(s0 + s1); + else if (details::e_in == opr) + result = node_allocator_->allocate_c >(details::in_op ::process(s0,s1)); + else if (details::e_like == opr) + result = node_allocator_->allocate_c >(details::like_op ::process(s0,s1)); + else if (details::e_ilike == opr) + result = node_allocator_->allocate_c >(details::ilike_op::process(s0,s1)); + else + { + expression_node_ptr temp = synthesize_sos_expression_impl(opr, s0, s1); + + const Type v = temp->value(); + + details::free_node(*node_allocator_,temp); + + result = node_allocator_->allocate(v); + } + + details::free_all_nodes(*node_allocator_,branch); + + return result; + } + + inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) + { + const std::string s0 = static_cast*> (branch[0])->str (); + std::string s1 = static_cast*>(branch[1])->str (); + range_t rp1 = static_cast*>(branch[1])->range(); + + static_cast*>(branch[1])->range_ref().clear(); + + free_node(*node_allocator_,branch[0]); + free_node(*node_allocator_,branch[1]); + + return synthesize_str_xoxr_expression_impl(opr, s0, s1, rp1); + } + + inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) + { + std::string s0 = static_cast*>(branch[0])->str (); + std::string& s1 = static_cast*> (branch[1])->ref (); + range_t rp0 = static_cast*>(branch[0])->range(); + + static_cast*>(branch[0])->range_ref().clear(); + + free_node(*node_allocator_,branch[0]); + + return synthesize_str_xrox_expression_impl(opr, s0, s1, rp0); + } + + inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) + { + const std::string s0 = static_cast*>(branch[0])->str (); + std::string& s1 = static_cast*> (branch[1])->ref (); + range_t rp0 = static_cast*>(branch[0])->range(); + range_t rp1 = static_cast*> (branch[1])->range(); + + static_cast*>(branch[0])->range_ref().clear(); + static_cast*> (branch[1])->range_ref().clear(); + + free_node(*node_allocator_,branch[0]); + free_node(*node_allocator_,branch[1]); + + return synthesize_str_xroxr_expression_impl(opr, s0, s1, rp0, rp1); + } + + inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) + { + std::string s0 = static_cast*>(branch[0])->str (); + const std::string s1 = static_cast*> (branch[1])->str (); + range_t rp0 = static_cast*>(branch[0])->range(); + + static_cast*>(branch[0])->range_ref().clear(); + + details::free_all_nodes(*node_allocator_,branch); + + return synthesize_str_xrox_expression_impl(opr, s0, s1, rp0); + } + + inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) + { + std::string s0 = static_cast*>(branch[0])->str (); + std::string s1 = static_cast*>(branch[1])->str (); + range_t rp0 = static_cast*>(branch[0])->range(); + range_t rp1 = static_cast*>(branch[1])->range(); + + static_cast*>(branch[0])->range_ref().clear(); + static_cast*>(branch[1])->range_ref().clear(); + + details::free_all_nodes(*node_allocator_,branch); + + return synthesize_str_xroxr_expression_impl(opr, s0, s1, rp0, rp1); + } + + inline expression_node_ptr synthesize_strogen_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) + { + switch (opr) + { + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + allocate_ttt > > \ + (opr, branch[0], branch[1]); \ + + string_opr_switch_statements + #undef case_stmt + default : return error_node(); + } + } + #endif + + #ifndef exprtk_disable_string_capabilities + inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) + { + if ((0 == branch[0]) || (0 == branch[1])) + { + details::free_all_nodes(*node_allocator_,branch); + + return error_node(); + } + + const bool b0_is_s = details::is_string_node (branch[0]); + const bool b0_is_cs = details::is_const_string_node (branch[0]); + const bool b0_is_sr = details::is_string_range_node (branch[0]); + const bool b0_is_csr = details::is_const_string_range_node(branch[0]); + + const bool b1_is_s = details::is_string_node (branch[1]); + const bool b1_is_cs = details::is_const_string_node (branch[1]); + const bool b1_is_sr = details::is_string_range_node (branch[1]); + const bool b1_is_csr = details::is_const_string_range_node(branch[1]); + + const bool b0_is_gen = details::is_string_assignment_node (branch[0]) || + details::is_genricstring_range_node(branch[0]) || + details::is_string_concat_node (branch[0]) || + details::is_string_function_node (branch[0]) || + details::is_string_condition_node (branch[0]) || + details::is_string_ccondition_node (branch[0]) || + details::is_string_vararg_node (branch[0]) ; + + const bool b1_is_gen = details::is_string_assignment_node (branch[1]) || + details::is_genricstring_range_node(branch[1]) || + details::is_string_concat_node (branch[1]) || + details::is_string_function_node (branch[1]) || + details::is_string_condition_node (branch[1]) || + details::is_string_ccondition_node (branch[1]) || + details::is_string_vararg_node (branch[1]) ; + + if (details::e_add == opr) + { + if (!b0_is_cs || !b1_is_cs) + { + return synthesize_expression(opr,branch); + } + } + + if (b0_is_gen || b1_is_gen) + { + return synthesize_strogen_expression(opr,branch); + } + else if (b0_is_s) + { + if (b1_is_s ) return synthesize_sos_expression (opr,branch); + else if (b1_is_cs ) return synthesize_socs_expression (opr,branch); + else if (b1_is_sr ) return synthesize_sosr_expression (opr,branch); + else if (b1_is_csr) return synthesize_socsr_expression (opr,branch); + } + else if (b0_is_cs) + { + if (b1_is_s ) return synthesize_csos_expression (opr,branch); + else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch); + else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch); + else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch); + } + else if (b0_is_sr) + { + if (b1_is_s ) return synthesize_sros_expression (opr,branch); + else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch); + else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch); + else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch); + } + else if (b0_is_csr) + { + if (b1_is_s ) return synthesize_csros_expression (opr,branch); + else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch); + else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch); + else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch); + } + + return error_node(); + } + #else + inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2]) + { + details::free_all_nodes(*node_allocator_,branch); + return error_node(); + } + #endif + + #ifndef exprtk_disable_string_capabilities + inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3]) + { + if (details::e_inrange != opr) + return error_node(); + else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2])) + { + details::free_all_nodes(*node_allocator_,branch); + + return error_node(); + } + else if ( + details::is_const_string_node(branch[0]) && + details::is_const_string_node(branch[1]) && + details::is_const_string_node(branch[2]) + ) + { + const std::string s0 = static_cast*>(branch[0])->str(); + const std::string s1 = static_cast*>(branch[1])->str(); + const std::string s2 = static_cast*>(branch[2])->str(); + + const Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0)); + + details::free_all_nodes(*node_allocator_,branch); + + return node_allocator_->allocate_c >(v); + } + else if ( + details::is_string_node(branch[0]) && + details::is_string_node(branch[1]) && + details::is_string_node(branch[2]) + ) + { + std::string& s0 = static_cast*>(branch[0])->ref(); + std::string& s1 = static_cast*>(branch[1])->ref(); + std::string& s2 = static_cast*>(branch[2])->ref(); + + typedef typename details::sosos_node > inrange_t; + + return node_allocator_->allocate_type(s0, s1, s2); + } + else if ( + details::is_const_string_node(branch[0]) && + details::is_string_node(branch[1]) && + details::is_const_string_node(branch[2]) + ) + { + std::string s0 = static_cast*>(branch[0])->str(); + std::string& s1 = static_cast< details::stringvar_node*>(branch[1])->ref(); + std::string s2 = static_cast*>(branch[2])->str(); + + typedef typename details::sosos_node > inrange_t; + + details::free_node(*node_allocator_,branch[0]); + details::free_node(*node_allocator_,branch[2]); + + return node_allocator_->allocate_type(s0, s1, s2); + } + else if ( + details::is_string_node(branch[0]) && + details::is_const_string_node(branch[1]) && + details::is_string_node(branch[2]) + ) + { + std::string& s0 = static_cast< details::stringvar_node*>(branch[0])->ref(); + std::string s1 = static_cast*>(branch[1])->str(); + std::string& s2 = static_cast< details::stringvar_node*>(branch[2])->ref(); + + typedef typename details::sosos_node > inrange_t; + + details::free_node(*node_allocator_,branch[1]); + + return node_allocator_->allocate_type(s0, s1, s2); + } + else if ( + details::is_string_node(branch[0]) && + details::is_string_node(branch[1]) && + details::is_const_string_node(branch[2]) + ) + { + std::string& s0 = static_cast< details::stringvar_node*>(branch[0])->ref(); + std::string& s1 = static_cast< details::stringvar_node*>(branch[1])->ref(); + std::string s2 = static_cast*>(branch[2])->str(); + + typedef typename details::sosos_node > inrange_t; + + details::free_node(*node_allocator_,branch[2]); + + return node_allocator_->allocate_type(s0, s1, s2); + } + else if ( + details::is_const_string_node(branch[0]) && + details:: is_string_node(branch[1]) && + details:: is_string_node(branch[2]) + ) + { + std::string s0 = static_cast*>(branch[0])->str(); + std::string& s1 = static_cast< details::stringvar_node*>(branch[1])->ref(); + std::string& s2 = static_cast< details::stringvar_node*>(branch[2])->ref(); + + typedef typename details::sosos_node > inrange_t; + + details::free_node(*node_allocator_,branch[0]); + + return node_allocator_->allocate_type(s0, s1, s2); + } + else + return error_node(); + } + #else + inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3]) + { + details::free_all_nodes(*node_allocator_,branch); + return error_node(); + } + #endif + + inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) + { + /* + Note: The following are the type promotion rules + that relate to operations that include 'null': + 0. null ==/!= null --> true false + 1. null operation null --> null + 2. x ==/!= null --> true/false + 3. null ==/!= x --> true/false + 4. x operation null --> x + 5. null operation x --> x + */ + + typedef typename details::null_eq_node nulleq_node_t; + + const bool b0_null = details::is_null_node(branch[0]); + const bool b1_null = details::is_null_node(branch[1]); + + if (b0_null && b1_null) + { + expression_node_ptr result = error_node(); + + if (details::e_eq == operation) + result = node_allocator_->allocate_c(T(1)); + else if (details::e_ne == operation) + result = node_allocator_->allocate_c(T(0)); + + if (result) + { + details::free_node(*node_allocator_,branch[0]); + details::free_node(*node_allocator_,branch[1]); + + return result; + } + + details::free_node(*node_allocator_,branch[1]); + + return branch[0]; + } + else if (details::e_eq == operation) + { + expression_node_ptr result = node_allocator_-> + allocate_rc(branch[b0_null ? 0 : 1],true); + + details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]); + + return result; + } + else if (details::e_ne == operation) + { + expression_node_ptr result = node_allocator_-> + allocate_rc(branch[b0_null ? 0 : 1],false); + + details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]); + + return result; + } + else if (b0_null) + { + details::free_node(*node_allocator_,branch[0]); + branch[0] = branch[1]; + branch[1] = error_node(); + } + else if (b1_null) + { + details::free_node(*node_allocator_,branch[1]); + branch[1] = error_node(); + } + + if ( + (details::e_add == operation) || (details::e_sub == operation) || + (details::e_mul == operation) || (details::e_div == operation) || + (details::e_mod == operation) || (details::e_pow == operation) + ) + { + return branch[0]; + } + else if ( + (details::e_lt == operation) || (details::e_lte == operation) || + (details::e_gt == operation) || (details::e_gte == operation) || + (details::e_and == operation) || (details::e_nand == operation) || + (details::e_or == operation) || (details::e_nor == operation) || + (details::e_xor == operation) || (details::e_xnor == operation) || + (details::e_in == operation) || (details::e_like == operation) || + (details::e_ilike == operation) + ) + { + return node_allocator_->allocate_c(T(0)); + } + + details::free_node(*node_allocator_,branch[0]); + + return node_allocator_->allocate >(); + } + + template + inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N]) + { + if ( + (details::e_in == operation) || + (details::e_like == operation) || + (details::e_ilike == operation) + ) + { + free_all_nodes(*node_allocator_,branch); + + return error_node(); + } + else if (!details::all_nodes_valid(branch)) + { + free_all_nodes(*node_allocator_,branch); + + return error_node(); + } + else if ((details::e_default != operation)) + { + // Attempt simple constant folding optimisation. + expression_node_ptr expression_point = node_allocator_->allocate(operation,branch); + + if (is_constant_foldable(branch)) + { + Type v = expression_point->value(); + details::free_node(*node_allocator_,expression_point); + + return node_allocator_->allocate(v); + } + else + return expression_point; + } + else + return error_node(); + } + + template + inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N]) + { + if (!details::all_nodes_valid(branch)) + { + free_all_nodes(*node_allocator_,branch); + + return error_node(); + } + + typedef typename details::function_N_node function_N_node_t; + + // Attempt simple constant folding optimisation. + + expression_node_ptr expression_point = node_allocator_->allocate(f); + function_N_node_t* func_node_ptr = dynamic_cast(expression_point); + + if (0 == func_node_ptr) + { + free_all_nodes(*node_allocator_,branch); + + return error_node(); + } + else + func_node_ptr->init_branches(branch); + + if (is_constant_foldable(branch) && !f->has_side_effects()) + { + Type v = expression_point->value(); + details::free_node(*node_allocator_,expression_point); + + return node_allocator_->allocate(v); + } + + parser_->state_.activate_side_effect("synthesize_expression(function)"); + + return expression_point; + } + + bool strength_reduction_enabled_; + details::node_allocator* node_allocator_; + synthesize_map_t synthesize_map_; + unary_op_map_t* unary_op_map_; + binary_op_map_t* binary_op_map_; + inv_binary_op_map_t* inv_binary_op_map_; + sf3_map_t* sf3_map_; + sf4_map_t* sf4_map_; + parser_t* parser_; + }; + + inline void set_error(const parser_error::type& error_type) + { + error_list_.push_back(error_type); + } + + inline void remove_last_error() + { + if (!error_list_.empty()) + { + error_list_.pop_back(); + } + } + + inline void set_synthesis_error(const std::string& synthesis_error_message) + { + if (synthesis_error_.empty()) + { + synthesis_error_ = synthesis_error_message; + } + } + + inline void register_local_vars(expression& e) + { + for (std::size_t i = 0; i < sem_.size(); ++i) + { + scope_element& se = sem_.get_element(i); + + if ( + (scope_element::e_variable == se.type) || + (scope_element::e_vecelem == se.type) + ) + { + if (se.var_node) + { + e.register_local_var(se.var_node); + } + + if (se.data) + { + e.register_local_data(se.data, 1, 0); + } + } + else if (scope_element::e_vector == se.type) + { + if (se.vec_node) + { + e.register_local_var(se.vec_node); + } + + if (se.data) + { + e.register_local_data(se.data, se.size, 1); + } + } + #ifndef exprtk_disable_string_capabilities + else if (scope_element::e_string == se.type) + { + if (se.str_node) + { + e.register_local_var(se.str_node); + } + + if (se.data) + { + e.register_local_data(se.data, se.size, 2); + } + } + #endif + + se.var_node = 0; + se.vec_node = 0; + #ifndef exprtk_disable_string_capabilities + se.str_node = 0; + #endif + se.data = 0; + se.ref_count = 0; + se.active = false; + } + } + + inline void register_return_results(expression& e) + { + e.register_return_results(results_context_); + results_context_ = 0; + } + + inline void load_unary_operations_map(unary_op_map_t& m) + { + #define register_unary_op(Op,UnaryFunctor) \ + m.insert(std::make_pair(Op,UnaryFunctor::process)); \ + + register_unary_op(details:: e_abs, details:: abs_op) + register_unary_op(details:: e_acos, details:: acos_op) + register_unary_op(details::e_acosh, details::acosh_op) + register_unary_op(details:: e_asin, details:: asin_op) + register_unary_op(details::e_asinh, details::asinh_op) + register_unary_op(details::e_atanh, details::atanh_op) + register_unary_op(details:: e_ceil, details:: ceil_op) + register_unary_op(details:: e_cos, details:: cos_op) + register_unary_op(details:: e_cosh, details:: cosh_op) + register_unary_op(details:: e_exp, details:: exp_op) + register_unary_op(details::e_expm1, details::expm1_op) + register_unary_op(details::e_floor, details::floor_op) + register_unary_op(details:: e_log, details:: log_op) + register_unary_op(details::e_log10, details::log10_op) + register_unary_op(details:: e_log2, details:: log2_op) + register_unary_op(details::e_log1p, details::log1p_op) + register_unary_op(details:: e_neg, details:: neg_op) + register_unary_op(details:: e_pos, details:: pos_op) + register_unary_op(details::e_round, details::round_op) + register_unary_op(details:: e_sin, details:: sin_op) + register_unary_op(details:: e_sinc, details:: sinc_op) + register_unary_op(details:: e_sinh, details:: sinh_op) + register_unary_op(details:: e_sqrt, details:: sqrt_op) + register_unary_op(details:: e_tan, details:: tan_op) + register_unary_op(details:: e_tanh, details:: tanh_op) + register_unary_op(details:: e_cot, details:: cot_op) + register_unary_op(details:: e_sec, details:: sec_op) + register_unary_op(details:: e_csc, details:: csc_op) + register_unary_op(details:: e_r2d, details:: r2d_op) + register_unary_op(details:: e_d2r, details:: d2r_op) + register_unary_op(details:: e_d2g, details:: d2g_op) + register_unary_op(details:: e_g2d, details:: g2d_op) + register_unary_op(details:: e_notl, details:: notl_op) + register_unary_op(details:: e_sgn, details:: sgn_op) + register_unary_op(details:: e_erf, details:: erf_op) + register_unary_op(details:: e_erfc, details:: erfc_op) + register_unary_op(details:: e_ncdf, details:: ncdf_op) + register_unary_op(details:: e_frac, details:: frac_op) + register_unary_op(details::e_trunc, details::trunc_op) + #undef register_unary_op + } + + inline void load_binary_operations_map(binary_op_map_t& m) + { + typedef typename binary_op_map_t::value_type value_type; + + #define register_binary_op(Op,BinaryFunctor) \ + m.insert(value_type(Op,BinaryFunctor::process)); \ + + register_binary_op(details:: e_add, details:: add_op) + register_binary_op(details:: e_sub, details:: sub_op) + register_binary_op(details:: e_mul, details:: mul_op) + register_binary_op(details:: e_div, details:: div_op) + register_binary_op(details:: e_mod, details:: mod_op) + register_binary_op(details:: e_pow, details:: pow_op) + register_binary_op(details:: e_lt, details:: lt_op) + register_binary_op(details:: e_lte, details:: lte_op) + register_binary_op(details:: e_gt, details:: gt_op) + register_binary_op(details:: e_gte, details:: gte_op) + register_binary_op(details:: e_eq, details:: eq_op) + register_binary_op(details:: e_ne, details:: ne_op) + register_binary_op(details:: e_and, details:: and_op) + register_binary_op(details::e_nand, details::nand_op) + register_binary_op(details:: e_or, details:: or_op) + register_binary_op(details:: e_nor, details:: nor_op) + register_binary_op(details:: e_xor, details:: xor_op) + register_binary_op(details::e_xnor, details::xnor_op) + #undef register_binary_op + } + + inline void load_inv_binary_operations_map(inv_binary_op_map_t& m) + { + typedef typename inv_binary_op_map_t::value_type value_type; + + #define register_binary_op(Op,BinaryFunctor) \ + m.insert(value_type(BinaryFunctor::process,Op)); \ + + register_binary_op(details:: e_add, details:: add_op) + register_binary_op(details:: e_sub, details:: sub_op) + register_binary_op(details:: e_mul, details:: mul_op) + register_binary_op(details:: e_div, details:: div_op) + register_binary_op(details:: e_mod, details:: mod_op) + register_binary_op(details:: e_pow, details:: pow_op) + register_binary_op(details:: e_lt, details:: lt_op) + register_binary_op(details:: e_lte, details:: lte_op) + register_binary_op(details:: e_gt, details:: gt_op) + register_binary_op(details:: e_gte, details:: gte_op) + register_binary_op(details:: e_eq, details:: eq_op) + register_binary_op(details:: e_ne, details:: ne_op) + register_binary_op(details:: e_and, details:: and_op) + register_binary_op(details::e_nand, details::nand_op) + register_binary_op(details:: e_or, details:: or_op) + register_binary_op(details:: e_nor, details:: nor_op) + register_binary_op(details:: e_xor, details:: xor_op) + register_binary_op(details::e_xnor, details::xnor_op) + #undef register_binary_op + } + + inline void load_sf3_map(sf3_map_t& sf3_map) + { + typedef std::pair pair_t; + + #define register_sf3(Op) \ + sf3_map[details::sf##Op##_op::id()] = pair_t(details::sf##Op##_op::process,details::e_sf##Op); \ + + register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03) + register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07) + register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11) + register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15) + register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19) + register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23) + register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27) + register_sf3(28) register_sf3(29) register_sf3(30) + #undef register_sf3 + + #define register_sf3_extid(Id, Op) \ + sf3_map[Id] = pair_t(details::sf##Op##_op::process,details::e_sf##Op); \ + + register_sf3_extid("(t-t)-t",23) // (t-t)-t --> t-(t+t) + #undef register_sf3_extid + } + + inline void load_sf4_map(sf4_map_t& sf4_map) + { + typedef std::pair pair_t; + + #define register_sf4(Op) \ + sf4_map[details::sf##Op##_op::id()] = pair_t(details::sf##Op##_op::process,details::e_sf##Op); \ + + register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51) + register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55) + register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59) + register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63) + register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67) + register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71) + register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75) + register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79) + register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83) + #undef register_sf4 + + #define register_sf4ext(Op) \ + sf4_map[details::sfext##Op##_op::id()] = pair_t(details::sfext##Op##_op::process,details::e_sf4ext##Op); \ + + register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03) + register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07) + register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11) + register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15) + register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19) + register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23) + register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27) + register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31) + register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35) + register_sf4ext(36) register_sf4ext(36) register_sf4ext(38) register_sf4ext(39) + register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43) + register_sf4ext(44) register_sf4ext(45) register_sf4ext(46) register_sf4ext(47) + register_sf4ext(48) register_sf4ext(49) register_sf4ext(50) register_sf4ext(51) + register_sf4ext(52) register_sf4ext(53) register_sf4ext(54) register_sf4ext(55) + register_sf4ext(56) register_sf4ext(57) register_sf4ext(58) register_sf4ext(59) + register_sf4ext(60) register_sf4ext(61) + #undef register_sf4ext + } + + inline results_context_t& results_ctx() + { + if (0 == results_context_) + { + results_context_ = new results_context_t(); + } + + return (*results_context_); + } + + inline void return_cleanup() + { + #ifndef exprtk_disable_return_statement + if (results_context_) + { + delete results_context_; + results_context_ = 0; + } + + state_.return_stmt_present = false; + #endif + } + + private: + + parser(const parser&); + parser& operator=(const parser&); + + settings_store settings_; + expression_generator expression_generator_; + details::node_allocator node_allocator_; + symtab_store symtab_store_; + dependent_entity_collector dec_; + std::deque error_list_; + std::deque brkcnt_list_; + parser_state state_; + bool resolve_unknown_symbol_; + results_context_t* results_context_; + unknown_symbol_resolver* unknown_symbol_resolver_; + unknown_symbol_resolver default_usr_; + base_ops_map_t base_ops_map_; + unary_op_map_t unary_op_map_; + binary_op_map_t binary_op_map_; + inv_binary_op_map_t inv_binary_op_map_; + sf3_map_t sf3_map_; + sf4_map_t sf4_map_; + std::string synthesis_error_; + scope_element_manager sem_; + + lexer::helper::helper_assembly helper_assembly_; + + lexer::helper::commutative_inserter commutative_inserter_; + lexer::helper::operator_joiner operator_joiner_2_; + lexer::helper::operator_joiner operator_joiner_3_; + lexer::helper::symbol_replacer symbol_replacer_; + lexer::helper::bracket_checker bracket_checker_; + lexer::helper::numeric_checker numeric_checker_; + lexer::helper::sequence_validator sequence_validator_; + lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_; + + template + friend void details::disable_type_checking(ParserType& p); + }; + + namespace details + { + template + struct collector_helper + { + typedef exprtk::symbol_table symbol_table_t; + typedef exprtk::expression expression_t; + typedef exprtk::parser parser_t; + typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t; + typedef typename parser_t::unknown_symbol_resolver usr_t; + + struct resolve_as_vector : public parser_t::unknown_symbol_resolver + { + typedef exprtk::parser parser_t; + + resolve_as_vector() + : usr_t(usr_t::e_usrmode_extended) + {} + + virtual bool process(const std::string& unknown_symbol, + symbol_table_t& symbol_table, + std::string&) + { + static T v[1]; + symbol_table.add_vector(unknown_symbol,v); + return true; + } + }; + + static inline bool collection_pass(const std::string& expression_string, + std::set& symbol_set, + const bool collect_variables, + const bool collect_functions, + const bool vector_pass, + symbol_table_t& ext_symbol_table) + { + symbol_table_t symbol_table; + expression_t expression; + parser_t parser; + + resolve_as_vector vect_resolver; + + expression.register_symbol_table(symbol_table ); + expression.register_symbol_table(ext_symbol_table); + + if (vector_pass) + parser.enable_unknown_symbol_resolver(&vect_resolver); + else + parser.enable_unknown_symbol_resolver(); + + if (collect_variables) + parser.dec().collect_variables() = true; + + if (collect_functions) + parser.dec().collect_functions() = true; + + bool pass_result = false; + + details::disable_type_checking(parser); + + if (parser.compile(expression_string, expression)) + { + pass_result = true; + + std::deque symb_list; + parser.dec().symbols(symb_list); + + for (std::size_t i = 0; i < symb_list.size(); ++i) + { + symbol_set.insert(symb_list[i].first); + } + } + + return pass_result; + } + }; + } + + template class Sequence> + inline bool collect_variables(const std::string& expression, + Sequence& symbol_list) + { + typedef double T; + typedef details::collector_helper collect_t; + + collect_t::symbol_table_t null_symbol_table; + + std::set symbol_set; + + const bool variable_pass = collect_t::collection_pass + (expression, symbol_set, true, false, false, null_symbol_table); + const bool vector_pass = collect_t::collection_pass + (expression, symbol_set, true, false, true, null_symbol_table); + + if (!variable_pass && !vector_pass) + return false; + + std::set::iterator itr = symbol_set.begin(); + + while (symbol_set.end() != itr) + { + symbol_list.push_back(*itr); + ++itr; + } + + return true; + } + + template class Sequence> + inline bool collect_variables(const std::string& expression, + exprtk::symbol_table& extrnl_symbol_table, + Sequence& symbol_list) + { + typedef details::collector_helper collect_t; + + std::set symbol_set; + + const bool variable_pass = collect_t::collection_pass + (expression, symbol_set, true, false, false, extrnl_symbol_table); + const bool vector_pass = collect_t::collection_pass + (expression, symbol_set, true, false, true, extrnl_symbol_table); + + if (!variable_pass && !vector_pass) + return false; + + std::set::iterator itr = symbol_set.begin(); + + while (symbol_set.end() != itr) + { + symbol_list.push_back(*itr); + ++itr; + } + + return true; + } + + template class Sequence> + inline bool collect_functions(const std::string& expression, + Sequence& symbol_list) + { + typedef double T; + typedef details::collector_helper collect_t; + + collect_t::symbol_table_t null_symbol_table; + + std::set symbol_set; + + const bool variable_pass = collect_t::collection_pass + (expression, symbol_set, false, true, false, null_symbol_table); + const bool vector_pass = collect_t::collection_pass + (expression, symbol_set, false, true, true, null_symbol_table); + + if (!variable_pass && !vector_pass) + return false; + + std::set::iterator itr = symbol_set.begin(); + + while (symbol_set.end() != itr) + { + symbol_list.push_back(*itr); + ++itr; + } + + return true; + } + + template class Sequence> + inline bool collect_functions(const std::string& expression, + exprtk::symbol_table& extrnl_symbol_table, + Sequence& symbol_list) + { + typedef details::collector_helper collect_t; + + std::set symbol_set; + + const bool variable_pass = collect_t::collection_pass + (expression, symbol_set, false, true, false, extrnl_symbol_table); + const bool vector_pass = collect_t::collection_pass + (expression, symbol_set, false, true, true, extrnl_symbol_table); + + if (!variable_pass && !vector_pass) + return false; + + std::set::iterator itr = symbol_set.begin(); + + while (symbol_set.end() != itr) + { + symbol_list.push_back(*itr); + ++itr; + } + + return true; + } + + template + inline T integrate(const expression& e, + T& x, + const T& r0, const T& r1, + const std::size_t number_of_intervals = 1000000) + { + if (r0 > r1) + return T(0); + + const T h = (r1 - r0) / (T(2) * number_of_intervals); + T total_area = T(0); + + for (std::size_t i = 0; i < number_of_intervals; ++i) + { + x = r0 + T(2) * i * h; + const T y0 = e.value(); x += h; + const T y1 = e.value(); x += h; + const T y2 = e.value(); x += h; + total_area += h * (y0 + T(4) * y1 + y2) / T(3); + } + + return total_area; + } + + template + inline T integrate(const expression& e, + const std::string& variable_name, + const T& r0, const T& r1, + const std::size_t number_of_intervals = 1000000) + { + const symbol_table& sym_table = e.get_symbol_table(); + + if (!sym_table.valid()) + return std::numeric_limits::quiet_NaN(); + + details::variable_node* var = sym_table.get_variable(variable_name); + + if (var) + { + T& x = var->ref(); + T x_original = x; + T result = integrate(e, x, r0, r1, number_of_intervals); + x = x_original; + + return result; + } + else + return std::numeric_limits::quiet_NaN(); + } + + template + inline T derivative(const expression& e, + T& x, + const T& h = T(0.00000001)) + { + const T x_init = x; + const T _2h = T(2) * h; + + x = x_init + _2h; + const T y0 = e.value(); + x = x_init + h; + const T y1 = e.value(); + x = x_init - h; + const T y2 = e.value(); + x = x_init - _2h; + const T y3 = e.value(); + x = x_init; + + return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h); + } + + template + inline T second_derivative(const expression& e, + T& x, + const T& h = T(0.00001)) + { + const T x_init = x; + const T _2h = T(2) * h; + + const T y = e.value(); + x = x_init + _2h; + const T y0 = e.value(); + x = x_init + h; + const T y1 = e.value(); + x = x_init - h; + const T y2 = e.value(); + x = x_init - _2h; + const T y3 = e.value(); + x = x_init; + + return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h); + } + + template + inline T third_derivative(const expression& e, + T& x, + const T& h = T(0.0001)) + { + const T x_init = x; + const T _2h = T(2) * h; + + x = x_init + _2h; + const T y0 = e.value(); + x = x_init + h; + const T y1 = e.value(); + x = x_init - h; + const T y2 = e.value(); + x = x_init - _2h; + const T y3 = e.value(); + x = x_init; + + return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h); + } + + template + inline T derivative(const expression& e, + const std::string& variable_name, + const T& h = T(0.00000001)) + { + const symbol_table& sym_table = e.get_symbol_table(); + + if (!sym_table.valid()) + { + return std::numeric_limits::quiet_NaN(); + } + + details::variable_node* var = sym_table.get_variable(variable_name); + + if (var) + { + T& x = var->ref(); + T x_original = x; + T result = derivative(e, x, h); + x = x_original; + + return result; + } + else + return std::numeric_limits::quiet_NaN(); + } + + template + inline T second_derivative(const expression& e, + const std::string& variable_name, + const T& h = T(0.00001)) + { + const symbol_table& sym_table = e.get_symbol_table(); + + if (!sym_table.valid()) + { + return std::numeric_limits::quiet_NaN(); + } + + details::variable_node* var = sym_table.get_variable(variable_name); + + if (var) + { + T& x = var->ref(); + const T x_original = x; + const T result = second_derivative(e, x, h); + x = x_original; + + return result; + } + else + return std::numeric_limits::quiet_NaN(); + } + + template + inline T third_derivative(const expression& e, + const std::string& variable_name, + const T& h = T(0.0001)) + { + const symbol_table& sym_table = e.get_symbol_table(); + + if (!sym_table.valid()) + { + return std::numeric_limits::quiet_NaN(); + } + + details::variable_node* var = sym_table.get_variable(variable_name); + + if (var) + { + T& x = var->ref(); + const T x_original = x; + const T result = third_derivative(e, x, h); + x = x_original; + + return result; + } + else + return std::numeric_limits::quiet_NaN(); + } + + /* + Note: The following 'compute' routines are simple helpers, + for quickly setting up the required pieces of code in order + to evaluate an expression. By virtue of how they operate + there will be an overhead with regards to their setup and + teardown and hence should not be used in time critical + sections of code. + Furthermore they only assume a small sub set of variables, + no string variables or user defined functions. + */ + template + inline bool compute(const std::string& expression_string, T& result) + { + // No variables + symbol_table symbol_table; + symbol_table.add_constants(); + + expression expression; + expression.register_symbol_table(symbol_table); + + parser parser; + + if (parser.compile(expression_string,expression)) + { + result = expression.value(); + + return true; + } + else + return false; + } + + template + inline bool compute(const std::string& expression_string, + const T& x, + T& result) + { + // Only 'x' + static const std::string x_var("x"); + + symbol_table symbol_table; + symbol_table.add_constants(); + symbol_table.add_constant(x_var,x); + + expression expression; + expression.register_symbol_table(symbol_table); + + parser parser; + + if (parser.compile(expression_string,expression)) + { + result = expression.value(); + + return true; + } + else + return false; + } + + template + inline bool compute(const std::string& expression_string, + const T&x, const T& y, + T& result) + { + // Only 'x' and 'y' + static const std::string x_var("x"); + static const std::string y_var("y"); + + symbol_table symbol_table; + symbol_table.add_constants(); + symbol_table.add_constant(x_var,x); + symbol_table.add_constant(y_var,y); + + expression expression; + expression.register_symbol_table(symbol_table); + + parser parser; + + if (parser.compile(expression_string,expression)) + { + result = expression.value(); + + return true; + } + else + return false; + } + + template + inline bool compute(const std::string& expression_string, + const T& x, const T& y, const T& z, + T& result) + { + // Only 'x', 'y' or 'z' + static const std::string x_var("x"); + static const std::string y_var("y"); + static const std::string z_var("z"); + + symbol_table symbol_table; + symbol_table.add_constants(); + symbol_table.add_constant(x_var,x); + symbol_table.add_constant(y_var,y); + symbol_table.add_constant(z_var,z); + + expression expression; + expression.register_symbol_table(symbol_table); + + parser parser; + + if (parser.compile(expression_string,expression)) + { + result = expression.value(); + + return true; + } + else + return false; + } + + template + class polynomial : public ifunction + { + private: + + template + struct poly_impl { }; + + template + struct poly_impl + { + static inline T evaluate(const Type x, + const Type c12, const Type c11, const Type c10, const Type c9, const Type c8, + const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, + const Type c2, const Type c1, const Type c0) + { + // p(x) = c_12x^12 + c_11x^11 + c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 + return ((((((((((((c12 * x + c11) * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); + } + }; + + template + struct poly_impl + { + static inline T evaluate(const Type x, + const Type c11, const Type c10, const Type c9, const Type c8, const Type c7, + const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, + const Type c1, const Type c0) + { + // p(x) = c_11x^11 + c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 + return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); + } + }; + + template + struct poly_impl + { + static inline T evaluate(const Type x, + const Type c10, const Type c9, const Type c8, const Type c7, const Type c6, + const Type c5, const Type c4, const Type c3, const Type c2, const Type c1, + const Type c0) + { + // p(x) = c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 + return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); + } + }; + + template + struct poly_impl + { + static inline T evaluate(const Type x, + const Type c9, const Type c8, const Type c7, const Type c6, const Type c5, + const Type c4, const Type c3, const Type c2, const Type c1, const Type c0) + { + // p(x) = c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 + return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); + } + }; + + template + struct poly_impl + { + static inline T evaluate(const Type x, + const Type c8, const Type c7, const Type c6, const Type c5, const Type c4, + const Type c3, const Type c2, const Type c1, const Type c0) + { + // p(x) = c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 + return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); + } + }; + + template + struct poly_impl + { + static inline T evaluate(const Type x, + const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, + const Type c2, const Type c1, const Type c0) + { + // p(x) = c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 + return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); + } + }; + + template + struct poly_impl + { + static inline T evaluate(const Type x, + const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, + const Type c1, const Type c0) + { + // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 + return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); + } + }; + + template + struct poly_impl + { + static inline T evaluate(const Type x, + const Type c5, const Type c4, const Type c3, const Type c2, + const Type c1, const Type c0) + { + // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 + return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); + } + }; + + template + struct poly_impl + { + static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0) + { + // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 + return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0); + } + }; + + template + struct poly_impl + { + static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0) + { + // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 + return (((c3 * x + c2) * x + c1) * x + c0); + } + }; + + template + struct poly_impl + { + static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0) + { + // p(x) = c_2x^2 + c_1x^1 + c_0x^0 + return ((c2 * x + c1) * x + c0); + } + }; + + template + struct poly_impl + { + static inline T evaluate(const Type x, const Type c1, const Type c0) + { + // p(x) = c_1x^1 + c_0x^0 + return (c1 * x + c0); + } + }; + + public: + + using ifunction::operator(); + + polynomial() + : ifunction((N+2 <= 20) ? (N + 2) : std::numeric_limits::max()) + { + disable_has_side_effects(*this); + } + + virtual ~polynomial() + {} + + #define poly_rtrn(NN) \ + return (NN != N) ? std::numeric_limits::quiet_NaN() : + + inline virtual T operator() (const T& x, const T& c1, const T& c0) + { + poly_rtrn(1) poly_impl::evaluate(x,c1,c0); + } + + inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0) + { + poly_rtrn(2) poly_impl::evaluate(x,c2,c1,c0); + } + + inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0) + { + poly_rtrn(3) poly_impl::evaluate(x,c3,c2,c1,c0); + } + + inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) + { + poly_rtrn(4) poly_impl::evaluate(x,c4,c3,c2,c1,c0); + } + + inline virtual T operator() (const T& x, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) + { + poly_rtrn(5) poly_impl::evaluate(x,c5,c4,c3,c2,c1,c0); + } + + inline virtual T operator() (const T& x, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) + { + poly_rtrn(6) poly_impl::evaluate(x,c6,c5,c4,c3,c2,c1,c0); + } + + inline virtual T operator() (const T& x, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) + { + poly_rtrn(7) poly_impl::evaluate(x,c7,c6,c5,c4,c3,c2,c1,c0); + } + + inline virtual T operator() (const T& x, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) + { + poly_rtrn(8) poly_impl::evaluate(x,c8,c7,c6,c5,c4,c3,c2,c1,c0); + } + + inline virtual T operator() (const T& x, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) + { + poly_rtrn(9) poly_impl::evaluate(x,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0); + } + + inline virtual T operator() (const T& x, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) + { + poly_rtrn(10) poly_impl::evaluate(x,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0); + } + + inline virtual T operator() (const T& x, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) + { + poly_rtrn(11) poly_impl::evaluate(x,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0); + } + + inline virtual T operator() (const T& x, const T& c12, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) + { + poly_rtrn(12) poly_impl::evaluate(x,c12,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0); + } + + #undef poly_rtrn + + inline virtual T operator() () + { + return std::numeric_limits::quiet_NaN(); + } + + inline virtual T operator() (const T&) + { + return std::numeric_limits::quiet_NaN(); + } + + inline virtual T operator() (const T&, const T&) + { + return std::numeric_limits::quiet_NaN(); + } + }; + + template + class function_compositor + { + public: + + typedef exprtk::expression expression_t; + typedef exprtk::symbol_table symbol_table_t; + typedef exprtk::parser parser_t; + typedef typename parser_t::settings_store settings_t; + + struct function + { + function() + {} + + function(const std::string& n) + : name_(n) + {} + + function(const std::string& name, + const std::string& expression) + : name_(name), + expression_(expression) + {} + + function(const std::string& name, + const std::string& expression, + const std::string& v0) + : name_(name), + expression_(expression) + { + v_.push_back(v0); + } + + function(const std::string& name, + const std::string& expression, + const std::string& v0, const std::string& v1) + : name_(name), + expression_(expression) + { + v_.push_back(v0); v_.push_back(v1); + } + + function(const std::string& name, + const std::string& expression, + const std::string& v0, const std::string& v1, + const std::string& v2) + : name_(name), + expression_(expression) + { + v_.push_back(v0); v_.push_back(v1); + v_.push_back(v2); + } + + function(const std::string& name, + const std::string& expression, + const std::string& v0, const std::string& v1, + const std::string& v2, const std::string& v3) + : name_(name), + expression_(expression) + { + v_.push_back(v0); v_.push_back(v1); + v_.push_back(v2); v_.push_back(v3); + } + + function(const std::string& name, + const std::string& expression, + const std::string& v0, const std::string& v1, + const std::string& v2, const std::string& v3, + const std::string& v4) + : name_(name), + expression_(expression) + { + v_.push_back(v0); v_.push_back(v1); + v_.push_back(v2); v_.push_back(v3); + v_.push_back(v4); + } + + inline function& name(const std::string& n) + { + name_ = n; + return (*this); + } + + inline function& expression(const std::string& e) + { + expression_ = e; + return (*this); + } + + inline function& var(const std::string& v) + { + v_.push_back(v); + return (*this); + } + + std::string name_; + std::string expression_; + std::deque v_; + }; + + private: + + struct base_func : public exprtk::ifunction + { + typedef const T& type; + typedef exprtk::ifunction function_t; + typedef std::vector varref_t; + typedef std::vector var_t; + typedef std::pair lvarref_t; + typedef std::vector lvr_vec_t; + + using exprtk::ifunction::operator(); + + base_func(const std::size_t& pc = 0) + : exprtk::ifunction(pc), + local_var_stack_size(0), + stack_depth(0) + { + v.resize(pc); + } + + virtual ~base_func() + {} + + inline void update(const T& v0) + { + (*v[0]) = v0; + } + + inline void update(const T& v0, const T& v1) + { + (*v[0]) = v0; (*v[1]) = v1; + } + + inline void update(const T& v0, const T& v1, const T& v2) + { + (*v[0]) = v0; (*v[1]) = v1; + (*v[2]) = v2; + } + + inline void update(const T& v0, const T& v1, const T& v2, const T& v3) + { + (*v[0]) = v0; (*v[1]) = v1; + (*v[2]) = v2; (*v[3]) = v3; + } + + inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) + { + (*v[0]) = v0; (*v[1]) = v1; + (*v[2]) = v2; (*v[3]) = v3; + (*v[4]) = v4; + } + + inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) + { + (*v[0]) = v0; (*v[1]) = v1; + (*v[2]) = v2; (*v[3]) = v3; + (*v[4]) = v4; (*v[5]) = v5; + } + + inline function_t& setup(expression_t& expr) + { + expression = expr; + + typedef typename expression_t::control_block::local_data_list_t ldl_t; + + ldl_t ldl = expr.local_data_list(); + + std::vector index_list; + + for (std::size_t i = 0; i < ldl.size(); ++i) + { + if (ldl[i].size) + { + index_list.push_back(i); + } + } + + std::size_t input_param_count = 0; + + for (std::size_t i = 0; i < index_list.size(); ++i) + { + const std::size_t index = index_list[i]; + + if (i < (index_list.size() - v.size())) + { + lv.push_back( + std::make_pair( + reinterpret_cast(ldl[index].pointer), + ldl[index].size)); + + local_var_stack_size += ldl[index].size; + } + else + v[input_param_count++] = reinterpret_cast(ldl[index].pointer); + } + + clear_stack(); + + return (*this); + } + + inline void pre() + { + if (stack_depth++) + { + if (!v.empty()) + { + var_t var_stack(v.size(),T(0)); + copy(v,var_stack); + param_stack.push_back(var_stack); + } + + if (!lv.empty()) + { + var_t local_var_stack(local_var_stack_size,T(0)); + copy(lv,local_var_stack); + local_stack.push_back(local_var_stack); + } + } + } + + inline void post() + { + if (--stack_depth) + { + if (!v.empty()) + { + copy(param_stack.back(),v); + param_stack.pop_back(); + } + + if (!lv.empty()) + { + copy(local_stack.back(),lv); + local_stack.pop_back(); + } + } + } + + void copy(const varref_t& src_v, var_t& dest_v) + { + for (std::size_t i = 0; i < src_v.size(); ++i) + { + dest_v[i] = (*src_v[i]); + } + } + + void copy(const var_t& src_v, varref_t& dest_v) + { + for (std::size_t i = 0; i < src_v.size(); ++i) + { + (*dest_v[i]) = src_v[i]; + } + } + + void copy(const lvr_vec_t& src_v, var_t& dest_v) + { + typename var_t::iterator itr = dest_v.begin(); + typedef typename std::iterator_traits::difference_type diff_t; + + for (std::size_t i = 0; i < src_v.size(); ++i) + { + lvarref_t vr = src_v[i]; + + if (1 == vr.second) + *itr++ = (*vr.first); + else + { + std::copy(vr.first, vr.first + vr.second, itr); + itr += static_cast(vr.second); + } + } + } + + void copy(const var_t& src_v, lvr_vec_t& dest_v) + { + typename var_t::const_iterator itr = src_v.begin(); + typedef typename std::iterator_traits::difference_type diff_t; + + for (std::size_t i = 0; i < src_v.size(); ++i) + { + lvarref_t vr = dest_v[i]; + + if (1 == vr.second) + (*vr.first) = *itr++; + else + { + std::copy(itr, itr + static_cast(vr.second), vr.first); + itr += static_cast(vr.second); + } + } + } + + inline void clear_stack() + { + for (std::size_t i = 0; i < v.size(); ++i) + { + (*v[i]) = 0; + } + } + + inline virtual T value(expression_t& e) + { + return e.value(); + } + + expression_t expression; + varref_t v; + lvr_vec_t lv; + std::size_t local_var_stack_size; + std::size_t stack_depth; + std::deque param_stack; + std::deque local_stack; + }; + + typedef std::map funcparam_t; + + struct func_0param : public base_func + { + using exprtk::ifunction::operator(); + + func_0param() : base_func(0) {} + + inline T operator() () + { + return this->value(base_func::expression); + } + }; + + typedef const T& type; + + template + struct scoped_bft + { + scoped_bft(BaseFuncType& bft) : bft_(bft) { bft_.pre (); } + ~scoped_bft() { bft_.post(); } + + BaseFuncType& bft_; + + private: + + scoped_bft(scoped_bft&); + scoped_bft& operator=(scoped_bft&); + }; + + struct func_1param : public base_func + { + using exprtk::ifunction::operator(); + + func_1param() : base_func(1) {} + + inline T operator() (type v0) + { + scoped_bft sb(*this); + base_func::update(v0); + return this->value(base_func::expression); + } + }; + + struct func_2param : public base_func + { + using exprtk::ifunction::operator(); + + func_2param() : base_func(2) {} + + inline T operator() (type v0, type v1) + { + scoped_bft sb(*this); + base_func::update(v0, v1); + return this->value(base_func::expression); + } + }; + + struct func_3param : public base_func + { + using exprtk::ifunction::operator(); + + func_3param() : base_func(3) {} + + inline T operator() (type v0, type v1, type v2) + { + scoped_bft sb(*this); + base_func::update(v0, v1, v2); + return this->value(base_func::expression); + } + }; + + struct func_4param : public base_func + { + using exprtk::ifunction::operator(); + + func_4param() : base_func(4) {} + + inline T operator() (type v0, type v1, type v2, type v3) + { + scoped_bft sb(*this); + base_func::update(v0, v1, v2, v3); + return this->value(base_func::expression); + } + }; + + struct func_5param : public base_func + { + using exprtk::ifunction::operator(); + + func_5param() : base_func(5) {} + + inline T operator() (type v0, type v1, type v2, type v3, type v4) + { + scoped_bft sb(*this); + base_func::update(v0, v1, v2, v3, v4); + return this->value(base_func::expression); + } + }; + + struct func_6param : public base_func + { + using exprtk::ifunction::operator(); + + func_6param() : base_func(6) {} + + inline T operator() (type v0, type v1, type v2, type v3, type v4, type v5) + { + scoped_bft sb(*this); + base_func::update(v0, v1, v2, v3, v4, v5); + return this->value(base_func::expression); + } + }; + + static T return_value(expression_t& e) + { + typedef exprtk::results_context results_context_t; + typedef typename results_context_t::type_store_t type_t; + typedef typename type_t::scalar_view scalar_t; + + T result = e.value(); + + if (e.return_invoked()) + { + // Due to the post compilation checks, it can be safely + // assumed that there will be at least one parameter + // and that the first parameter will always be scalar. + return scalar_t(e.results()[0])(); + } + + return result; + } + + #define def_fp_retval(N) \ + struct func_##N##param_retval : public func_##N##param \ + { \ + inline T value(expression_t& e) \ + { \ + return return_value(e); \ + } \ + }; \ + + def_fp_retval(0) + def_fp_retval(1) + def_fp_retval(2) + def_fp_retval(3) + def_fp_retval(4) + def_fp_retval(5) + def_fp_retval(6) + + template class Sequence> + inline bool add(const std::string& name, + const std::string& expression, + const Sequence& var_list, + const bool override = false) + { + const typename std::map::iterator itr = expr_map_.find(name); + + if (expr_map_.end() != itr) + { + if (!override) + { + exprtk_debug(("Compositor error(add): function '%s' already defined\n", + name.c_str())); + + return false; + } + + remove(name, var_list.size()); + } + + if (compile_expression(name,expression,var_list)) + { + const std::size_t n = var_list.size(); + + fp_map_[n][name]->setup(expr_map_[name]); + + return true; + } + else + { + exprtk_debug(("Compositor error(add): Failed to compile function '%s'\n", + name.c_str())); + + return false; + } + } + + public: + + function_compositor() + : parser_(settings_t::compile_all_opts + + settings_t::e_disable_zero_return), + fp_map_(7) + {} + + function_compositor(const symbol_table_t& st) + : symbol_table_(st), + parser_(settings_t::compile_all_opts + + settings_t::e_disable_zero_return), + fp_map_(7) + {} + + ~function_compositor() + { + clear(); + } + + inline symbol_table_t& symbol_table() + { + return symbol_table_; + } + + inline void add_auxiliary_symtab(symbol_table_t& symtab) + { + auxiliary_symtab_list_.push_back(&symtab); + } + + void clear() + { + symbol_table_.clear(); + expr_map_ .clear(); + + for (std::size_t i = 0; i < fp_map_.size(); ++i) + { + typename funcparam_t::iterator itr = fp_map_[i].begin(); + typename funcparam_t::iterator end = fp_map_[i].end (); + + while (itr != end) + { + delete itr->second; + ++itr; + } + + fp_map_[i].clear(); + } + } + + inline bool add(const function& f, const bool override = false) + { + return add(f.name_, f.expression_, f.v_,override); + } + + private: + + template class Sequence> + bool compile_expression(const std::string& name, + const std::string& expression, + const Sequence& input_var_list, + bool return_present = false) + { + expression_t compiled_expression; + symbol_table_t local_symbol_table; + + local_symbol_table.load_from(symbol_table_); + local_symbol_table.add_constants(); + + if (!valid(name,input_var_list.size())) + return false; + + if (!forward(name, + input_var_list.size(), + local_symbol_table, + return_present)) + return false; + + compiled_expression.register_symbol_table(local_symbol_table); + + for (std::size_t i = 0; i < auxiliary_symtab_list_.size(); ++i) + { + compiled_expression.register_symbol_table((*auxiliary_symtab_list_[i])); + } + + std::string mod_expression; + + for (std::size_t i = 0; i < input_var_list.size(); ++i) + { + mod_expression += " var " + input_var_list[i] + "{};\n"; + } + + if ( + ('{' == details::front(expression)) && + ('}' == details::back (expression)) + ) + mod_expression += "~" + expression + ";"; + else + mod_expression += "~{" + expression + "};"; + + if (!parser_.compile(mod_expression,compiled_expression)) + { + exprtk_debug(("Compositor Error: %s\n",parser_.error().c_str())); + exprtk_debug(("Compositor modified expression: \n%s\n",mod_expression.c_str())); + + remove(name,input_var_list.size()); + + return false; + } + + if (!return_present && parser_.dec().return_present()) + { + remove(name,input_var_list.size()); + + return compile_expression(name, expression, input_var_list, true); + } + + // Make sure every return point has a scalar as its first parameter + if (parser_.dec().return_present()) + { + typedef std::vector str_list_t; + + str_list_t ret_param_list = parser_.dec().return_param_type_list(); + + for (std::size_t i = 0; i < ret_param_list.size(); ++i) + { + const std::string& params = ret_param_list[i]; + + if (params.empty() || ('T' != params[0])) + { + exprtk_debug(("Compositor Error: Return statement in function '%s' is invalid\n", + name.c_str())); + + remove(name,input_var_list.size()); + + return false; + } + } + } + + expr_map_[name] = compiled_expression; + + exprtk::ifunction& ifunc = (*(fp_map_[input_var_list.size()])[name]); + + if (symbol_table_.add_function(name,ifunc)) + return true; + else + { + exprtk_debug(("Compositor Error: Failed to add function '%s' to symbol table\n", + name.c_str())); + return false; + } + } + + inline bool symbol_used(const std::string& symbol) const + { + return ( + symbol_table_.is_variable (symbol) || + symbol_table_.is_stringvar (symbol) || + symbol_table_.is_function (symbol) || + symbol_table_.is_vector (symbol) || + symbol_table_.is_vararg_function(symbol) + ); + } + + inline bool valid(const std::string& name, + const std::size_t& arg_count) const + { + if (arg_count > 6) + return false; + else if (symbol_used(name)) + return false; + else if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name)) + return false; + else + return true; + } + + inline bool forward(const std::string& name, + const std::size_t& arg_count, + symbol_table_t& sym_table, + const bool ret_present = false) + { + switch (arg_count) + { + #define case_stmt(N) \ + case N : (fp_map_[arg_count])[name] = \ + (!ret_present) ? static_cast \ + (new func_##N##param) : \ + static_cast \ + (new func_##N##param_retval) ; \ + break; \ + + case_stmt(0) case_stmt(1) case_stmt(2) + case_stmt(3) case_stmt(4) case_stmt(5) + case_stmt(6) + #undef case_stmt + } + + exprtk::ifunction& ifunc = (*(fp_map_[arg_count])[name]); + + return sym_table.add_function(name,ifunc); + } + + inline void remove(const std::string& name, const std::size_t& arg_count) + { + if (arg_count > 6) + return; + + const typename std::map::iterator em_itr = expr_map_.find(name); + + if (expr_map_.end() != em_itr) + { + expr_map_.erase(em_itr); + } + + const typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name); + + if (fp_map_[arg_count].end() != fp_itr) + { + delete fp_itr->second; + fp_map_[arg_count].erase(fp_itr); + } + + symbol_table_.remove_function(name); + } + + private: + + symbol_table_t symbol_table_; + parser_t parser_; + std::map expr_map_; + std::vector fp_map_; + std::vector auxiliary_symtab_list_; + }; + + template + inline bool pgo_primer() + { + static const std::string expression_list[] + = { + "(y + x)", + "2 * (y + x)", + "(2 * y + 2 * x)", + "(y + x / y) * (x - y / x)", + "x / ((x + y) * (x - y)) / y", + "1 - ((x * y) + (y / x)) - 3", + "sin(2 * x) + cos(pi / y)", + "1 - sin(2 * x) + cos(pi / y)", + "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)", + "(x^2 / sin(2 * pi / y)) -x / 2", + "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y", + "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)", + "iclamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)", + "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))", + "if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x", + "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^4 - 5.5x^5 + 6.6y^6 - 7.7x^27 + 8.8y^55", + "(yy + xx)", + "2 * (yy + xx)", + "(2 * yy + 2 * xx)", + "(yy + xx / yy) * (xx - yy / xx)", + "xx / ((xx + yy) * (xx - yy)) / yy", + "1 - ((xx * yy) + (yy / xx)) - 3", + "sin(2 * xx) + cos(pi / yy)", + "1 - sin(2 * xx) + cos(pi / yy)", + "sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)", + "(xx^2 / sin(2 * pi / yy)) -xx / 2", + "xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy", + "clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)", + "max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))", + "if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx", + "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55", + "(1.1*(2.2*(3.3*(4.4*(5.5*(6.6*(7.7*(8.8*(9.9+x)))))))))", + "(((((((((x+9.9)*8.8)*7.7)*6.6)*5.5)*4.4)*3.3)*2.2)*1.1)", + "(x + y) * z", "x + (y * z)", "(x + y) * 7", "x + (y * 7)", + "(x + 7) * y", "x + (7 * y)", "(7 + x) * y", "7 + (x * y)", + "(2 + x) * 3", "2 + (x * 3)", "(2 + 3) * x", "2 + (3 * x)", + "(x + 2) * 3", "x + (2 * 3)", + "(x + y) * (z / w)", "(x + y) * (z / 7)", "(x + y) * (7 / z)", "(x + 7) * (y / z)", + "(7 + x) * (y / z)", "(2 + x) * (y / z)", "(x + 2) * (y / 3)", "(2 + x) * (y / 3)", + "(x + 2) * (3 / y)", "x + (y * (z / w))", "x + (y * (z / 7))", "x + (y * (7 / z))", + "x + (7 * (y / z))", "7 + (x * (y / z))", "2 + (x * (3 / y))", "x + (2 * (y / 4))", + "2 + (x * (y / 3))", "x + (2 * (3 / y))", + "x + ((y * z) / w)", "x + ((y * z) / 7)", "x + ((y * 7) / z)", "x + ((7 * y) / z)", + "7 + ((y * z) / w)", "2 + ((x * 3) / y)", "x + ((2 * y) / 3)", "2 + ((x * y) / 3)", + "x + ((2 * 3) / y)", "(((x + y) * z) / w)", + "(((x + y) * z) / 7)", "(((x + y) * 7) / z)", "(((x + 7) * y) / z)", "(((7 + x) * y) / z)", + "(((2 + x) * 3) / y)", "(((x + 2) * y) / 3)", "(((2 + x) * y) / 3)", "(((x + 2) * 3) / y)", + "((x + (y * z)) / w)", "((x + (y * z)) / 7)", "((x + (y * 7)) / y)", "((x + (7 * y)) / z)", + "((7 + (x * y)) / z)", "((2 + (x * 3)) / y)", "((x + (2 * y)) / 3)", "((2 + (x * y)) / 3)", + "((x + (2 * 3)) / y)", + "(xx + yy) * zz", "xx + (yy * zz)", + "(xx + yy) * 7", "xx + (yy * 7)", + "(xx + 7) * yy", "xx + (7 * yy)", + "(7 + xx) * yy", "7 + (xx * yy)", + "(2 + x) * 3", "2 + (x * 3)", + "(2 + 3) * x", "2 + (3 * x)", + "(x + 2) * 3", "x + (2 * 3)", + "(xx + yy) * (zz / ww)", "(xx + yy) * (zz / 7)", + "(xx + yy) * (7 / zz)", "(xx + 7) * (yy / zz)", + "(7 + xx) * (yy / zz)", "(2 + xx) * (yy / zz)", + "(xx + 2) * (yy / 3)", "(2 + xx) * (yy / 3)", + "(xx + 2) * (3 / yy)", "xx + (yy * (zz / ww))", + "xx + (yy * (zz / 7))", "xx + (yy * (7 / zz))", + "xx + (7 * (yy / zz))", "7 + (xx * (yy / zz))", + "2 + (xx * (3 / yy))", "xx + (2 * (yy / 4))", + "2 + (xx * (yy / 3))", "xx + (2 * (3 / yy))", + "xx + ((yy * zz) / ww)", "xx + ((yy * zz) / 7)", + "xx + ((yy * 7) / zz)", "xx + ((7 * yy) / zz)", + "7 + ((yy * zz) / ww)", "2 + ((xx * 3) / yy)", + "xx + ((2 * yy) / 3)", "2 + ((xx * yy) / 3)", + "xx + ((2 * 3) / yy)", "(((xx + yy) * zz) / ww)", + "(((xx + yy) * zz) / 7)", "(((xx + yy) * 7) / zz)", + "(((xx + 7) * yy) / zz)", "(((7 + xx) * yy) / zz)", + "(((2 + xx) * 3) / yy)", "(((xx + 2) * yy) / 3)", + "(((2 + xx) * yy) / 3)", "(((xx + 2) * 3) / yy)", + "((xx + (yy * zz)) / ww)", "((xx + (yy * zz)) / 7)", + "((xx + (yy * 7)) / yy)", "((xx + (7 * yy)) / zz)", + "((7 + (xx * yy)) / zz)", "((2 + (xx * 3)) / yy)", + "((xx + (2 * yy)) / 3)", "((2 + (xx * yy)) / 3)", + "((xx + (2 * 3)) / yy)" + }; + static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string); + + T x = T(0); + T y = T(0); + T z = T(0); + T w = T(0); + T xx = T(0); + T yy = T(0); + T zz = T(0); + T ww = T(0); + + exprtk::symbol_table symbol_table; + symbol_table.add_constants(); + symbol_table.add_variable( "x", x); + symbol_table.add_variable( "y", y); + symbol_table.add_variable( "z", z); + symbol_table.add_variable( "w", w); + symbol_table.add_variable("xx",xx); + symbol_table.add_variable("yy",yy); + symbol_table.add_variable("zz",zz); + symbol_table.add_variable("ww",ww); + + typedef typename std::deque > expr_list_t; + expr_list_t expr_list; + + const std::size_t rounds = 50; + + { + for (std::size_t r = 0; r < rounds; ++r) + { + expr_list.clear(); + exprtk::parser parser; + + for (std::size_t i = 0; i < expression_list_size; ++i) + { + exprtk::expression expression; + expression.register_symbol_table(symbol_table); + + if (!parser.compile(expression_list[i],expression)) + { + return false; + } + + expr_list.push_back(expression); + } + } + } + + struct execute + { + static inline T process(T& x, T& y, expression& expression) + { + static const T lower_bound = T(-20); + static const T upper_bound = T(+20); + static const T delta = T(0.1); + + T total = T(0); + + for (x = lower_bound; x <= upper_bound; x += delta) + { + for (y = lower_bound; y <= upper_bound; y += delta) + { + total += expression.value(); + } + } + + return total; + } + }; + + for (std::size_t i = 0; i < expr_list.size(); ++i) + { + execute::process( x, y, expr_list[i]); + execute::process(xx, yy, expr_list[i]); + } + + { + for (std::size_t i = 0; i < 10000; ++i) + { + const T v = T(123.456 + i); + + if (details::is_true(details::numeric::nequal(details::numeric::fast_exp::result(v),details::numeric::pow(v,T( 1))))) + return false; + + #define else_stmt(N) \ + else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp::result(v),details::numeric::pow(v,T(N))))) \ + return false; \ + + else_stmt( 2) else_stmt( 3) else_stmt( 4) else_stmt( 5) + else_stmt( 6) else_stmt( 7) else_stmt( 8) else_stmt( 9) + else_stmt(10) else_stmt(11) else_stmt(12) else_stmt(13) + else_stmt(14) else_stmt(15) else_stmt(16) else_stmt(17) + else_stmt(18) else_stmt(19) else_stmt(20) else_stmt(21) + else_stmt(22) else_stmt(23) else_stmt(24) else_stmt(25) + else_stmt(26) else_stmt(27) else_stmt(28) else_stmt(29) + else_stmt(30) else_stmt(31) else_stmt(32) else_stmt(33) + else_stmt(34) else_stmt(35) else_stmt(36) else_stmt(37) + else_stmt(38) else_stmt(39) else_stmt(40) else_stmt(41) + else_stmt(42) else_stmt(43) else_stmt(44) else_stmt(45) + else_stmt(46) else_stmt(47) else_stmt(48) else_stmt(49) + else_stmt(50) else_stmt(51) else_stmt(52) else_stmt(53) + else_stmt(54) else_stmt(55) else_stmt(56) else_stmt(57) + else_stmt(58) else_stmt(59) else_stmt(60) else_stmt(61) + } + } + + return true; + } +} + +#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# ifndef NOMINMAX +# define NOMINMAX +# endif +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include +# include +#else +# include +# include +# include +#endif + +namespace exprtk +{ + class timer + { + public: + + #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) + timer() + : in_use_(false) + { + QueryPerformanceFrequency(&clock_frequency_); + } + + inline void start() + { + in_use_ = true; + QueryPerformanceCounter(&start_time_); + } + + inline void stop() + { + QueryPerformanceCounter(&stop_time_); + in_use_ = false; + } + + inline double time() const + { + return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart); + } + + #else + + timer() + : in_use_(false) + { + start_time_.tv_sec = 0; + start_time_.tv_usec = 0; + stop_time_.tv_sec = 0; + stop_time_.tv_usec = 0; + } + + inline void start() + { + in_use_ = true; + gettimeofday(&start_time_,0); + } + + inline void stop() + { + gettimeofday(&stop_time_, 0); + in_use_ = false; + } + + inline unsigned long long int usec_time() const + { + if (!in_use_) + { + if (stop_time_.tv_sec >= start_time_.tv_sec) + { + return 1000000LLU * static_cast(stop_time_.tv_sec - start_time_.tv_sec ) + + static_cast(stop_time_.tv_usec - start_time_.tv_usec) ; + } + else + return std::numeric_limits::max(); + } + else + return std::numeric_limits::max(); + } + + inline double time() const + { + return usec_time() * 0.000001; + } + + #endif + + inline bool in_use() const + { + return in_use_; + } + + private: + + bool in_use_; + + #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) + LARGE_INTEGER start_time_; + LARGE_INTEGER stop_time_; + LARGE_INTEGER clock_frequency_; + #else + struct timeval start_time_; + struct timeval stop_time_; + #endif + }; + +} // namespace exprtk + +#ifndef exprtk_disable_rtl_io +namespace exprtk +{ + namespace rtl { namespace io { namespace details + { + template + inline void print_type(const std::string& fmt, + const T v, + exprtk::details::numeric::details::real_type_tag) + { + printf(fmt.c_str(),v); + } + + template + struct print_impl + { + typedef typename igeneric_function::generic_type generic_type; + typedef typename igeneric_function::parameter_list_t parameter_list_t; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + typedef typename generic_type::string_view string_t; + typedef typename exprtk::details::numeric::details::number_type::type num_type; + + static void process(const std::string& scalar_format, parameter_list_t parameters) + { + for (std::size_t i = 0; i < parameters.size(); ++i) + { + generic_type& gt = parameters[i]; + + switch (gt.type) + { + case generic_type::e_scalar : print(scalar_format,scalar_t(gt)); + break; + + case generic_type::e_vector : print(scalar_format,vector_t(gt)); + break; + + case generic_type::e_string : print(string_t(gt)); + break; + + default : continue; + } + } + } + + static inline void print(const std::string& scalar_format, const scalar_t& s) + { + print_type(scalar_format,s(),num_type()); + } + + static inline void print(const std::string& scalar_format, const vector_t& v) + { + for (std::size_t i = 0; i < v.size(); ++i) + { + print_type(scalar_format,v[i],num_type()); + + if ((i + 1) < v.size()) + printf(" "); + } + } + + static inline void print(const string_t& s) + { + printf("%s",to_str(s).c_str()); + } + }; + + } // namespace exprtk::rtl::io::details + + template + struct print : public exprtk::igeneric_function + { + typedef typename igeneric_function::parameter_list_t parameter_list_t; + + using exprtk::igeneric_function::operator(); + + print(const std::string& scalar_format = "%10.5f") + : scalar_format_(scalar_format) + { + exprtk::enable_zero_parameters(*this); + } + + inline T operator() (parameter_list_t parameters) + { + details::print_impl::process(scalar_format_,parameters); + return T(0); + } + + std::string scalar_format_; + }; + + template + struct println : public exprtk::igeneric_function + { + typedef typename igeneric_function::parameter_list_t parameter_list_t; + + using exprtk::igeneric_function::operator(); + + println(const std::string& scalar_format = "%10.5f") + : scalar_format_(scalar_format) + { + exprtk::enable_zero_parameters(*this); + } + + inline T operator() (parameter_list_t parameters) + { + details::print_impl::process(scalar_format_,parameters); + printf("\n"); + return T(0); + } + + std::string scalar_format_; + }; + + template + struct package + { + print p; + println pl; + + bool register_package(exprtk::symbol_table& symtab) + { + #define exprtk_register_function(FunctionName,FunctionType) \ + if (!symtab.add_function(FunctionName,FunctionType)) \ + { \ + exprtk_debug(( \ + "exprtk::rtl::io::register_package - Failed to add function: %s\n", \ + FunctionName)); \ + return false; \ + } \ + + exprtk_register_function("print" , p) + exprtk_register_function("println", pl) + #undef exprtk_register_function + + return true; + } + }; + + } // namespace exprtk::rtl::io + } // namespace exprtk::rtl +} // namespace exprtk +#endif + +#ifndef exprtk_disable_rtl_io_file +#include +namespace exprtk +{ + namespace rtl { namespace io { namespace file { namespace details + { + enum file_mode + { + e_error = 0, + e_read = 1, + e_write = 2, + e_rdwrt = 4 + }; + + struct file_descriptor + { + file_descriptor(const std::string& fname, const std::string& access) + : stream_ptr(0), + mode(get_file_mode(access)), + file_name(fname) + {} + + void* stream_ptr; + file_mode mode; + std::string file_name; + + bool open() + { + if (e_read == mode) + { + std::ifstream* stream = new std::ifstream(file_name.c_str(),std::ios::binary); + + if (!(*stream)) + { + file_name.clear(); + delete stream; + + return false; + } + else + stream_ptr = stream; + + return true; + } + else if (e_write == mode) + { + std::ofstream* stream = new std::ofstream(file_name.c_str(),std::ios::binary); + + if (!(*stream)) + { + file_name.clear(); + delete stream; + + return false; + } + else + stream_ptr = stream; + + return true; + } + else if (e_rdwrt == mode) + { + std::fstream* stream = new std::fstream(file_name.c_str(),std::ios::binary); + + if (!(*stream)) + { + file_name.clear(); + delete stream; + + return false; + } + else + stream_ptr = stream; + + return true; + } + else + return false; + } + + template + void close(Ptr& p) + { + Stream* stream = reinterpret_cast(p); + stream->close(); + delete stream; + p = reinterpret_cast(0); + } + + bool close() + { + switch (mode) + { + case e_read : close(stream_ptr); + break; + + case e_write : close(stream_ptr); + break; + + case e_rdwrt : close (stream_ptr); + break; + + default : return false; + } + + return true; + } + + template + bool write(const View& view, const std::size_t amount, const std::size_t offset = 0) + { + switch (mode) + { + case e_write : reinterpret_cast(stream_ptr)-> + write(reinterpret_cast(view.begin() + offset), amount * sizeof(typename View::value_t)); + break; + + case e_rdwrt : reinterpret_cast(stream_ptr)-> + write(reinterpret_cast(view.begin() + offset) , amount * sizeof(typename View::value_t)); + break; + + default : return false; + } + + return true; + } + + template + bool read(View& view, const std::size_t amount, const std::size_t offset = 0) + { + switch (mode) + { + case e_read : reinterpret_cast(stream_ptr)-> + read(reinterpret_cast(view.begin() + offset), amount * sizeof(typename View::value_t)); + break; + + case e_rdwrt : reinterpret_cast(stream_ptr)-> + read(reinterpret_cast(view.begin() + offset) , amount * sizeof(typename View::value_t)); + break; + + default : return false; + } + + return true; + } + + bool getline(std::string& s) + { + switch (mode) + { + case e_read : return (!!std::getline(*reinterpret_cast(stream_ptr),s)); + case e_rdwrt : return (!!std::getline(*reinterpret_cast(stream_ptr),s)); + default : return false; + } + } + + bool eof() const + { + switch (mode) + { + case e_read : return reinterpret_cast(stream_ptr)->eof(); + case e_write : return reinterpret_cast(stream_ptr)->eof(); + case e_rdwrt : return reinterpret_cast(stream_ptr)->eof(); + default : return true; + } + } + + file_mode get_file_mode(const std::string& access) const + { + if (access.empty() || access.size() > 2) + return e_error; + + std::size_t w_cnt = 0; + std::size_t r_cnt = 0; + + for (std::size_t i = 0; i < access.size(); ++i) + { + switch (std::tolower(access[i])) + { + case 'r' : r_cnt++; break; + case 'w' : w_cnt++; break; + default : return e_error; + } + } + + if ((0 == r_cnt) && (0 == w_cnt)) + return e_error; + else if ((r_cnt > 1) || (w_cnt > 1)) + return e_error; + else if ((1 == r_cnt) && (1 == w_cnt)) + return e_rdwrt; + else if (1 == r_cnt) + return e_read; + else + return e_write; + } + }; + + template + file_descriptor* make_handle(T v) + { + file_descriptor* fd = reinterpret_cast(0); + + std::memcpy(reinterpret_cast(&fd), + reinterpret_cast(&v), + sizeof(fd)); + return fd; + } + + template + void perform_check() + { + #ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable: 4127) + #endif + if (sizeof(T) < sizeof(void*)) + { + throw std::runtime_error("exprtk::rtl::io::file - Error - pointer size larger than holder."); + } + #ifdef _MSC_VER + #pragma warning(pop) + #endif + } + + } // namespace exprtk::rtl::io::file::details + + template + class open : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::string_view string_t; + + using exprtk::igeneric_function::operator(); + + open() + : exprtk::igeneric_function("S|SS") + { details::perform_check(); } + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + { + std::string file_name = to_str(string_t(parameters[0])); + std::string access; + + if (file_name.empty()) + return T(0); + + if (0 == ps_index) + access = "r"; + else if (0 == string_t(parameters[1]).size()) + return T(0); + else + access = to_str(string_t(parameters[1])); + + details::file_descriptor* fd = new details::file_descriptor(file_name,access); + + if (fd->open()) + { + T t = T(0); + + std::memcpy(reinterpret_cast(&t ), + reinterpret_cast(&fd), + sizeof(fd)); + return t; + } + else + { + delete fd; + return T(0); + } + } + }; + + template + struct close : public exprtk::ifunction + { + using exprtk::ifunction::operator(); + + close() + : exprtk::ifunction(1) + { details::perform_check(); } + + inline T operator() (const T& v) + { + details::file_descriptor* fd = details::make_handle(v); + + if (!fd->close()) + return T(0); + + delete fd; + + return T(1); + } + }; + + template + class write : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::string_view string_t; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + write() + : igfun_t("TS|TST|TV|TVT") + { details::perform_check(); } + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + { + details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); + + std::size_t amount = 0; + + switch (ps_index) + { + case 0 : { + const string_t buffer(parameters[1]); + amount = buffer.size(); + return T(fd->write(buffer, amount) ? 1 : 0); + } + + case 1 : { + const string_t buffer(parameters[1]); + amount = std::min(buffer.size(), + static_cast(scalar_t(parameters[2])())); + return T(fd->write(buffer, amount) ? 1 : 0); + } + + case 2 : { + const vector_t vec(parameters[1]); + amount = vec.size(); + return T(fd->write(vec, amount) ? 1 : 0); + } + + case 3 : { + const vector_t vec(parameters[1]); + amount = std::min(vec.size(), + static_cast(scalar_t(parameters[2])())); + return T(fd->write(vec, amount) ? 1 : 0); + } + } + + return T(0); + } + }; + + template + class read : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::string_view string_t; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + read() + : igfun_t("TS|TST|TV|TVT") + { details::perform_check(); } + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + { + details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); + + std::size_t amount = 0; + + switch (ps_index) + { + case 0 : { + string_t buffer(parameters[1]); + amount = buffer.size(); + return T(fd->read(buffer,amount) ? 1 : 0); + } + + case 1 : { + string_t buffer(parameters[1]); + amount = std::min(buffer.size(), + static_cast(scalar_t(parameters[2])())); + return T(fd->read(buffer,amount) ? 1 : 0); + } + + case 2 : { + vector_t vec(parameters[1]); + amount = vec.size(); + return T(fd->read(vec,amount) ? 1 : 0); + } + + case 3 : { + vector_t vec(parameters[1]); + amount = std::min(vec.size(), + static_cast(scalar_t(parameters[2])())); + return T(fd->read(vec,amount) ? 1 : 0); + } + } + + return T(0); + } + }; + + template + class getline : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::string_view string_t; + typedef typename generic_type::scalar_view scalar_t; + + using exprtk::igeneric_function::operator(); + + getline() + : igfun_t("T",igfun_t::e_rtrn_string) + { details::perform_check(); } + + inline T operator() (std::string& result, + parameter_list_t parameters) + { + details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); + return T(fd->getline(result) ? 1 : 0); + } + }; + + template + struct eof : public exprtk::ifunction + { + using exprtk::ifunction::operator(); + + eof() + : exprtk::ifunction(1) + { details::perform_check(); } + + inline T operator() (const T& v) + { + details::file_descriptor* fd = details::make_handle(v); + + return (fd->eof() ? T(1) : T(0)); + } + }; + + template + struct package + { + open o; + close c; + write w; + read r; + getline g; + eof e; + + bool register_package(exprtk::symbol_table& symtab) + { + #define exprtk_register_function(FunctionName,FunctionType) \ + if (!symtab.add_function(FunctionName,FunctionType)) \ + { \ + exprtk_debug(( \ + "exprtk::rtl::io::file::register_package - Failed to add function: %s\n", \ + FunctionName)); \ + return false; \ + } \ + + exprtk_register_function("open" ,o) + exprtk_register_function("close" ,c) + exprtk_register_function("write" ,w) + exprtk_register_function("read" ,r) + exprtk_register_function("getline",g) + exprtk_register_function("eof" ,e) + #undef exprtk_register_function + + return true; + } + }; + + } // namespace exprtk::rtl::io::file + } // namespace exprtk::rtl::io + } // namespace exprtk::rtl +} // namespace exprtk +#endif + +#ifndef exprtk_disable_rtl_vecops +namespace exprtk +{ + namespace rtl { namespace vecops { + + namespace helper + { + template + inline bool invalid_range(const Vector& v, const std::size_t r0, const std::size_t r1) + { + if (r0 > (v.size() - 1)) + return true; + else if (r1 > (v.size() - 1)) + return true; + else if (r1 < r0) + return true; + else + return false; + } + + template + struct load_vector_range + { + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + static inline bool process(parameter_list_t& parameters, + std::size_t& r0, std::size_t& r1, + const std::size_t& r0_prmidx, + const std::size_t& r1_prmidx, + const std::size_t vec_idx = 0) + { + if (r0_prmidx >= parameters.size()) + return false; + + if (r1_prmidx >= parameters.size()) + return false; + + if (!scalar_t(parameters[r0_prmidx]).to_uint(r0)) + return false; + + if (!scalar_t(parameters[r1_prmidx]).to_uint(r1)) + return false; + + return !invalid_range(vector_t(parameters[vec_idx]), r0, r1); + } + }; + } + + namespace details + { + template + inline void kahan_sum(T& sum, T& error, const T v) + { + const T x = v - error; + const T y = sum + x; + error = (y - sum) - x; + sum = y; + } + + } // namespace exprtk::rtl::details + + template + class all_true : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + all_true() + : exprtk::igeneric_function("V|VTT") + /* + Overloads: + 0. V - vector + 1. VTT - vector, r0, r1 + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + { + const vector_t vec(parameters[0]); + + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if ( + (1 == ps_index) && + !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0) + ) + return std::numeric_limits::quiet_NaN(); + + for (std::size_t i = r0; i <= r1; ++i) + { + if (vec[i] == T(0)) + { + return T(0); + } + } + + return T(1); + } + }; + + template + class all_false : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + all_false() + : exprtk::igeneric_function("V|VTT") + /* + Overloads: + 0. V - vector + 1. VTT - vector, r0, r1 + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + { + const vector_t vec(parameters[0]); + + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if ( + (1 == ps_index) && + !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0) + ) + return std::numeric_limits::quiet_NaN(); + + for (std::size_t i = r0; i <= r1; ++i) + { + if (vec[i] != T(0)) + { + return T(0); + } + } + + return T(1); + } + }; + + template + class any_true : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + any_true() + : exprtk::igeneric_function("V|VTT") + /* + Overloads: + 0. V - vector + 1. VTT - vector, r0, r1 + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + { + const vector_t vec(parameters[0]); + + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if ( + (1 == ps_index) && + !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0) + ) + return std::numeric_limits::quiet_NaN(); + + for (std::size_t i = r0; i <= r1; ++i) + { + if (vec[i] != T(0)) + { + return T(1); + } + } + + return T(0); + } + }; + + template + class any_false : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + any_false() + : exprtk::igeneric_function("V|VTT") + /* + Overloads: + 0. V - vector + 1. VTT - vector, r0, r1 + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + { + const vector_t vec(parameters[0]); + + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if ( + (1 == ps_index) && + !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0) + ) + return std::numeric_limits::quiet_NaN(); + + for (std::size_t i = r0; i <= r1; ++i) + { + if (vec[i] == T(0)) + { + return T(1); + } + } + + return T(0); + } + }; + + template + class count : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + count() + : exprtk::igeneric_function("V|VTT") + /* + Overloads: + 0. V - vector + 1. VTT - vector, r0, r1 + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + { + const vector_t vec(parameters[0]); + + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if ( + (1 == ps_index) && + !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0) + ) + return std::numeric_limits::quiet_NaN(); + + std::size_t cnt = 0; + + for (std::size_t i = r0; i <= r1; ++i) + { + if (vec[i] != T(0)) ++cnt; + } + + return T(cnt); + } + }; + + template + class copy : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + copy() + : exprtk::igeneric_function("VV|VTTVTT") + /* + Overloads: + 0. VV - x(vector), y(vector) + 1. VTTVTT - x(vector), xr0, xr1, y(vector), yr0, yr1, + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + { + const vector_t x(parameters[0]); + vector_t y(parameters[(0 == ps_index) ? 1 : 3]); + + std::size_t xr0 = 0; + std::size_t xr1 = x.size() - 1; + + std::size_t yr0 = 0; + std::size_t yr1 = y.size() - 1; + + if (1 == ps_index) + { + if ( + !helper::load_vector_range::process(parameters, xr0, xr1, 1, 2, 0) || + !helper::load_vector_range::process(parameters, yr0, yr1, 4, 5, 3) + ) + return T(0); + } + + const std::size_t n = std::min(xr1 - xr0 + 1, yr1 - yr0 + 1); + + std::copy(x.begin() + xr0, x.begin() + xr0 + n, y.begin() + yr0); + + return T(n); + } + }; + + template + class rol : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + rol() + : exprtk::igeneric_function("VT|VTTT") + /* + Overloads: + 0. VT - vector, N + 1. VTTT - vector, N, r0, r1 + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + { + vector_t vec(parameters[0]); + + std::size_t n = 0; + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if (!scalar_t(parameters[1]).to_uint(n)) + return T(0); + + if ( + (1 == ps_index) && + !helper::load_vector_range::process(parameters, r0, r1, 2, 3, 0) + ) + return T(0); + + std::size_t dist = r1 - r0 + 1; + std::size_t shift = n % dist; + + std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1); + + return T(1); + } + }; + + template + class ror : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + ror() + : exprtk::igeneric_function("VT|VTTT") + /* + Overloads: + 0. VT - vector, N + 1. VTTT - vector, N, r0, r1 + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + { + vector_t vec(parameters[0]); + + std::size_t n = 0; + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if (!scalar_t(parameters[1]).to_uint(n)) + return T(0); + + if ( + (1 == ps_index) && + !helper::load_vector_range::process(parameters, r0, r1, 2, 3, 0) + ) + return T(0); + + std::size_t dist = r1 - r0 + 1; + std::size_t shift = (dist - (n % dist)) % dist; + + std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1); + + return T(1); + } + }; + + template + class shift_left : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + shift_left() + : exprtk::igeneric_function("VT|VTTT") + /* + Overloads: + 0. VT - vector, N + 1. VTTT - vector, N, r0, r1 + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + { + vector_t vec(parameters[0]); + + std::size_t n = 0; + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if (!scalar_t(parameters[1]).to_uint(n)) + return T(0); + + if ( + (1 == ps_index) && + !helper::load_vector_range::process(parameters, r0, r1, 2, 3, 0) + ) + return T(0); + + std::size_t dist = r1 - r0 + 1; + + if (n > dist) + return T(0); + + std::rotate(vec.begin() + r0, vec.begin() + r0 + n, vec.begin() + r1 + 1); + + for (std::size_t i = r1 - n + 1; i <= r1; ++i) + { + vec[i] = T(0); + } + + return T(1); + } + }; + + template + class shift_right : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + shift_right() + : exprtk::igeneric_function("VT|VTTT") + /* + Overloads: + 0. VT - vector, N + 1. VTTT - vector, N, r0, r1 + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + { + vector_t vec(parameters[0]); + + std::size_t n = 0; + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if (!scalar_t(parameters[1]).to_uint(n)) + return T(0); + + if ( + (1 == ps_index) && + !helper::load_vector_range::process(parameters, r0, r1, 2, 3, 0) + ) + return T(0); + + std::size_t dist = r1 - r0 + 1; + + if (n > dist) + return T(0); + + std::size_t shift = (dist - (n % dist)) % dist; + + std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1); + + for (std::size_t i = r0; i < r0 + n; ++i) + { + vec[i] = T(0); + } + + return T(1); + } + }; + + template + class sort : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::string_view string_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + sort() + : exprtk::igeneric_function("V|VTT|VS|VSTT") + /* + Overloads: + 0. V - vector + 1. VTT - vector, r0, r1 + 2. VS - vector, string + 3. VSTT - vector, string, r0, r1 + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + { + vector_t vec(parameters[0]); + + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0)) + return T(0); + if ((3 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 2, 3, 0)) + return T(0); + + bool ascending = true; + + if ((2 == ps_index) || (3 == ps_index)) + { + if (exprtk::details::imatch(to_str(string_t(parameters[1])),"ascending")) + ascending = true; + else if (exprtk::details::imatch(to_str(string_t(parameters[1])),"descending")) + ascending = false; + else + return T(0); + } + + if (ascending) + std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::less ()); + else + std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::greater()); + + return T(1); + } + }; + + template + class nthelement : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + nthelement() + : exprtk::igeneric_function("VT|VTTT") + /* + Overloads: + 0. VT - vector, nth-element + 1. VTTT - vector, nth-element, r0, r1 + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + { + vector_t vec(parameters[0]); + + std::size_t n = 0; + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if (!scalar_t(parameters[1]).to_uint(n)) + return T(0); + + if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 2, 3, 0)) + return std::numeric_limits::quiet_NaN(); + + std::nth_element(vec.begin() + r0, vec.begin() + r0 + n , vec.begin() + r1 + 1); + + return T(1); + } + }; + + template + class iota : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + iota() + : exprtk::igeneric_function("VT|VTT|VTTT|VTTTT") + /* + Overloads: + 0. VT - vector, increment + 1. VTT - vector, increment, base + 2. VTTTT - vector, increment, r0, r1 + 3. VTTTT - vector, increment, base, r0, r1 + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + { + vector_t vec(parameters[0]); + + T increment = scalar_t(parameters[1])(); + T base = ((1 == ps_index) || (3 == ps_index)) ? scalar_t(parameters[2])() : T(0); + + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if ((2 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 2, 3, 0)) + return std::numeric_limits::quiet_NaN(); + else if ((3 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 3, 4, 0)) + return std::numeric_limits::quiet_NaN(); + else + { + long long j = 0; + + for (std::size_t i = r0; i <= r1; ++i, ++j) + { + vec[i] = base + (increment * j); + } + } + + return T(1); + } + }; + + template + class sumk : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + sumk() + : exprtk::igeneric_function("V|VTT") + /* + Overloads: + 0. V - vector + 1. VTT - vector, r0, r1 + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + { + const vector_t vec(parameters[0]); + + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0)) + return std::numeric_limits::quiet_NaN(); + + T result = T(0); + T error = T(0); + + for (std::size_t i = r0; i <= r1; ++i) + { + details::kahan_sum(result, error, vec[i]); + } + + return result; + } + }; + + template + class axpy : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + axpy() + : exprtk::igeneric_function("TVV|TVVTT") + /* + y <- ax + y + Overloads: + 0. TVV - a, x(vector), y(vector) + 1. TVVTT - a, x(vector), y(vector), r0, r1 + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + { + const vector_t x(parameters[1]); + vector_t y(parameters[2]); + + std::size_t r0 = 0; + std::size_t r1 = std::min(x.size(),y.size()) - 1; + + if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 3, 4, 1)) + return std::numeric_limits::quiet_NaN(); + else if (helper::invalid_range(y, r0, r1)) + return std::numeric_limits::quiet_NaN(); + + const T a = scalar_t(parameters[0])(); + + for (std::size_t i = r0; i <= r1; ++i) + { + y[i] = (a * x[i]) + y[i]; + } + + return T(1); + } + }; + + template + class axpby : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + axpby() + : exprtk::igeneric_function("TVTV|TVTVTT") + /* + y <- ax + by + Overloads: + 0. TVTV - a, x(vector), b, y(vector) + 1. TVTVTT - a, x(vector), b, y(vector), r0, r1 + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + { + const vector_t x(parameters[1]); + vector_t y(parameters[3]); + + std::size_t r0 = 0; + std::size_t r1 = std::min(x.size(),y.size()) - 1; + + if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 4, 5, 1)) + return std::numeric_limits::quiet_NaN(); + else if (helper::invalid_range(y, r0, r1)) + return std::numeric_limits::quiet_NaN(); + + const T a = scalar_t(parameters[0])(); + const T b = scalar_t(parameters[2])(); + + for (std::size_t i = r0; i <= r1; ++i) + { + y[i] = (a * x[i]) + (b * y[i]); + } + + return T(1); + } + }; + + template + class axpyz : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + axpyz() + : exprtk::igeneric_function("TVVV|TVVVTT") + /* + z <- ax + y + Overloads: + 0. TVVV - a, x(vector), y(vector), z(vector) + 1. TVVVTT - a, x(vector), y(vector), z(vector), r0, r1 + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + { + const vector_t x(parameters[1]); + const vector_t y(parameters[2]); + vector_t z(parameters[3]); + + std::size_t r0 = 0; + std::size_t r1 = std::min(x.size(),y.size()) - 1; + + if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 3, 4, 1)) + return std::numeric_limits::quiet_NaN(); + else if (helper::invalid_range(y, r0, r1)) + return std::numeric_limits::quiet_NaN(); + else if (helper::invalid_range(z, r0, r1)) + return std::numeric_limits::quiet_NaN(); + + const T a = scalar_t(parameters[0])(); + + for (std::size_t i = r0; i <= r1; ++i) + { + z[i] = (a * x[i]) + y[i]; + } + + return T(1); + } + }; + + template + class axpbyz : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + axpbyz() + : exprtk::igeneric_function("TVTVV|TVTVVTT") + /* + z <- ax + by + Overloads: + 0. TVTVV - a, x(vector), b, y(vector), z(vector) + 1. TVTVVTT - a, x(vector), b, y(vector), z(vector), r0, r1 + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + { + const vector_t x(parameters[1]); + const vector_t y(parameters[3]); + vector_t z(parameters[4]); + + std::size_t r0 = 0; + std::size_t r1 = std::min(x.size(),y.size()) - 1; + + if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 4, 5, 1)) + return std::numeric_limits::quiet_NaN(); + else if (helper::invalid_range(y, r0, r1)) + return std::numeric_limits::quiet_NaN(); + else if (helper::invalid_range(z, r0, r1)) + return std::numeric_limits::quiet_NaN(); + + const T a = scalar_t(parameters[0])(); + const T b = scalar_t(parameters[2])(); + + for (std::size_t i = r0; i <= r1; ++i) + { + z[i] = (a * x[i]) + (b * y[i]); + } + + return T(1); + } + }; + + template + class axpbz : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + axpbz() + : exprtk::igeneric_function("TVTV|TVTVTT") + /* + z <- ax + b + Overloads: + 0. TVTV - a, x(vector), b, z(vector) + 1. TVTVTT - a, x(vector), b, z(vector), r0, r1 + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + { + const vector_t x(parameters[1]); + vector_t z(parameters[3]); + + std::size_t r0 = 0; + std::size_t r1 = x.size() - 1; + + if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 4, 5, 1)) + return std::numeric_limits::quiet_NaN(); + else if (helper::invalid_range(z, r0, r1)) + return std::numeric_limits::quiet_NaN(); + + const T a = scalar_t(parameters[0])(); + const T b = scalar_t(parameters[2])(); + + for (std::size_t i = r0; i <= r1; ++i) + { + z[i] = (a * x[i]) + b; + } + + return T(1); + } + }; + + template + class dot : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + dot() + : exprtk::igeneric_function("VV|VVTT") + /* + Overloads: + 0. VV - x(vector), y(vector) + 1. VVTT - x(vector), y(vector), r0, r1 + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + { + const vector_t x(parameters[0]); + const vector_t y(parameters[1]); + + std::size_t r0 = 0; + std::size_t r1 = std::min(x.size(),y.size()) - 1; + + if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 2, 3, 0)) + return std::numeric_limits::quiet_NaN(); + else if (helper::invalid_range(y, r0, r1)) + return std::numeric_limits::quiet_NaN(); + + T result = T(0); + + for (std::size_t i = r0; i <= r1; ++i) + { + result += (x[i] * y[i]); + } + + return result; + } + }; + + template + class dotk : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + dotk() + : exprtk::igeneric_function("VV|VVTT") + /* + Overloads: + 0. VV - x(vector), y(vector) + 1. VVTT - x(vector), y(vector), r0, r1 + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + { + const vector_t x(parameters[0]); + const vector_t y(parameters[1]); + + std::size_t r0 = 0; + std::size_t r1 = std::min(x.size(),y.size()) - 1; + + if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 2, 3, 0)) + return std::numeric_limits::quiet_NaN(); + else if (helper::invalid_range(y, r0, r1)) + return std::numeric_limits::quiet_NaN(); + + T result = T(0); + T error = T(0); + + for (std::size_t i = r0; i <= r1; ++i) + { + details::kahan_sum(result, error, (x[i] * y[i])); + } + + return result; + } + }; + + template + struct package + { + all_true at; + all_false af; + any_true nt; + any_false nf; + count c; + copy cp; + rol rl; + ror rr; + shift_left sl; + shift_right sr; + sort st; + nthelement ne; + iota ia; + sumk sk; + axpy b1_axpy; + axpby b1_axpby; + axpyz b1_axpyz; + axpbyz b1_axpbyz; + axpbz b1_axpbz; + dot dt; + dotk dtk; + + bool register_package(exprtk::symbol_table& symtab) + { + #define exprtk_register_function(FunctionName,FunctionType) \ + if (!symtab.add_function(FunctionName,FunctionType)) \ + { \ + exprtk_debug(( \ + "exprtk::rtl::vecops::register_package - Failed to add function: %s\n", \ + FunctionName)); \ + return false; \ + } \ + + exprtk_register_function("all_true" ,at) + exprtk_register_function("all_false" ,af) + exprtk_register_function("any_true" ,nt) + exprtk_register_function("any_false" ,nf) + exprtk_register_function("count" , c) + exprtk_register_function("copy" ,cp) + exprtk_register_function("rotate_left" ,rl) + exprtk_register_function("rol" ,rl) + exprtk_register_function("rotate_right" ,rr) + exprtk_register_function("ror" ,rr) + exprtk_register_function("shftl" ,sl) + exprtk_register_function("shftr" ,sr) + exprtk_register_function("sort" ,st) + exprtk_register_function("nth_element" ,ne) + exprtk_register_function("iota" ,ia) + exprtk_register_function("sumk" ,sk) + exprtk_register_function("axpy" ,b1_axpy) + exprtk_register_function("axpby" ,b1_axpby) + exprtk_register_function("axpyz" ,b1_axpyz) + exprtk_register_function("axpbyz",b1_axpbyz) + exprtk_register_function("axpbz" ,b1_axpbz) + exprtk_register_function("dot" ,dt) + exprtk_register_function("dotk" ,dtk) + #undef exprtk_register_function + + return true; + } + }; + + } // namespace exprtk::rtl::vecops + } // namespace exprtk::rtl +} // namespace exprtk +#endif + +namespace exprtk +{ + namespace information + { + static const char* library = "Mathematical Expression Toolkit"; + static const char* version = "2.7182818284590452353602874713526624977572470936999595749" + "669676277240766303535475945713821785251664274274663919320"; + static const char* date = "20200101"; + + static inline std::string data() + { + static const std::string info_str = std::string(library) + + std::string(" v") + std::string(version) + + std::string(" (") + date + std::string(")"); + return info_str; + } + + } // namespace information + + #ifdef exprtk_debug + #undef exprtk_debug + #endif + + #ifdef exprtk_error_location + #undef exprtk_error_location + #endif + + #ifdef exprtk_disable_fallthrough_begin + #undef exprtk_disable_fallthrough_begin + #endif + + #ifdef exprtk_disable_fallthrough_end + #undef exprtk_disable_fallthrough_end + #endif + +} // namespace exprtk + +#endif diff --git a/external/libsoda/.travis.yml b/external/libsoda/.travis.yml new file mode 100644 index 00000000..df47800d --- /dev/null +++ b/external/libsoda/.travis.yml @@ -0,0 +1,25 @@ +language: cpp +branches: + only: + - master + - devel + +compiler: + - clang + - gcc + +matrix: + # works on Precise and Trusty + - os: linux + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-5 + env: + - MATRIX_EVAL="CC=gcc-5 && CXX=g++-5" + +script: + - cmake . && make && ctest --output-on-failure + diff --git a/external/libsoda/CMakeLists.txt b/external/libsoda/CMakeLists.txt new file mode 100644 index 00000000..203d1de8 --- /dev/null +++ b/external/libsoda/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 2.8) + +find_package(Threads REQUIRED) + +add_library(lsoda ${CMAKE_CURRENT_SOURCE_DIR}/LSODA.cpp) + +add_executable(cpp_test_lsoda test_LSODA.cpp) +target_link_libraries(cpp_test_lsoda lsoda) + +add_executable(cpp_benchmark_lsoda benchmark_LSODA.cpp) +target_link_libraries(cpp_benchmark_lsoda lsoda ${CMAKE_THREAD_LIBS_INIT}) + +enable_testing() +add_test(NAME cpp_test_lsoda COMMAND $) +add_test(NAME cpp_test_benchmark COMMAND $) diff --git a/external/libsoda/LICENSE b/external/libsoda/LICENSE new file mode 100644 index 00000000..2a530488 --- /dev/null +++ b/external/libsoda/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Dilawar Singh + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/external/libsoda/LSODA.cpp b/external/libsoda/LSODA.cpp new file mode 100644 index 00000000..6e932a55 --- /dev/null +++ b/external/libsoda/LSODA.cpp @@ -0,0 +1,2268 @@ +/* + * HISTORY: + * This is a CPP version of the LSODA library for integration into MOOSE + somulator. + * The original was aquired from + * http://www.ccl.net/cca/software/SOURCES/C/kinetics2/index.shtml and modified + by + * Heng Li . Heng merged several C files into one and added a + * simpler interface. [Available + here](http://lh3lh3.users.sourceforge.net/download/lsoda.c) + + * The original source code came with no license or copyright + * information. Heng Li released his modification under the MIT/X11 license. I + * maintain the same license. I have removed quite a lot of text/comments from + * this library. Please refer to the standard documentation. + * + * Contact: Dilawar Singh +*/ + +#include "LSODA.h" +#include +#include +#include +#include +#include +#include +#include + +#include "helper.h" + +using namespace std; + +#define ETA 2.2204460492503131e-16 + +LSODA::LSODA() +{ + // Initialize arrays. + mord = {{12, 5}}; + sm1 = {{ + 0., 0.5, 0.575, 0.55, 0.45, 0.35, 0.25, 0.2, 0.15, 0.1, 0.075, 0.05, + 0.025 + } + }; + el = {{0}}; + cm1 = {{0}}; + cm2 = {{0}}; +} + +LSODA::~LSODA() {} + +bool LSODA::abs_compare(double a, double b) +{ + return (std::abs(a) < std::abs(b)); +} + +/* Purpose : Find largest component of double vector dx */ +size_t LSODA::idamax1( const vector& dx, const size_t n, const size_t offset=0) +{ + + size_t v = 0, vmax = 0; + size_t idmax = 1; + for( size_t i = 1; i <= n; i++) + { + v = abs(dx[i+offset]); + if( v > vmax ) + { + vmax = v; + idmax = i; + } + } + return idmax; + + // Following has failed with seg-fault. Probably issue with STL. + // return std::max_element( dx.begin()+1+offset, dx.begin()+1+n, LSODA::abs_compare) - dx.begin() - offset; +} + +/* Purpose : scalar vector multiplication + dx = da * dx +*/ +void LSODA::dscal1(const double da, vector &dx, const size_t n, + const size_t offset = 0) +{ + std::transform( dx.begin()+1+offset, dx.end(), dx.begin()+1+offset, + [&da](double x) -> double { return da*x; } ); +} + +/* Purpose : Inner product dx . dy */ +double LSODA::ddot1(const vector &a, const vector &b, + const size_t n, const size_t offsetA = 0, + const size_t offsetB = 0) +{ + double sum = 0.0; + for (size_t i = 1; i <= n; i++) + sum += a[i+offsetA] * b[i+offsetB]; + return sum; +} + +void LSODA::daxpy1(const double da, const vector &dx, + vector &dy, const size_t n, const size_t offsetX = 0, + const size_t offsetY = 0) +{ + + for (size_t i = 1; i <= n; i++) + dy[i + offsetY] = da * dx[i + offsetX] + dy[i + offsetY]; +} + +// See BLAS documentation. The first argument has been changed to vector. +void LSODA::dgesl(const vector> &a, const size_t n, + vector &ipvt, vector &b, const size_t job) +{ + size_t k, j; + double t; + + /* + Job = 0, solve a * x = b. + */ + if (job == 0) + { + /* + First solve L * y = b. + */ + for (k = 1; k <= n; k++) + { + t = ddot1(a[k], b, k - 1); + b[k] = (b[k] - t) / a[k][k]; + } + /* + Now solve U * x = y. + */ + for (k = n - 1; k >= 1; k--) + { + b[k] = b[k] + ddot1(a[k], b, n - k, k, k); + j = ipvt[k]; + if (j != k) + { + t = b[j]; + b[j] = b[k]; + b[k] = t; + } + } + return; + } + /* + Job = nonzero, solve Transpose(a) * x = b. + + First solve Transpose(U) * y = b. + */ + for (k = 1; k <= n - 1; k++) + { + j = ipvt[k]; + t = b[j]; + if (j != k) + { + b[j] = b[k]; + b[k] = t; + } + daxpy1(t, a[k], b, n - k, k, k); + } + /* + Now solve Transpose(L) * x = y. + */ + for (k = n; k >= 1; k--) + { + b[k] = b[k] / a[k][k]; + t = -b[k]; + daxpy1(t, a[k], b, k - 1); + } +} + +// See BLAS documentation. All double* has been changed to std::vector . +void LSODA::dgefa(vector> &a, const size_t n, vector &ipvt, + size_t *const info) +{ + size_t j = 0, k = 0, i = 0; + double t = 0.0; + + /* Gaussian elimination with partial pivoting. */ + + *info = 0; + for (k = 1; k <= n - 1; k++) + { + /* + Find j = pivot index. Note that a[k]+k-1 is the address of + the 0-th element of the row vector whose 1st element is a[k][k]. + */ + j = idamax1(a[k], n - k + 1, k - 1) + k - 1; + ipvt[k] = j; + /* + Zero pivot implies this row already triangularized. + */ + if (a[k][j] == 0.) + { + *info = k; + continue; + } + /* + Interchange if necessary. + */ + if (j != k) + { + t = a[k][j]; + a[k][j] = a[k][k]; + a[k][k] = t; + } + /* + Compute multipliers. + */ + t = -1. / a[k][k]; + dscal1(t, a[k], n - k, k); + + /* + Column elimination with row indexing. + */ + for (i = k + 1; i <= n; i++) + { + t = a[i][j]; + if (j != k) + { + a[i][j] = a[i][k]; + a[i][k] = t; + } + daxpy1(t, a[k], a[i], n - k, k, k); + } + } /* end k-loop */ + + ipvt[n] = n; + if (a[n][n] == 0.) + *info = n; +} + +/* Terminate lsoda due to illegal input. */ +void LSODA::terminate(int *istate) +{ + if (illin == 5) + cerr << "[lsoda] repeated occurrence of illegal input. run aborted.. " + "apparent infinite loop." + << endl; + else + { + illin++; + *istate = -3; + } +} + +/* Terminate lsoda due to various error conditions. */ +void LSODA::terminate2(vector &y, double *t) +{ + for (size_t i = 1; i <= n; i++) + y[i] = yh_[1][i]; + *t = tn_; + illin = 0; + return; +} + +/* + The following block handles all successful returns from lsoda. + If itask != 1, y is loaded from yh_ and t is set accordingly. + *Istate is set to 2, the illegal input counter is zeroed, and the + optional outputs are loaded into the work arrays before returning. +*/ + +void LSODA::successreturn(vector &y, double *t, int itask, int ihit, + double tcrit, int *istate) +{ + for (size_t i = 1; i <= n; i++) + y[i] = yh_[1][i]; + *t = tn_; + if (itask == 4 || itask == 5) + if (ihit) + *t = tcrit; + *istate = 2; + illin = 0; +} + +/* +c references.. +c 1. alan c. hindmarsh, odepack, a systematized collection of ode +c solvers, in scientific computing, r. s. stepleman et al. (eds.), +c north-holland, amsterdam, 1983, pp. 55-64. +c 2. linda r. petzold, automatic selection of methods for solving +c stiff and nonstiff systems of ordinary differential equations, +c siam j. sci. stat. comput. 4 (1983), pp. 136-148. +c----------------------------------------------------------------------- +*/ +void LSODA::lsoda(LSODA_ODE_SYSTEM_TYPE f, const size_t neq, vector &y, + double *t, double tout, int itask, int *istate, int iopt, + int jt, array &iworks, array &rworks, + void *_data) +{ + assert(tout > *t); + + int mxstp0 = 500, mxhnl0 = 10; + + int iflag = 0, lenyh = 0, ihit = 0; + + double atoli = 0, ayi = 0, big = 0, h0 = 0, hmax = 0, hmx = 0, rh = 0, + rtoli = 0, tcrit = 0, tdist = 0, tnext = 0, tol = 0, tolsf = 0, tp = 0, + size = 0, sum = 0, w0 = 0; + + /* + Block a. + This code block is executed on every call. + It tests *istate and itask for legality and branches appropriately. + If *istate > 1 but the flag init shows that initialization has not + yet been done, an error return occurs. + If *istate = 1 and tout = t, return immediately. + */ + + if (*istate < 1 || *istate > 3) + { + // fprintf(stderr, "[lsoda] illegal istate = %d\n", *istate); + cerr << "[lsoda] illegal istate = " << *istate << endl; + terminate(istate); + return; + } + if (itask < 1 || itask > 5) + { + fprintf(stderr, "[lsoda] illegal itask = %d\n", itask); + terminate(istate); + return; + } + if (init == 0 && (*istate == 2 || *istate == 3)) + { + fprintf(stderr, "[lsoda] istate > 1 but lsoda not initialized\n"); + terminate(istate); + return; + } + + /* + Block b. + The next code block is executed for the initial call ( *istate = 1 ), + or for a continuation call with parameter changes ( *istate = 3 ). + It contains checking of all inputs and various initializations. + + First check legality of the non-optional inputs neq, itol, iopt, + jt, ml, and mu. + */ + + if (*istate == 1 || *istate == 3) + { + ntrep = 0; + if (neq <= 0) + { + cerr << "[lsoda] neq = " << neq << " is less than 1." << endl; + terminate(istate); + return; + } + if (*istate == 3 && neq > n) + { + cerr << "[lsoda] istate = 3 and neq increased" << endl; + terminate(istate); + return; + } + n = neq; + if (itol_ < 1 || itol_ > 4) + { + cerr << "[lsoda] itol = " << itol_ << " illegal" << endl; + terminate(istate); + return; + } + if (iopt < 0 || iopt > 1) + { + cerr << "[lsoda] iopt = " << iopt << " illegal" << endl; + terminate(istate); + return; + } + if (jt == 3 || jt < 1 || jt > 5) + { + cerr << "[lsoda] jt = " << jt << " illegal" << endl; + terminate(istate); + return; + } + jtyp = jt; + if (jt > 2) + { + ml = iworks[0]; + mu = iworks[1]; + if (ml >= n) + { + cerr << "[lsoda] ml = " << ml << " not between 1 and neq" << endl; + terminate(istate); + return; + } + if (mu >= n) + { + cerr << "[lsoda] mu = " << mu << " not between 1 and neq" << endl; + terminate(istate); + return; + } + } + + /* Next process and check the optional inpus. */ + /* Default options. */ + if (iopt == 0) + { + ixpr = 0; + mxstep = mxstp0; + mxhnil = mxhnl0; + hmxi = 0.; + hmin = 0.; + if (*istate == 1) + { + h0 = 0.; + mxordn = mord[0]; + mxords = mord[1]; + } + } + /* end if ( iopt == 0 ) */ + /* Optional inputs. */ + else /* if ( iopt = 1 ) */ + { + ixpr = iworks[2]; + if (ixpr > 1) + { + cerr << "[lsoda] ixpr = " << ixpr << " is illegal" << endl; + terminate(istate); + return; + } + + mxstep = iworks[3]; + if (mxstep == 0) + mxstep = mxstp0; + mxhnil = iworks[4]; + + if (*istate == 1) + { + h0 = rworks[1]; + mxordn = iworks[5]; + + if (mxordn == 0) + mxordn = 100; + + mxordn = min(mxordn, mord[0]); + mxords = iworks[6]; + + // if mxords is not given use 100. + if (mxords == 0) + mxords = 100; + + mxords = min(mxords, mord[1]); + + if ((tout - *t) * h0 < 0.) + { + cerr << "[lsoda] tout = " << tout << " behind t = " << *t + << ". integration direction is given by " << h0 << endl; + terminate(istate); + return; + } + } /* end if ( *istate == 1 ) */ + hmax = rworks[2]; + if (hmax < 0.) + { + cerr << "[lsoda] hmax < 0." << endl; + terminate(istate); + return; + } + hmxi = 0.; + if (hmax > 0) + hmxi = 1. / hmax; + + hmin = rworks[3]; + if (hmin < 0.) + { + cerr << "[lsoda] hmin < 0." << endl; + terminate(istate); + return; + } + } /* end else */ /* end iopt = 1 */ + } /* end if ( *istate == 1 || *istate == 3 ) */ + /* + If *istate = 1, meth_ is initialized to 1. + + Also allocate memory for yh_, wm_, ewt, savf, acor, ipvt. + */ + if (*istate == 1) + { + /* + If memory were not freed, *istate = 3 need not reallocate memory. + Hence this section is not executed by *istate = 3. + */ + sqrteta = sqrt(ETA); + meth_ = 1; + + nyh = n; + lenyh = 1 + max(mxordn, mxords); + + yh_.resize(lenyh + 1, std::vector(nyh + 1, 0.0)); + wm_.resize(nyh + 1, std::vector(nyh + 1, 0.0)); + ewt.resize(1 + nyh, 0); + savf.resize(1 + nyh, 0); + acor.resize(nyh + 1, 0.0); + ipvt.resize(nyh + 1, 0.0); + } + /* + Check rtol and atol for legality. + */ + if (*istate == 1 || *istate == 3) + { + rtoli = rtol_[1]; + atoli = atol_[1]; + for (size_t i = 1; i <= n; i++) + { + if (itol_ >= 3) + rtoli = rtol_[i]; + if (itol_ == 2 || itol_ == 4) + atoli = atol_[i]; + if (rtoli < 0.) + { + fprintf(stderr, "[lsoda] rtol = %g is less than 0.\n", rtoli); + terminate(istate); + return; + } + if (atoli < 0.) + { + fprintf(stderr, "[lsoda] atol = %g is less than 0.\n", atoli); + terminate(istate); + return; + } + } /* end for */ + } /* end if ( *istate == 1 || *istate == 3 ) */ + + /* If *istate = 3, set flag to signal parameter changes to stoda. */ + if (*istate == 3) + { + jstart = -1; + } + /* + Block c. + The next block is for the initial call only ( *istate = 1 ). + It contains all remaining initializations, the initial call to f, + and the calculation of the initial step size. + The error weights in ewt are inverted after being loaded. + */ + if (*istate == 1) + { + tn_ = *t; + tsw = *t; + maxord = mxordn; + if (itask == 4 || itask == 5) + { + tcrit = rworks[0]; + if ((tcrit - tout) * (tout - *t) < 0.) + { + fprintf(stderr, "[lsoda] itask = 4 or 5 and tcrit behind tout\n"); + terminate(istate); + return; + } + if (h0 != 0. && (*t + h0 - tcrit) * h0 > 0.) + h0 = tcrit - *t; + } + + jstart = 0; + nhnil = 0; + nst = 0; + nje = 0; + nslast = 0; + hu = 0.; + nqu = 0; + mused = 0; + miter = 0; + ccmax = 0.3; + maxcor = 3; + msbp = 20; + mxncf = 10; + + /* Initial call to f. */ + assert(yh_.size() == lenyh + 1); + assert(yh_[0].size() == nyh + 1); + + (*f)(*t, &y[1], &yh_[2][1], _data); + nfe = 1; + + /* Load the initial value vector in yh_. */ + for (size_t i = 1; i <= n; i++) + yh_[1][i] = y[i]; + + /* Load and invert the ewt array. ( h_ is temporarily set to 1. ) */ + nq = 1; + h_ = 1.; + ewset(y); + for (size_t i = 1; i <= n; i++) + { + if (ewt[i] <= 0.) + { + cerr << "[lsoda] ewt[" << i << "] = " << ewt[i] << " <= 0.\n" << endl; + terminate2(y, t); + return; + } + ewt[i] = 1. / ewt[i]; + } + + /* + The coding below computes the step size, h0, to be attempted on the + first step, unless the user has supplied a value for this. + First check that tout - *t differs significantly from zero. + A scalar tolerance quantity tol is computed, as max(rtol[i]) + if this is positive, or max(atol[i]/fabs(y[i])) otherwise, adjusted + so as to be between 100*ETA and 0.001. + Then the computed value h0 is given by + + h0^(-2) = 1. / ( tol * w0^2 ) + tol * ( norm(f) )^2 + + where w0 = max( fabs(*t), fabs(tout) ), + f = the initial value of the vector f(t,y), and + norm() = the weighted vector norm used throughout, given by + the vmnorm function routine, and weighted by the + tolerances initially loaded into the ewt array. + + The sign of h0 is inferred from the initial values of tout and *t. + fabs(h0) is made < fabs(tout-*t) in any case. + */ + if (h0 == 0.) + { + tdist = fabs(tout - *t); + w0 = max(fabs(*t), fabs(tout)); + if (tdist < 2. * ETA * w0) + { + fprintf(stderr, "[lsoda] tout too close to t to start integration\n "); + terminate(istate); + return; + } + tol = rtol_[1]; + if (itol_ > 2) + { + for (size_t i = 2; i <= n; i++) + tol = max(tol, rtol_[i]); + } + if (tol <= 0.) + { + atoli = atol_[1]; + for (size_t i = 1; i <= n; i++) + { + if (itol_ == 2 || itol_ == 4) + atoli = atol_[i]; + ayi = fabs(y[i]); + if (ayi != 0.) + tol = max(tol, atoli / ayi); + } + } + tol = max(tol, 100. * ETA); + tol = min(tol, 0.001); + sum = vmnorm(n, yh_[2], ewt); + sum = 1. / (tol * w0 * w0) + tol * sum * sum; + h0 = 1. / sqrt(sum); + h0 = min(h0, tdist); + h0 = h0 * ((tout - *t >= 0.) ? 1. : -1.); + } /* end if ( h0 == 0. ) */ + /* + Adjust h0 if necessary to meet hmax bound. + */ + rh = fabs(h0) * hmxi; + if (rh > 1.) + h0 /= rh; + + /* + Load h_ with h0 and scale yh_[2] by h0. + */ + h_ = h0; + for (size_t i = 1; i <= n; i++) + yh_[2][i] *= h0; + } /* if ( *istate == 1 ) */ + /* + Block d. + The next code block is for continuation calls only ( *istate = 2 or 3 ) + and is to check stop conditions before taking a step. + */ + if (*istate == 2 || *istate == 3) + { + nslast = nst; + switch (itask) + { + case 1: + if ((tn_ - tout) * h_ >= 0.) + { + intdy(tout, 0, y, &iflag); + if (iflag != 0) + { + fprintf(stderr, "[lsoda] trouble from intdy, itask = %d, tout = %g\n", + itask, tout); + terminate(istate); + return; + } + *t = tout; + *istate = 2; + illin = 0; + return; + } + break; + case 2: + break; + case 3: + tp = tn_ - hu * (1. + 100. * ETA); + if ((tp - tout) * h_ > 0.) + { + fprintf(stderr, "[lsoda] itask = %d and tout behind tcur - hu\n", + itask); + terminate(istate); + return; + } + if ((tn_ - tout) * h_ < 0.) + break; + successreturn(y, t, itask, ihit, tcrit, istate); + return; + case 4: + tcrit = rworks[0]; + if ((tn_ - tcrit) * h_ > 0.) + { + fprintf(stderr, "[lsoda] itask = 4 or 5 and tcrit behind tcur\n"); + terminate(istate); + return; + } + if ((tcrit - tout) * h_ < 0.) + { + fprintf(stderr, "[lsoda] itask = 4 or 5 and tcrit behind tout\n"); + terminate(istate); + return; + } + if ((tn_ - tout) * h_ >= 0.) + { + intdy(tout, 0, y, &iflag); + if (iflag != 0) + { + fprintf(stderr, "[lsoda] trouble from intdy, itask = %d, tout = %g\n", + itask, tout); + terminate(istate); + return; + } + *t = tout; + *istate = 2; + illin = 0; + return; + } + case 5: + if (itask == 5) + { + tcrit = rworks[0]; + if ((tn_ - tcrit) * h_ > 0.) + { + fprintf(stderr, "[lsoda] itask = 4 or 5 and tcrit behind tcur\n"); + terminate(istate); + return; + } + } + hmx = fabs(tn_) + fabs(h_); + ihit = fabs(tn_ - tcrit) <= (100. * ETA * hmx); + if (ihit) + { + *t = tcrit; + successreturn(y, t, itask, ihit, tcrit, istate); + return; + } + tnext = tn_ + h_ * (1. + 4. * ETA); + if ((tnext - tcrit) * h_ <= 0.) + break; + h_ = (tcrit - tn_) * (1. - 4. * ETA); + if (*istate == 2) + jstart = -2; + break; + } /* end switch */ + } /* end if ( *istate == 2 || *istate == 3 ) */ + /* + Block e. + The next block is normally executed for all calls and contains + the call to the one-step core integrator stoda. + + This is a looping point for the integration steps. + + First check for too many steps being taken, update ewt ( if not at + start of problem). Check for too much accuracy being requested, and + check for h_ below the roundoff level in *t. + */ + while (1) + { + if (*istate != 1 || nst != 0) + { + if ((nst - nslast) >= mxstep) + { + cerr << "[lsoda] " << mxstep << " steps taken before reaching tout" + << endl; + *istate = -1; + terminate2(y, t); + return; + } + + ewset(yh_[1]); + for (size_t i = 1; i <= n; i++) + { + if (ewt[i] <= 0.) + { + cerr << "[lsoda] ewt[" << i << "] = " << ewt[i] << " <= 0." << endl; + *istate = -6; + terminate2(y, t); + return; + } + ewt[i] = 1. / ewt[i]; + } + } + tolsf = ETA * vmnorm(n, yh_[1], ewt); + if (tolsf > 0.01) + { + tolsf = tolsf * 200.; + if (nst == 0) + { + fprintf(stderr, "lsoda -- at start of problem, too much accuracy\n"); + fprintf(stderr, " requested for precision of machine,\n"); + fprintf(stderr, " suggested scaling factor = %g\n", tolsf); + terminate(istate); + return; + } + fprintf(stderr, "lsoda -- at t = %g, too much accuracy requested\n", *t); + fprintf(stderr, " for precision of machine, suggested\n"); + fprintf(stderr, " scaling factor = %g\n", tolsf); + *istate = -2; + terminate2(y, t); + return; + } + + if ((tn_ + h_) == tn_) + { + nhnil++; + if (nhnil <= mxhnil) + { + fprintf(stderr, "lsoda -- warning..internal t = %g and h_ = %g are\n", + tn_, h_); + fprintf( + stderr, + " such that in the machine, t + h_ = t on the next step\n"); + fprintf(stderr, " solver will continue anyway.\n"); + if (nhnil == mxhnil) + { + cerr << "lsoda -- above warning has been issued " << nhnil + << " times, " << endl + << " it will not be issued again for this problem" << endl; + } + } + } + + /* Call stoda */ + stoda(neq, y, f, _data); + if (kflag == 0) + { + /* + Block f. + The following block handles the case of a successful return from the + core integrator ( kflag = 0 ). + If a method switch was just made, record tsw, reset maxord, + set jstart to -1 to signal stoda to complete the switch, + and do extra printing of data if ixpr = 1. + Then, in any case, check for stop conditions. + */ + init = 1; + if (meth_ != mused) + { + tsw = tn_; + maxord = mxordn; + if (meth_ == 2) + maxord = mxords; + jstart = -1; + if (ixpr) + { + if (meth_ == 2) + cerr << "[lsoda] a switch to the stiff method has occurred " + << endl; + if (meth_ == 1) + cerr << "[lsoda] a switch to the nonstiff method has occurred" + << endl; + } + } /* end if ( meth_ != mused ) */ + /* + itask = 1. + If tout has been reached, interpolate. + */ + if (1 == itask) + { + if ((tn_ - tout) * h_ < 0.) + continue; + + intdy(tout, 0, y, &iflag); + *t = tout; + *istate = 2; + illin = 0; + return; + } + /* + itask = 2. + */ + if (itask == 2) + { + successreturn(y, t, itask, ihit, tcrit, istate); + return; + } + /* + itask = 3. + Jump to exit if tout was reached. + */ + if (itask == 3) + { + if ((tn_ - tout) * h_ >= 0.) + { + successreturn(y, t, itask, ihit, tcrit, istate); + return; + } + continue; + } + /* + itask = 4. + See if tout or tcrit was reached. Adjust h_ if necessary. + */ + if (itask == 4) + { + if ((tn_ - tout) * h_ >= 0.) + { + intdy(tout, 0, y, &iflag); + *t = tout; + *istate = 2; + illin = 0; + return; + } + else + { + hmx = fabs(tn_) + fabs(h_); + ihit = fabs(tn_ - tcrit) <= (100. * ETA * hmx); + if (ihit) + { + successreturn(y, t, itask, ihit, tcrit, istate); + return; + } + tnext = tn_ + h_ * (1. + 4. * ETA); + if ((tnext - tcrit) * h_ <= 0.) + continue; + h_ = (tcrit - tn_) * (1. - 4. * ETA); + jstart = -2; + continue; + } + } /* end if ( itask == 4 ) */ + /* + itask = 5. + See if tcrit was reached and jump to exit. + */ + if (itask == 5) + { + hmx = fabs(tn_) + fabs(h_); + ihit = fabs(tn_ - tcrit) <= (100. * ETA * hmx); + successreturn(y, t, itask, ihit, tcrit, istate); + return; + } + } /* end if ( kflag == 0 ) */ + /* + kflag = -1, error test failed repeatedly or with fabs(h_) = hmin. + kflag = -2, convergence failed repeatedly or with fabs(h_) = hmin. + */ + if (kflag == -1 || kflag == -2) + { + fprintf(stderr, "lsoda -- at t = %g and step size h_ = %g, the\n", tn_, + h_); + if (kflag == -1) + { + fprintf(stderr, " error test failed repeatedly or\n"); + fprintf(stderr, " with fabs(h_) = hmin\n"); + *istate = -4; + } + if (kflag == -2) + { + fprintf(stderr, + " corrector convergence failed repeatedly or\n"); + fprintf(stderr, " with fabs(h_) = hmin\n"); + *istate = -5; + } + big = 0.; + imxer = 1; + for (size_t i = 1; i <= n; i++) + { + size = fabs(acor[i]) * ewt[i]; + if (big < size) + { + big = size; + imxer = i; + } + } + terminate2(y, t); + return; + } /* end if ( kflag == -1 || kflag == -2 ) */ + } /* end while */ +} /* end lsoda */ + +void LSODA::stoda(const size_t neq, vector &y, LSODA_ODE_SYSTEM_TYPE f, + void *_data) +{ + assert(neq + 1 == y.size()); + + size_t corflag = 0, orderflag = 0; + size_t i = 0, i1 = 0, j = 0, m = 0, ncf = 0; + double del = 0.0, delp = 0.0, dsm = 0.0, dup = 0.0, exup = 0.0, r = 0.0, + rh = 0.0, rhup = 0.0, told = 0.0; + double pdh = 0.0, pnorm = 0.0; + + /* + stoda performs one step of the integration of an initial value + problem for a system of ordinary differential equations. + Note.. stoda is independent of the value of the iteration method + indicator miter, when this is != 0, and hence is independent + of the type of chord method used, or the Jacobian structure. + Communication with stoda is done with the following variables: + + jstart = an integer used for input only, with the following + values and meanings: + + 0 perform the first step, + > 0 take a new step continuing from the last, + -1 take the next step with a new value of h_, + n, meth_, miter, and/or matrix parameters. + -2 take the next step with a new value of h_, + but with other inputs unchanged. + + kflag = a completion code with the following meanings: + + 0 the step was successful, + -1 the requested error could not be achieved, + -2 corrector convergence could not be achieved, + -3 fatal error in prja or solsy. + + miter = corrector iteration method: + + 0 functional iteration, + >0 a chord method corresponding to jacobian type jt. + + */ + kflag = 0; + told = tn_; + ncf = 0; + ierpj = 0; + iersl = 0; + jcur = 0; + delp = 0.; + + /* + On the first call, the order is set to 1, and other variables are + initialized. rmax is the maximum ratio by which h_ can be increased + in a single step. It is initially 1.e4 to compensate for the small + initial h_, but then is normally equal to 10. If a filure occurs + (in corrector convergence or error test), rmax is set at 2 for + the next increase. + cfode is called to get the needed coefficients for both methods. + */ + if (jstart == 0) + { + lmax = maxord + 1; + nq = 1; + l = 2; + ialth = 2; + rmax = 10000.; + rc = 0.; + el0 = 1.; + crate = 0.7; + hold = h_; + nslp = 0; + ipup = miter; + /* + Initialize switching parameters. meth_ = 1 is assumed initially. + */ + icount = 20; + irflag = 0; + pdest = 0.; + pdlast = 0.; + ratio = 5.; + cfode(2); + for (i = 1; i <= 5; i++) + cm2[i] = tesco[i][2] * elco[i][i + 1]; + cfode(1); + for (i = 1; i <= 12; i++) + cm1[i] = tesco[i][2] * elco[i][i + 1]; + resetcoeff(); + } /* end if ( jstart == 0 ) */ + /* + The following block handles preliminaries needed when jstart = -1. + ipup is set to miter to force a matrix update. + If an order increase is about to be considered ( ialth = 1 ), + ialth is reset to 2 to postpone consideration one more step. + If the caller has changed meth_, cfode is called to reset + the coefficients of the method. + If h_ is to be changed, yh_ must be rescaled. + If h_ or meth_ is being changed, ialth is reset to l = nq + 1 + to prevent further changes in h_ for that many steps. + */ + if (jstart == -1) + { + ipup = miter; + lmax = maxord + 1; + if (ialth == 1) + ialth = 2; + if (meth_ != mused) + { + cfode(meth_); + ialth = l; + resetcoeff(); + } + if (h_ != hold) + { + rh = h_ / hold; + h_ = hold; + scaleh(&rh, &pdh); + } + } /* if ( jstart == -1 ) */ + if (jstart == -2) + { + if (h_ != hold) + { + rh = h_ / hold; + h_ = hold; + scaleh(&rh, &pdh); + } + } /* if ( jstart == -2 ) */ + + /* + Prediction. + This section computes the predicted values by effectively + multiplying the yh_ array by the pascal triangle matrix. + rc is the ratio of new to old values of the coefficient h_ * el[1]. + When rc differs from 1 by more than ccmax, ipup is set to miter + to force pjac to be called, if a jacobian is involved. + In any case, prja is called at least every msbp steps. + */ + while (1) + { + while (1) + { + if (fabs(rc - 1.) > ccmax) + ipup = miter; + if (nst >= nslp + msbp) + ipup = miter; + tn_ += h_; + for (size_t j = nq; j >= 1; j--) + for (size_t i1 = j; i1 <= nq; i1++) + for (i = 1; i <= n; i++) + yh_[i1][i] += yh_[i1 + 1][i]; + + pnorm = vmnorm(n, yh_[1], ewt); + correction(neq, y, f, &corflag, pnorm, &del, &delp, &told, &ncf, &rh, &m, + _data); + if (corflag == 0) + break; + if (corflag == 1) + { + rh = max(rh, hmin / fabs(h_)); + scaleh(&rh, &pdh); + continue; + } + if (corflag == 2) + { + kflag = -2; + hold = h_; + jstart = 1; + return; + } + } /* end inner while ( corrector loop ) */ + + /* + The corrector has converged. jcur is set to 0 + to signal that the Jacobian involved may need updating later. + The local error test is done now. + */ + jcur = 0; + if (m == 0) + dsm = del / tesco[nq][2]; + if (m > 0) + dsm = vmnorm(n, acor, ewt) / tesco[nq][2]; + + if (dsm <= 1.) + { + /* + After a successful step, update the yh_ array. + Decrease icount by 1, and if it is -1, consider switching methods. + If a method switch is made, reset various parameters, + rescale the yh_ array, and exit. If there is no switch, + consider changing h_ if ialth = 1. Otherwise decrease ialth by 1. + If ialth is then 1 and nq < maxord, then acor is saved for + use in a possible order increase on the next step. + If a change in h_ is considered, an increase or decrease in order + by one is considered also. A change in h_ is made only if it is by + a factor of at least 1.1. If not, ialth is set to 3 to prevent + testing for that many steps. + */ + kflag = 0; + nst++; + hu = h_; + nqu = nq; + mused = meth_; + for (size_t j = 1; j <= l; j++) + { + r = el[j]; + for (i = 1; i <= n; i++) + yh_[j][i] += r * acor[i]; + } + icount--; + if (icount < 0) + { + methodswitch(dsm, pnorm, &pdh, &rh); + if (meth_ != mused) + { + rh = max(rh, hmin / fabs(h_)); + scaleh(&rh, &pdh); + rmax = 10.; + endstoda(); + break; + } + } + /* + No method switch is being made. Do the usual step/order selection. + */ + ialth--; + if (ialth == 0) + { + rhup = 0.; + if (l != lmax) + { + for (i = 1; i <= n; i++) + savf[i] = acor[i] - yh_[lmax][i]; + dup = vmnorm(n, savf, ewt) / tesco[nq][3]; + exup = 1. / (double)(l + 1); + rhup = 1. / (1.4 * pow(dup, exup) + 0.0000014); + } + + orderswitch(&rhup, dsm, &pdh, &rh, &orderflag); + + /* + No change in h_ or nq. + */ + if (orderflag == 0) + { + endstoda(); + break; + } + /* + h_ is changed, but not nq. + */ + if (orderflag == 1) + { + rh = max(rh, hmin / fabs(h_)); + scaleh(&rh, &pdh); + rmax = 10.; + endstoda(); + break; + } + /* + both nq and h_ are changed. + */ + if (orderflag == 2) + { + resetcoeff(); + rh = max(rh, hmin / fabs(h_)); + scaleh(&rh, &pdh); + rmax = 10.; + endstoda(); + break; + } + } /* end if ( ialth == 0 ) */ + if (ialth > 1 || l == lmax) + { + endstoda(); + break; + } + + for (size_t i = 1; i <= n; i++) + yh_[lmax][i] = acor[i]; + + endstoda(); + break; + } + /* end if ( dsm <= 1. ) */ + /* + The error test failed. kflag keeps track of multiple failures. + Restore tn_ and the yh_ array to their previous values, and prepare + to try the step again. Compute the optimum step size for this or + one lower. After 2 or more failures, h_ is forced to decrease + by a factor of 0.2 or less. + */ + else + { + kflag--; + tn_ = told; + for (j = nq; j >= 1; j--) + { + for (i1 = j; i1 <= nq; i1++) + for (i = 1; i <= n; i++) + yh_[i1][i] -= yh_[i1 + 1][i]; + } + rmax = 2.; + if (fabs(h_) <= hmin * 1.00001) + { + kflag = -1; + hold = h_; + jstart = 1; + break; + } + if (kflag > -3) + { + rhup = 0.; + orderswitch(&rhup, dsm, &pdh, &rh, &orderflag); + if (orderflag == 1 || orderflag == 0) + { + if (orderflag == 0) + rh = min(rh, 0.2); + rh = max(rh, hmin / fabs(h_)); + scaleh(&rh, &pdh); + } + if (orderflag == 2) + { + resetcoeff(); + rh = max(rh, hmin / fabs(h_)); + scaleh(&rh, &pdh); + } + continue; + } + /* if ( kflag > -3 ) */ + /* + Control reaches this section if 3 or more failures have occurred. + If 10 failures have occurred, exit with kflag = -1. + It is assumed that the derivatives that have accumulated in the + yh_ array have errors of the wrong order. Hence the first + derivative is recomputed, and the order is set to 1. Then + h_ is reduced by a factor of 10, and the step is retried, + until it succeeds or h_ reaches hmin. + */ + else + { + if (kflag == -10) + { + kflag = -1; + hold = h_; + jstart = 1; + break; + } + else + { + rh = 0.1; + rh = max(hmin / fabs(h_), rh); + h_ *= rh; + for (i = 1; i <= n; i++) + y[i] = yh_[1][i]; + (*f)(tn_, &y[1], &savf[1], _data); + nfe++; + for (i = 1; i <= n; i++) + yh_[2][i] = h_ * savf[i]; + ipup = miter; + ialth = 5; + if (nq == 1) + continue; + nq = 1; + l = 2; + resetcoeff(); + continue; + } + } /* end else -- kflag <= -3 */ + } /* end error failure handling */ + } /* end outer while */ + +} /* end stoda */ + +void LSODA::ewset(const vector &ycur) +{ + switch (itol_) + { + case 1: + for (size_t i = 1; i <= n; i++) + ewt[i] = rtol_[1] * fabs(ycur[i]) + atol_[1]; + break; + case 2: + for (size_t i = 1; i <= n; i++) + ewt[i] = rtol_[1] * fabs(ycur[i]) + atol_[i]; + break; + case 3: + for (size_t i = 1; i <= n; i++) + ewt[i] = rtol_[i] * fabs(ycur[i]) + atol_[1]; + break; + case 4: + for (size_t i = 1; i <= n; i++) + ewt[i] = rtol_[i] * fabs(ycur[i]) + atol_[i]; + break; + } + +} /* end ewset */ + +/* + Intdy computes interpolated values of the k-th derivative of the + dependent variable vector y, and stores it in dky. This routine + is called within the package with k = 0 and *t = tout, but may + also be called by the user for any k up to the current order. + ( See detailed instructions in the usage documentation. ) + + The computed values in dky are gotten by interpolation using the + Nordsieck history array yh_. This array corresponds uniquely to a + vector-valued polynomial of degree nqcur or less, and dky is set + to the k-th derivative of this polynomial at t. + The formula for dky is + + q + dky[i] = sum c[k][j] * ( t - tn_ )^(j-k) * h_^(-j) * yh_[j+1][i] + j=k + + where c[k][j] = j*(j-1)*...*(j-k+1), q = nqcur, tn_ = tcur, h_ = hcur. + The quantities nq = nqcur, l = nq+1, n = neq, tn_, and h_ are declared + static globally. The above sum is done in reverse order. + *iflag is returned negative if either k or t is out of bounds. +*/ +void LSODA::intdy(double t, int k, vector &dky, int *iflag) +{ + int ic, jp1 = 0; + double c, r, s, tp; + + *iflag = 0; + if (k < 0 || k > (int)nq) + { + fprintf(stderr, "[intdy] k = %d illegal\n", k); + *iflag = -1; + return; + } + tp = tn_ - hu - 100. * ETA * (tn_ + hu); + if ((t - tp) * (t - tn_) > 0.) + { + fprintf(stderr, + "intdy -- t = %g illegal. t not in interval tcur - hu to tcur\n", + t); + *iflag = -2; + return; + } + s = (t - tn_) / h_; + ic = 1; + for (size_t jj = l - k; jj <= nq; jj++) + ic *= jj; + c = (double)ic; + for (size_t i = 1; i <= n; i++) + dky[i] = c * yh_[l][i]; + + for (int j = nq - 1; j >= k; j--) + { + jp1 = j + 1; + ic = 1; + for (int jj = jp1 - k; jj <= j; jj++) + ic *= jj; + c = (double)ic; + + for (size_t i = 1; i <= n; i++) + dky[i] = c * yh_[jp1][i] + s * dky[i]; + } + if (k == 0) + return; + r = pow(h_, (double)(-k)); + + for (size_t i = 1; i <= n; i++) + dky[i] *= r; + +} /* end intdy */ + +void LSODA::cfode(int meth_) +{ + int i, nq, nqm1, nqp1; + double agamq, fnq, fnqm1, pc[13], pint, ragq, rqfac, rq1fac, tsign, xpin; + /* + cfode is called by the integrator routine to set coefficients + needed there. The coefficients for the current method, as + given by the value of meth_, are set for all orders and saved. + The maximum order assumed here is 12 if meth_ = 1 and 5 if meth_ = 2. + ( A smaller value of the maximum order is also allowed. ) + cfode is called once at the beginning of the problem, and + is not called again unless and until meth_ is changed. + + The elco array contains the basic method coefficients. + The coefficients el[i], 1 < i < nq+1, for the method of + order nq are stored in elco[nq][i]. They are given by a generating + polynomial, i.e., + + l(x) = el[1] + el[2]*x + ... + el[nq+1]*x^nq. + + For the implicit Adams method, l(x) is given by + + dl/dx = (x+1)*(x+2)*...*(x+nq-1)/factorial(nq-1), l(-1) = 0. + + For the bdf methods, l(x) is given by + + l(x) = (x+1)*(x+2)*...*(x+nq)/k, + + where k = factorial(nq)*(1+1/2+...+1/nq). + + The tesco array contains test constants used for the + local error test and the selection of step size and/or order. + At order nq, tesco[nq][k] is used for the selection of step + size at order nq-1 if k = 1, at order nq if k = 2, and at order + nq+1 if k = 3. + */ + if (meth_ == 1) + { + elco[1][1] = 1.; + elco[1][2] = 1.; + tesco[1][1] = 0.; + tesco[1][2] = 2.; + tesco[2][1] = 1.; + tesco[12][3] = 0.; + pc[1] = 1.; + rqfac = 1.; + for (nq = 2; nq <= 12; nq++) + { + /* + The pc array will contain the coefficients of the polynomial + + p(x) = (x+1)*(x+2)*...*(x+nq-1). + + Initially, p(x) = 1. + */ + rq1fac = rqfac; + rqfac = rqfac / (double)nq; + nqm1 = nq - 1; + fnqm1 = (double)nqm1; + nqp1 = nq + 1; + /* + Form coefficients of p(x)*(x+nq-1). + */ + pc[nq] = 0.; + for (i = nq; i >= 2; i--) + pc[i] = pc[i - 1] + fnqm1 * pc[i]; + pc[1] = fnqm1 * pc[1]; + /* + Compute integral, -1 to 0, of p(x) and x*p(x). + */ + pint = pc[1]; + xpin = pc[1] / 2.; + tsign = 1.; + for (i = 2; i <= nq; i++) + { + tsign = -tsign; + pint += tsign * pc[i] / (double)i; + xpin += tsign * pc[i] / (double)(i + 1); + } + /* + Store coefficients in elco and tesco. + */ + elco[nq][1] = pint * rq1fac; + elco[nq][2] = 1.; + for (i = 2; i <= nq; i++) + elco[nq][i + 1] = rq1fac * pc[i] / (double)i; + agamq = rqfac * xpin; + ragq = 1. / agamq; + tesco[nq][2] = ragq; + if (nq < 12) + tesco[nqp1][1] = ragq * rqfac / (double)nqp1; + tesco[nqm1][3] = ragq; + } /* end for */ + return; + } /* end if ( meth_ == 1 ) */ + + /* meth_ = 2. */ + pc[1] = 1.; + rq1fac = 1.; + + /* + The pc array will contain the coefficients of the polynomial + p(x) = (x+1)*(x+2)*...*(x+nq). + Initially, p(x) = 1. + */ + for (nq = 1; nq <= 5; nq++) + { + fnq = (double)nq; + nqp1 = nq + 1; + /* + Form coefficients of p(x)*(x+nq). + */ + pc[nqp1] = 0.; + for (i = nq + 1; i >= 2; i--) + pc[i] = pc[i - 1] + fnq * pc[i]; + pc[1] *= fnq; + /* + Store coefficients in elco and tesco. + */ + for (i = 1; i <= nqp1; i++) + elco[nq][i] = pc[i] / pc[2]; + elco[nq][2] = 1.; + tesco[nq][1] = rq1fac; + tesco[nq][2] = ((double)nqp1) / elco[nq][1]; + tesco[nq][3] = ((double)(nq + 2)) / elco[nq][1]; + rq1fac /= fnq; + } + return; + +} /* end cfode */ + +void LSODA::scaleh(double *rh, double *pdh) +{ + double r; + /* + If h_ is being changed, the h_ ratio rh is checked against rmax, hmin, + and hmxi, and the yh_ array is rescaled. ialth is set to l = nq + 1 + to prevent a change of h_ for that many steps, unless forced by a + convergence or error test failure. + */ + *rh = min(*rh, rmax); + *rh = *rh / max(1., fabs(h_) * hmxi * *rh); + /* + If meth_ = 1, also restrict the new step size by the stability region. + If this reduces h_, set irflag to 1 so that if there are roundoff + problems later, we can assume that is the cause of the trouble. + */ + if (meth_ == 1) + { + irflag = 0; + *pdh = max(fabs(h_) * pdlast, 0.000001); + if ((*rh * *pdh * 1.00001) >= sm1[nq]) + { + *rh = sm1[nq] / *pdh; + irflag = 1; + } + } + r = 1.; + for (size_t j = 2; j <= l; j++) + { + r *= *rh; + for (size_t i = 1; i <= n; i++) + yh_[j][i] *= r; + } + h_ *= *rh; + rc *= *rh; + ialth = l; + +} /* end scaleh */ + +void LSODA::prja(const size_t neq, vector &y, LSODA_ODE_SYSTEM_TYPE f, + void *_data) +{ + size_t i = 0, ier = 0, j = 0; + double fac = 0.0, hl0 = 0.0, r = 0.0, r0 = 0.0, yj = 0.0; + /* + prja is called by stoda to compute and process the matrix + P = I - h_ * el[1] * J, where J is an approximation to the Jacobian. + Here J is computed by finite differencing. + J, scaled by -h_ * el[1], is stored in wm_. Then the norm of J ( the + matrix norm consistent with the weighted max-norm on vectors given + by vmnorm ) is computed, and J is overwritten by P. P is then + subjected to LU decomposition in preparation for later solution + of linear systems with p as coefficient matrix. This is done + by dgefa if miter = 2, and by dgbfa if miter = 5. + */ + nje++; + ierpj = 0; + jcur = 1; + hl0 = h_ * el0; + /* + If miter = 2, make n calls to f to approximate J. + */ + if (miter != 2) + { + fprintf(stderr, "[prja] miter != 2\n"); + return; + } + if (miter == 2) + { + fac = vmnorm(n, savf, ewt); + r0 = 1000. * fabs(h_) * ETA * ((double)n) * fac; + if (r0 == 0.) + r0 = 1.; + for (j = 1; j <= n; j++) + { + yj = y[j]; + r = max(sqrteta * fabs(yj), r0 / ewt[j]); + y[j] += r; + fac = -hl0 / r; + (*f)(tn_, &y[1], &acor[1], _data); + for (i = 1; i <= n; i++) + wm_[i][j] = (acor[i] - savf[i]) * fac; + y[j] = yj; + } + nfe += n; + /* + Compute norm of Jacobian. + */ + pdnorm = fnorm(n, wm_, ewt) / fabs(hl0); + /* + Add identity matrix. + */ + for (i = 1; i <= n; i++) + wm_[i][i] += 1.; + /* + Do LU decomposition on P. + */ + dgefa(wm_, n, ipvt, &ier); + if (ier != 0) + ierpj = 1; + return; + } +} /* end prja */ + +/* + This function routine computes the weighted max-norm + of the vector of length n contained in the array v, with weights + contained in the array w of length n. + + vmnorm = max( i = 1, ..., n ) fabs( v[i] ) * w[i]. +*/ +double LSODA::vmnorm(const size_t n, const vector &v, + const vector &w) +{ + double vm = 0.; + for (size_t i = 1; i <= n; i++) + vm = max(vm, fabs(v[i]) * w[i]); + return vm; +} + +double LSODA::fnorm(int n, const vector> &a, + const vector &w) + +/* + This subroutine computes the norm of a full n by n matrix, + stored in the array a, that is consistent with the weighted max-norm + on vectors, with weights stored in the array w. + + fnorm = max(i=1,...,n) ( w[i] * sum(j=1,...,n) fabs( a[i][j] ) / w[j] ) +*/ + +{ + double an = 0, sum = 0; + + for (size_t i = 1; i <= (size_t)n; i++) + { + sum = 0.; + for (size_t j = 1; j <= (size_t)n; j++) + sum += fabs(a[i][j]) / w[j]; + an = max(an, sum * w[i]); + } + return an; +} + +/* + *corflag = 0 : corrector converged, +1 : step size to be reduced, redo prediction, +2 : corrector cannot converge, failure flag. +*/ +void LSODA::correction(const size_t neq, vector &y, + LSODA_ODE_SYSTEM_TYPE f, size_t *corflag, double pnorm, + double *del, double *delp, double *told, size_t *ncf, + double *rh, size_t *m, void *_data) +{ + double rm = 0.0, rate = 0.0, dcon = 0.0; + + /* + Up to maxcor corrector iterations are taken. A convergence test is + made on the r.m.s. norm of each correction, weighted by the error + weight vector ewt. The sum of the corrections is accumulated in the + vector acor[i]. The yh_ array is not altered in the corrector loop. + */ + + *m = 0; + *corflag = 0; + *del = 0.; + + for (size_t i = 1; i <= n; i++) + y[i] = yh_[1][i]; + + (*f)(tn_, &y[1], &savf[1], _data); + + nfe++; + /* + If indicated, the matrix P = I - h_ * el[1] * J is reevaluated and + preprocessed before starting the corrector iteration. ipup is set + to 0 as an indicator that this has been done. + */ + while (1) + { + if (*m == 0) + { + if (ipup > 0) + { + prja(neq, y, f, _data); + ipup = 0; + rc = 1.; + nslp = nst; + crate = 0.7; + if (ierpj != 0) + { + corfailure(told, rh, ncf, corflag); + return; + } + } + for (size_t i = 1; i <= n; i++) + acor[i] = 0.; + } /* end if ( *m == 0 ) */ + if (miter == 0) + { + /* + In case of functional iteration, update y directly from + the result of the last function evaluation. + */ + for (size_t i = 1; i <= n; i++) + { + savf[i] = h_ * savf[i] - yh_[2][i]; + y[i] = savf[i] - acor[i]; + } + *del = vmnorm(n, y, ewt); + for (size_t i = 1; i <= n; i++) + { + y[i] = yh_[1][i] + el[1] * savf[i]; + acor[i] = savf[i]; + } + } + /* end functional iteration */ + /* + In the case of the chord method, compute the corrector error, + and solve the linear system with that as right-hand side and + P as coefficient matrix. + */ + else + { + for (size_t i = 1; i <= n; i++) + y[i] = h_ * savf[i] - (yh_[2][i] + acor[i]); + + solsy(y); + *del = vmnorm(n, y, ewt); + + for (size_t i = 1; i <= n; i++) + { + acor[i] += y[i]; + y[i] = yh_[1][i] + el[1] * acor[i]; + } + } /* end chord method */ + /* + Test for convergence. If *m > 0, an estimate of the convergence + rate constant is stored in crate, and this is used in the test. + + We first check for a change of iterates that is the size of + roundoff error. If this occurs, the iteration has converged, and a + new rate estimate is not formed. + In all other cases, force at least two iterations to estimate a + local Lipschitz constant estimate for Adams method. + On convergence, form pdest = local maximum Lipschitz constant + estimate. pdlast is the most recent nonzero estimate. + */ + if (*del <= 100. * pnorm * ETA) + break; + if (*m != 0 || meth_ != 1) + { + if (*m != 0) + { + rm = 1024.0; + if (*del <= (1024. * *delp)) + rm = *del / *delp; + rate = max(rate, rm); + crate = max(0.2 * crate, rm); + } + dcon = *del * min(1., 1.5 * crate) / (tesco[nq][2] * conit); + if (dcon <= 1.) + { + pdest = max(pdest, rate / fabs(h_ * el[1])); + if (pdest != 0.) + pdlast = pdest; + break; + } + } + /* + The corrector iteration failed to converge. + If miter != 0 and the Jacobian is out of date, prja is called for + the next try. Otherwise the yh_ array is retracted to its values + before prediction, and h_ is reduced, if possible. If h_ cannot be + reduced or mxncf failures have occured, exit with corflag = 2. + */ + (*m)++; + if (*m == maxcor || (*m >= 2 && *del > 2. * *delp)) + { + if (miter == 0 || jcur == 1) + { + corfailure(told, rh, ncf, corflag); + return; + } + ipup = miter; + /* + Restart corrector if Jacobian is recomputed. + */ + *m = 0; + rate = 0.; + *del = 0.; + for (size_t i = 1; i <= n; i++) + y[i] = yh_[1][i]; + + (*f)(tn_, &y[1], &savf[1], _data); + + nfe++; + } + /* + Iterate corrector. + */ + else + { + *delp = *del; + (*f)(tn_, &y[1], &savf[1], _data); + nfe++; + } + } /* end while */ +} /* end correction */ + +void LSODA::corfailure(double *told, double *rh, size_t *ncf, size_t *corflag) +{ + ncf++; + rmax = 2.; + tn_ = *told; + for (size_t j = nq; j >= 1; j--) + for (size_t i1 = j; i1 <= nq; i1++) + for (size_t i = 1; i <= n; i++) + yh_[i1][i] -= yh_[i1 + 1][i]; + + if (fabs(h_) <= hmin * 1.00001 || *ncf == mxncf) + { + *corflag = 2; + return; + } + *corflag = 1; + *rh = 0.25; + ipup = miter; +} + +/* + This routine manages the solution of the linear system arising from + a chord iteration. It is called if miter != 0. + If miter is 2, it calls dgesl to accomplish this. + If miter is 5, it calls dgbsl. + + y = the right-hand side vector on input, and the solution vector + on output. +*/ +void LSODA::solsy(vector &y) +{ + iersl = 0; + if (miter != 2) + { + printf("solsy -- miter != 2\n"); + return; + } + if (miter == 2) + dgesl(wm_, n, ipvt, y, 0); + return; +} + +void LSODA::methodswitch(double dsm, double pnorm, double *pdh, double *rh) +{ + int lm1, lm1p1, lm2, lm2p1, nqm1, nqm2; + double rh1, rh2, rh1it, exm2, dm2, exm1, dm1, alpha, exsm; + + /* + We are current using an Adams method. Consider switching to bdf. + If the current order is greater than 5, assume the problem is + not stiff, and skip this section. + If the Lipschitz constant and error estimate are not polluted + by roundoff, perform the usual test. + Otherwise, switch to the bdf methods if the last step was + restricted to insure stability ( irflag = 1 ), and stay with Adams + method if not. When switching to bdf with polluted error estimates, + in the absence of other information, double the step size. + + When the estimates are ok, we make the usual test by computing + the step size we could have (ideally) used on this step, + with the current (Adams) method, and also that for the bdf. + If nq > mxords, we consider changing to order mxords on switching. + Compare the two step sizes to decide whether to switch. + The step size advantage must be at least ratio = 5 to switch. + */ + if (meth_ == 1) + { + if (nq > 5) + return; + if (dsm <= (100. * pnorm * ETA) || pdest == 0.) + { + if (irflag == 0) + return; + rh2 = 2.; + nqm2 = min(nq, mxords); + } + else + { + exsm = 1. / (double)l; + rh1 = 1. / (1.2 * pow(dsm, exsm) + 0.0000012); + rh1it = 2. * rh1; + *pdh = pdlast * fabs(h_); + if ((*pdh * rh1) > 0.00001) + rh1it = sm1[nq] / *pdh; + rh1 = min(rh1, rh1it); + if (nq > mxords) + { + nqm2 = mxords; + lm2 = mxords + 1; + exm2 = 1. / (double)lm2; + lm2p1 = lm2 + 1; + dm2 = vmnorm(n, yh_[lm2p1], ewt) / cm2[mxords]; + rh2 = 1. / (1.2 * pow(dm2, exm2) + 0.0000012); + } + else + { + dm2 = dsm * (cm1[nq] / cm2[nq]); + rh2 = 1. / (1.2 * pow(dm2, exsm) + 0.0000012); + nqm2 = nq; + } + if (rh2 < ratio * rh1) + return; + } + /* + The method switch test passed. Reset relevant quantities for bdf. + */ + *rh = rh2; + icount = 20; + meth_ = 2; + miter = jtyp; + pdlast = 0.; + nq = nqm2; + l = nq + 1; + return; + } /* end if ( meth_ == 1 ) */ + + /* + We are currently using a bdf method, considering switching to Adams. + Compute the step size we could have (ideally) used on this step, + with the current (bdf) method, and also that for the Adams. + If nq > mxordn, we consider changing to order mxordn on switching. + Compare the two step sizes to decide whether to switch. + The step size advantage must be at least 5/ratio = 1 to switch. + If the step size for Adams would be so small as to cause + roundoff pollution, we stay with bdf. + */ + exsm = 1. / (double)l; + if (mxordn < nq) + { + nqm1 = mxordn; + lm1 = mxordn + 1; + exm1 = 1. / (double)lm1; + lm1p1 = lm1 + 1; + dm1 = vmnorm(n, yh_[lm1p1], ewt) / cm1[mxordn]; + rh1 = 1. / (1.2 * pow(dm1, exm1) + 0.0000012); + } + else + { + dm1 = dsm * (cm2[nq] / cm1[nq]); + rh1 = 1. / (1.2 * pow(dm1, exsm) + 0.0000012); + nqm1 = nq; + exm1 = exsm; + } + rh1it = 2. * rh1; + *pdh = pdnorm * fabs(h_); + if ((*pdh * rh1) > 0.00001) + rh1it = sm1[nqm1] / *pdh; + rh1 = min(rh1, rh1it); + rh2 = 1. / (1.2 * pow(dsm, exsm) + 0.0000012); + if ((rh1 * ratio) < (5. * rh2)) + return; + alpha = max(0.001, rh1); + dm1 *= pow(alpha, exm1); + if (dm1 <= 1000. * ETA * pnorm) + return; + /* + The switch test passed. Reset relevant quantities for Adams. + */ + *rh = rh1; + icount = 20; + meth_ = 1; + miter = 0; + pdlast = 0.; + nq = nqm1; + l = nq + 1; +} /* end methodswitch */ + +/* + This routine returns from stoda to lsoda. Hence freevectors() is + not executed. +*/ +void LSODA::endstoda() +{ + double r = 1. / tesco[nqu][2]; + for (size_t i = 1; i <= n; i++) + acor[i] *= r; + hold = h_; + jstart = 1; +} + +/* + Regardless of the success or failure of the step, factors + rhdn, rhsm, and rhup are computed, by which h_ could be multiplied + at order nq - 1, order nq, or order nq + 1, respectively. + In the case of a failure, rhup = 0. to avoid an order increase. + The largest of these is determined and the new order chosen + accordingly. If the order is to be increased, we compute one + additional scaled derivative. + + orderflag = 0 : no change in h_ or nq, + 1 : change in h_ but not nq, + 2 : change in both h_ and nq. +*/ +void LSODA::orderswitch(double *rhup, double dsm, double *pdh, double *rh, + size_t *orderflag) +{ + size_t newq = 0; + double exsm, rhdn, rhsm, ddn, exdn, r; + + *orderflag = 0; + + exsm = 1. / (double)l; + rhsm = 1. / (1.2 * pow(dsm, exsm) + 0.0000012); + + rhdn = 0.; + if (nq != 1) + { + ddn = vmnorm(n, yh_[l], ewt) / tesco[nq][1]; + exdn = 1. / (double)nq; + rhdn = 1. / (1.3 * pow(ddn, exdn) + 0.0000013); + } + /* + If meth_ = 1, limit rh accordinfg to the stability region also. + */ + if (meth_ == 1) + { + *pdh = max(fabs(h_) * pdlast, 0.000001); + if (l < lmax) + *rhup = min(*rhup, sm1[l] / *pdh); + rhsm = min(rhsm, sm1[nq] / *pdh); + if (nq > 1) + rhdn = min(rhdn, sm1[nq - 1] / *pdh); + pdest = 0.; + } + if (rhsm >= *rhup) + { + if (rhsm >= rhdn) + { + newq = nq; + *rh = rhsm; + } + else + { + newq = nq - 1; + *rh = rhdn; + if (kflag < 0 && *rh > 1.) + *rh = 1.; + } + } + else + { + if (*rhup <= rhdn) + { + newq = nq - 1; + *rh = rhdn; + if (kflag < 0 && *rh > 1.) + *rh = 1.; + } + else + { + *rh = *rhup; + if (*rh >= 1.1) + { + r = el[l] / (double)l; + nq = l; + l = nq + 1; + for (size_t i = 1; i <= n; i++) + yh_[l][i] = acor[i] * r; + + *orderflag = 2; + return; + } + else + { + ialth = 3; + return; + } + } + } + /* + If meth_ = 1 and h_ is restricted by stability, bypass 10 percent test. + */ + if (1 == meth_) + { + if ((*rh * *pdh * 1.00001) < sm1[newq]) + if (kflag == 0 && *rh < 1.1) + { + ialth = 3; + return; + } + } + else + { + if (kflag == 0 && *rh < 1.1) + { + ialth = 3; + return; + } + } + if (kflag <= -2) + *rh = min(*rh, 0.2); + /* + If there is a change of order, reset nq, l, and the coefficients. + In any case h_ is reset according to rh and the yh_ array is rescaled. + Then exit or redo the step. + */ + if (newq == nq) + { + *orderflag = 1; + return; + } + nq = newq; + l = nq + 1; + *orderflag = 2; + +} /* end orderswitch */ + +void LSODA::resetcoeff() +/* + The el vector and related constants are reset + whenever the order nq is changed, or at the start of the problem. +*/ +{ + array ep1; + + ep1 = elco[nq]; + for (size_t i = 1; i <= l; i++) + el[i] = ep1[i]; + rc = rc * el[1] / el0; + el0 = el[1]; + conit = 0.5 / (double)(nq + 2); +} + +void LSODA::_freevectors(void) +{ + // Does nothing. USE c++ memory mechanism here. +} + +/* --------------------------------------------------------------------------*/ +/** + * @Synopsis Simpler interface. + * + * @Param f System + * @Param neq, size of system. + * @Param y, init values of size neq + * @Param yout, results vector for size neq+1, ignore yout[0] + * @Param t, start time. + * @Param tout, stop time. + * @Param _data + * @Param rtol, relative tolerance. + * @Param atol, absolute tolerance. + */ +/* ----------------------------------------------------------------------------*/ +void LSODA::lsoda_update(LSODA_ODE_SYSTEM_TYPE f, const size_t neq, + vector &y, vector &yout, double *t, + const double tout, int *istate, void * _data, + double rtol, double atol + ) +{ + array iworks = {{0}}; + array rworks = {{0.0}}; + + int itask, iopt, jt; + + // cout << "Debug : rtol " << rtol << ". atol " << atol << endl; + + itask = 1; + iopt = 0; + jt = 2; + + yout.resize(neq + 1); + + // Set the tolerance. We should do it only once. + rtol_.resize(neq + 1, rtol); + atol_.resize(neq + 1, atol); + rtol_[0] = 0; + atol_[0] = 0; + + // Fill-in values. + for (size_t i = 1; i <= neq; i++) + yout[i] = y[i - 1]; + + lsoda(f, neq, yout, t, tout, itask, istate, iopt, jt, iworks, rworks, _data); +} diff --git a/external/libsoda/LSODA.h b/external/libsoda/LSODA.h new file mode 100644 index 00000000..f8b4e139 --- /dev/null +++ b/external/libsoda/LSODA.h @@ -0,0 +1,158 @@ +/*** + * Created: 2018-08-14 + + * Author: Dilawar Singh + * Organization: NCBS Bangalore + * License: MIT License + */ + +#ifndef LSODE_H +#define LSODE_H + +#include +#include +#include +#include + +using namespace std; + +/* --------------------------------------------------------------------------*/ +/** + * @Synopsis Type definition of LSODA ode system. See the file test_LSODA.cpp + * for an example. + * + * @Param time, double + * @Param y, array of double. + * @Param dydt, array of double + * @Param data, void* + * + * @Returns void + */ +/* ----------------------------------------------------------------------------*/ +typedef void (*LSODA_ODE_SYSTEM_TYPE)(double t, double *y, double *dydt, void *); + +class LSODA +{ + +public: + LSODA(); + ~LSODA(); + + size_t idamax1(const vector &dx, const size_t n, const size_t offset); + + void dscal1(const double da, vector &dx, const size_t n, + const size_t offset); + + double ddot1(const vector &a, const vector &b, const size_t n, + const size_t offsetA, const size_t offsetB); + + void daxpy1(const double da, const vector &dx, vector &dy, + const size_t n, const size_t offsetX, + const size_t offsetY); + + void dgesl(const vector> &a, const size_t n, vector &ipvt, + vector &b, const size_t job); + + void dgefa(vector> &a, const size_t n, vector &ipvt, + size_t *const info); + + void prja(const size_t neq, vector &y, LSODA_ODE_SYSTEM_TYPE f, + void *_data); + + void lsoda(LSODA_ODE_SYSTEM_TYPE f, const size_t neq, vector &y, + double *t, double tout, int itask, int *istate, int iopt, int jt, + array &iworks, array &rworks, void *_data); + + void correction(const size_t neq, vector &y, LSODA_ODE_SYSTEM_TYPE f, + size_t *corflag, double pnorm, double *del, double *delp, + double *told, size_t *ncf, double *rh, size_t *m, + void *_data); + + void stoda(const size_t neq, vector &y, LSODA_ODE_SYSTEM_TYPE f, + void *_data); + + // We call this function in VoxelPools:: + void lsoda_update(LSODA_ODE_SYSTEM_TYPE f, const size_t neq, + vector &y, std::vector &yout, double *t, + const double tout, int *istate, void *const _data, + double rtol = 1e-3, double atol = 1e-6 // Tolerance + ); + + void terminate(int *istate); + void terminate2(vector &y, double *t); + void successreturn(vector &y, double *t, int itask, int ihit, + double tcrit, int *istate); + void _freevectors(void); + void ewset(const vector &ycur); + void resetcoeff(void); + void solsy(vector &y); + void endstoda(void); + void orderswitch(double *rhup, double dsm, double *pdh, double *rh, + size_t *orderflag); + void intdy(double t, int k, vector &dky, int *iflag); + void corfailure(double *told, double *rh, size_t *ncf, size_t *corflag); + void methodswitch(double dsm, double pnorm, double *pdh, double *rh); + void cfode(int meth_); + void scaleh(double *rh, double *pdh); + double fnorm(int n, const vector> &a, const vector &w); + double vmnorm(const size_t n, const vector &v, + const vector &w); + + static bool abs_compare(double a, double b); + +private: + size_t ml, mu, imxer; + double sqrteta; + + // NOTE: initialize in default constructor. Older compiler e.g. 4.8.4 would + // produce error if these are initialized here. With newer compiler, + // initialization can be done here. + array mord; + array sm1; + + array el; // = {0}; + array cm1; // = {0}; + array cm2; // = {0}; + + array, 13> elco; + array, 13> tesco; + + size_t illin, init, ierpj, iersl, jcur, l, miter, maxord, maxcor, msbp, mxncf; + + int kflag, jstart; + + size_t ixpr = 0, jtyp, mused, mxordn, mxords = 12; + size_t meth_; + + size_t n, nq, nst, nfe, nje, nqu; + size_t mxstep, mxhnil; + size_t nslast, nhnil, ntrep, nyh; + + double ccmax, el0, h_ = .0; + double hmin, hmxi, hu, rc, tn_ = 0.0; + double tsw, pdnorm; + double conit, crate, hold, rmax; + + size_t ialth, ipup, lmax; + size_t nslp; + double pdest, pdlast, ratio; + int icount, irflag; + + vector ewt; + vector savf; + vector acor; + vector> yh_; + vector> wm_; + + vector ipvt; + +private: + int itol_ = 2; + std::vector rtol_; + std::vector atol_; + +public: + void *param = nullptr; +}; + +#endif /* end of include guard: LSODE_H */ diff --git a/external/libsoda/README.md b/external/libsoda/README.md new file mode 100644 index 00000000..cd2020e6 --- /dev/null +++ b/external/libsoda/README.md @@ -0,0 +1,13 @@ +[![Build Status](https://travis-ci.org/dilawar/libsoda.svg?branch=master)](https://travis-ci.org/dilawar/libsoda) + +## libsoda++ + +This is `c++11` version of LSODA library. See the `./test_LSODA.cpp` file for example. + +## CREDIT + +This work is based on http://lh3lh3.users.sourceforge.net/download/lsoda.c . + +Related projects: + +1. https://github.com/sdwfrost/liblsoda diff --git a/external/libsoda/benchmark_LSODA.cpp b/external/libsoda/benchmark_LSODA.cpp new file mode 100644 index 00000000..82692b63 --- /dev/null +++ b/external/libsoda/benchmark_LSODA.cpp @@ -0,0 +1,248 @@ +/*** + * Description: benchamark ODE system. + * + * Created: 2018-08-14 + + * Author: Dilawar Singh + * Organization: NCBS Bangalore + * License: MIT License + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "LSODA.h" +#include "helper.h" + +using namespace std; +using namespace std::chrono; + +// Describe the system. +static void fex(double t, double *y, double *ydot, void *data) +{ + ydot[0] = 1.0E4 * y[1] * y[2] - .04E0 * y[0]; + // Don't swap ydot[1] and ydot[2]. The order will change and test will fail. + ydot[2] = 3.0E7 * y[1] * y[1]; + ydot[1] = -1.0 * (ydot[0] + ydot[2]); +} + +static void system_scipy( double t, double* y, double* ydot, void* data) +{ + double mu = 1E4; + ydot[0] = y[1]; + ydot[1] = mu * (1- y[0]*y[0])*y[1] - y[0]; +} + +// This system is described here +// https://github.com/sdwfrost/liblsoda/issues/10 +static void system_github_issue_10(double t, double* y, double* ydot, void* data) +{ + ydot[0]= 9*y[0] + 24*y[1] + 5*cos(t)-(1/3)*sin(t); + ydot[1]= -24*y[0] -51*y[1] -95*cos(t) + (1/3)*sin(t); +} + +double test_github_system( void ) +{ + // cout << "Running test given https://github.com/sdwfrost/liblsoda/issues/10" << endl; + double t = 0e0, tout = 0.5; + + vector y = {4.0/3.0, 2.0/3.0}; + int istate = 1; + + LSODA lsoda; + + chrono::steady_clock::time_point begin = chrono::steady_clock::now(); + vector yout; + vector res; + for (size_t i = 0; i < 10; i++) + { + lsoda.lsoda_update( system_github_issue_10, 2, y, yout, &t, tout, &istate, nullptr ); + res.push_back( yout[1] ); + res.push_back( yout[2] ); + tout += 0.5; + + y[0] = yout[1]; + y[1] = yout[2]; + } + + chrono::steady_clock::time_point end = chrono::steady_clock::now(); + + if( !areEqual(-11.9400786, res[0])) cout << 'x'; + if( !areEqual( 3.8608262, res[1])) cout << 'x'; + double dt = duration_cast(end-begin).count(); + return dt; +} + +double test_scipy_sys( void ) +{ + // cout << "Running test scipy sys" << endl; + double t, tout; + t = 0e0; tout = 10; + + vector y = {10,0}; + int istate = 1; + + LSODA lsoda; + + vector yout; + chrono::steady_clock::time_point begin = chrono::steady_clock::now(); + lsoda.lsoda_update( system_scipy, 2, y, yout, &t, tout, &istate, nullptr ); + chrono::steady_clock::time_point end = chrono::steady_clock::now(); + + // printf(" at t= %12.4e y= %14.6e %14.6e\n", t, yout[1], yout[2]); + + if( ! areEqual(9.999899e+00, yout[1])) cout << 'x'; + if( !areEqual(-1.010111e-05, yout[2])) cout << 'x'; + + if (istate <= 0) + { + cerr << "error istate = " << istate << endl; + exit(0); + } + + double dt = duration_cast(end-begin).count(); + return dt; +} + +double test_fex(void) +{ + // cout << "Running test fex." << endl; + int neq = 3; + double t, tout; + t = 0e0; + tout = 0.4e0; + + vector y = { 1e0, 0e0, 0.0 }; + int istate = 1; + + LSODA lsoda; + setprecision( 12 ); + + chrono::steady_clock::time_point begin = chrono::steady_clock::now(); + + vector res; + vector yout; + for (size_t iout = 1; iout <= 12; iout++) + { + lsoda.lsoda_update( fex, neq, y, yout, &t, tout, &istate, nullptr, 1e-4, 1e-8 ); + // cerr << " at t " << t << " y= " << yout[1] << ' ' << yout[2] << ' ' << yout[3] << endl; + // Update the y for next iteration. + y[0] = yout[1]; + y[1] = yout[2]; + y[2] = yout[3]; + + res.push_back( y[0] ); + res.push_back( y[1] ); + res.push_back( y[2] ); + + if (istate <= 0) + { + cerr << "error istate = " << istate << endl; + exit(0); + } + tout = tout * 10.0E0; + } + + chrono::steady_clock::time_point end= chrono::steady_clock::now(); + double dt = chrono::duration_cast(end - begin).count(); + // cout << "|| Time taken (us)= " << dt << endl; + + vector expected = { 0.985172 ,3.3864e-05 , 0.0147939 + , 0.905514 ,2.24042e-05, 0.0944634 + , 0.715803 ,9.18446e-06, 0.284188 + , 0.450479 ,3.22234e-06, 0.549517 + , 0.183171 ,8.94046e-07, 0.816828 + , 0.0389738 ,1.62135e-07, 0.961026 + , 0.00493686 ,1.98442e-08, 0.995063 + , 0.00051665 ,2.06765e-09, 0.999483 + , 5.20075e-05 ,2.08041e-10, 0.999948 + , 5.20168e-06 ,2.08068e-11, 0.999995 + , 5.19547e-07 ,2.07819e-12, 0.999999 + }; + + // Assert here. + for (size_t i = 0; i < expected.size(); i++) + { + double err = abs( expected[i] - res[i] ); + if( err > 1e-6 ) + { + cerr << "FAILED: Expected " << expected[i] << ". Got " << res[i] << endl; + assert( false ); + } + } + + return dt; +} + +int run_serial( ) +{ + vector t1s, t2s, t3s; + size_t N = 10000; + cout << "Running " << N << " iterations. " << endl; + + // Launch all three tests in parallel. + chrono::steady_clock::time_point begin = chrono::steady_clock::now(); + for (size_t i = 0; i < N; i++) + { + double t1 = test_scipy_sys(); + double t2 = test_fex(); + double t3 = test_github_system( ); + t1s.push_back( t1 ); + t2s.push_back( t2 ); + t3s.push_back( t3 ); + } + + cout << "Avg time for 1 " << std::accumulate(t1s.begin(), t1s.end(), 0)/N + << " us per loop."<< endl; + cout << "Avg time for 2 " << std::accumulate(t2s.begin(), t2s.end(), 0)/N + << " us per loop."<< endl; + cout << "Avg time for 3 " << std::accumulate(t3s.begin(), t3s.end(), 0)/N + << " us per loop."<< endl; + + chrono::steady_clock::time_point end = chrono::steady_clock::now(); + double dt = chrono::duration_cast(end - begin).count(); + cout << "Total time taken " << dt/N << " us. (per loop)" << endl; + + + return 0; +} + +int run_multithreaded( ) +{ + vector t1s, t2s, t3s; + size_t N = 10000; + cout << "Running " << N << " iterations. " << endl; + + // Launch all three tests in parallel. + chrono::steady_clock::time_point begin = chrono::steady_clock::now(); + for (size_t i = 0; i < N; i++) + { + std::thread th1(test_scipy_sys); + std::thread th2(test_fex); + std::thread th3(test_github_system); + th1.join(); + th2.join(); + th3.join(); + } + + chrono::steady_clock::time_point end = chrono::steady_clock::now(); + double dt = chrono::duration_cast(end - begin).count(); + cout << "Total time taken " << dt / N << " us (per loop)." << endl; + return 0; +} + +int main(int argc, const char *argv[]) +{ + cout <<"|| running serial version" << endl; + run_serial(); + + cout <<"|| running multithreaded version" << endl; + run_multithreaded(); + return 0; +} diff --git a/external/libsoda/helper.h b/external/libsoda/helper.h new file mode 100644 index 00000000..cef7f08b --- /dev/null +++ b/external/libsoda/helper.h @@ -0,0 +1,24 @@ +#ifndef HELPER_H +#define HELPER_H + +template bool areEqual(T a, T b) { + return std::fabs(a - b) < 1e-6; +} + +template +void print_vec(const vector &v, const string prefix = "") { + cout << prefix << " SIZE=" << v.size() << " : "; + for (auto x : v) + cout << x << ','; + cout << endl; +} + +template +void print_arr( const double* a, const size_t n, const string prefix="" ) { + cout << prefix << " SIZE=" << n << " : "; + for (size_t i = 0; i < n; i++) + cout << a[i] << ','; + cout << endl; +} + +#endif /* end of include guard: HELPER_H */ diff --git a/external/libsoda/run_benchmark.sh b/external/libsoda/run_benchmark.sh new file mode 100755 index 00000000..04320cc3 --- /dev/null +++ b/external/libsoda/run_benchmark.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +set -e +set -x +valgrind --tool=callgrind --callgrind-out-file=callgrind.out ./test_lsoda +gprof2dot -f callgrind ./callgrind.out > callgrind.prof.dot +dot -Tpng ./callgrind.prof.dot > lsoda_prof.png diff --git a/external/libsoda/test_LSODA.cpp b/external/libsoda/test_LSODA.cpp new file mode 100644 index 00000000..e00dd5a3 --- /dev/null +++ b/external/libsoda/test_LSODA.cpp @@ -0,0 +1,199 @@ +/*** + * Description: test libsoda. + * + * Created: 2018-08-14 + + * Author: Dilawar Singh + * Organization: NCBS Bangalore + * License: MIT License + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "LSODA.h" +#include "helper.h" + +using namespace std; + +// Describe the system. +static void fex(double t, double *y, double *ydot, void *data) +{ + ydot[0] = 1.0E4 * y[1] * y[2] - .04E0 * y[0]; + // Don't swap ydot[1] and ydot[2]. The order will change and test will fail. + ydot[2] = 3.0E7 * y[1] * y[1]; + ydot[1] = -1.0 * (ydot[0] + ydot[2]); +} + +static void system_scipy( double t, double* y, double* ydot, void* data) +{ + double mu = 1E4; + ydot[0] = y[1]; + ydot[1] = mu * (1- y[0]*y[0]) * y[1] - y[0]; +} + +// This system is described here +// https://github.com/sdwfrost/liblsoda/issues/10 +static void system_github_issue_10(double t, double* y, double* ydot, void* data) +{ + ydot[0]= 9*y[0] + 24*y[1] + 5*cos(t)-(1/3)*sin(t); + ydot[1]= -24*y[0] -51*y[1] -95*cos(t) + (1/3)*sin(t); +} + +int test_github_system( void ) +{ + // cout << "Running test given https://github.com/sdwfrost/liblsoda/issues/10" << endl; + double t = 0e0, tout = 0.5; + + vector y = {4.0/3.0, 2.0/3.0}; + int istate = 1; + + LSODA lsoda; + + vector yout; + vector res; + + for (size_t i = 0; i < 10; i++) + { + lsoda.lsoda_update( system_github_issue_10, 2, y, yout, &t, tout, &istate, nullptr, 1e-6, 1e-6 ); + res.push_back( yout[1] ); + res.push_back( yout[2] ); + tout += 0.5; + + y[0] = yout[1]; + y[1] = yout[2]; + + cout << t << ' ' << setprecision(8) << y[0] << ' ' << y[1] << endl; + } + + cout << res[0] << ' ' << res[1] << endl; + assert( areEqual(-11.94045, res[0]) ); + assert( areEqual( 3.8610102, res[1]) ); + + if (istate <= 0) + { + cerr << "error istate = " << istate << endl; + throw runtime_error( "Failed to compute the solution." ); + } + + return 0; +} + +int test_scipy_sys( void ) +{ + cout << "Running test scipy sys" << endl; + double t, tout; + t = 0e0; tout = 10; + + vector y = {10,0}; + int istate = 1; + + LSODA lsoda; + + // Create vector to store results. NOTE THAT yout[0] will be ignored. + vector yout; + lsoda.lsoda_update( system_scipy, 2, y, yout, &t, tout, &istate, nullptr ); + + areEqual( 9.999899e+00, yout[1]); + areEqual( -1.010111e-05, yout[2] ); + + if (istate <= 0) + { + cerr << "error istate = " << istate << endl; + exit(0); + } + return 0; +} + +int test_fex(void) +{ + // cout << "Running test fex." << endl; + int neq = 3; + double t, tout; + t = 0e0; + tout = 0.4e0; + vector y = { 1e0, 0e0, 0.0 }; + int istate = 1; + + LSODA lsoda; + setprecision( 12 ); + + vector res; + + vector yout; + for (size_t iout = 1; iout <= 12; iout++) + { + lsoda.lsoda_update( fex, neq, y, yout, &t, tout, &istate, nullptr, 1e-4, 1e-8 ); + // cerr << " at t " << t << " y= " << yout[1] << ' ' << yout[2] << ' ' << yout[3] << endl; + // Update the y for next iteration. + y[0] = yout[1]; + y[1] = yout[2]; + y[2] = yout[3]; + + res.push_back( y[0] ); + res.push_back( y[1] ); + res.push_back( y[2] ); + + if (istate <= 0) + { + cerr << "error istate = " << istate << endl; + exit(0); + } + tout = tout * 10.0E0; + } + + + vector expected = { 0.985172 ,3.3864e-05 , 0.0147939 + , 0.905514 ,2.24042e-05, 0.0944634 + , 0.715803 ,9.18446e-06, 0.284188 + , 0.450479 ,3.22234e-06, 0.549517 + , 0.183171 ,8.94046e-07, 0.816828 + , 0.0389738 ,1.62135e-07, 0.961026 + , 0.00493686 ,1.98442e-08, 0.995063 + , 0.00051665 ,2.06765e-09, 0.999483 + , 5.20075e-05 ,2.08041e-10, 0.999948 + , 5.20168e-06 ,2.08068e-11, 0.999995 + , 5.19547e-07 ,2.07819e-12, 0.999999 + }; + + // Assert here. + for (size_t i = 0; i < expected.size(); i++) + { + double err = abs( expected[i] - res[i] ); + if( err > 1e-6 ) + { + cerr << "FAILED: Expected " << expected[i] << ". Got " << res[i] << endl; + assert( false ); + } + } + + return 0; +} + +int main(int argc, const char *argv[]) +{ + chrono::steady_clock::time_point begin = chrono::steady_clock::now(); + test_scipy_sys(); + chrono::steady_clock::time_point end= chrono::steady_clock::now(); + cout << "|| Time taken (us)= " << chrono::duration_cast(end - begin).count() < \___ >|__| # -# \/ \/ \/ \/ # -# Fast math parser Library # -# # -# Copyright (C) 2011 Ingo Berg # -# # -# Web: muparser.beltoforion.de # -# e-mail: muparser@beltoforion.de # -# # -# # -####################################################################### - - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/external/muparser/Makefile.in b/external/muparser/Makefile.in deleted file mode 100644 index 8d192bb1..00000000 --- a/external/muparser/Makefile.in +++ /dev/null @@ -1,368 +0,0 @@ -# ========================================================================= -# This makefile was generated by -# Bakefile 0.2.9 (http://www.bakefile.org) -# Do not modify, all changes will be overwritten! -# ========================================================================= - - -@MAKE_SET@ - -prefix = @prefix@ -exec_prefix = @exec_prefix@ -datarootdir = @datarootdir@ -INSTALL = @INSTALL@ -SHARED_LD_CXX = @SHARED_LD_CXX@ -LIBEXT = @LIBEXT@ -LIBPREFIX = @LIBPREFIX@ -SO_SUFFIX = @SO_SUFFIX@ -DLLIMP_SUFFIX = @DLLIMP_SUFFIX@ -EXEEXT = @EXEEXT@ -LN_S = @LN_S@ -SETFILE = @SETFILE@ -PIC_FLAG = @PIC_FLAG@ -SONAME_FLAG = @SONAME_FLAG@ -STRIP = @STRIP@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_DIR = @INSTALL_DIR@ -BK_DEPS = @BK_DEPS@ -srcdir = @srcdir@ -top_builddir = @top_builddir@ -libdir = @libdir@ -DLLPREFIX = @DLLPREFIX@ -LIBS = @LIBS@ -AR = @AR@ -AROPTIONS = @AROPTIONS@ -RANLIB = @RANLIB@ -CXX = @CXX@ -CXXFLAGS = @CXXFLAGS@ -CPPFLAGS = @CPPFLAGS@ -LDFLAGS = @LDFLAGS@ - -### Variables: ### - -DESTDIR = -MUPARSER_LIB_CXXFLAGS = $(____DEBUG) $(____SHARED) $(____SHARED_0) \ - -I$(srcdir)/include $(CPPFLAGS) $(CXXFLAGS) -MUPARSER_LIB_OBJECTS = \ - muParser_lib_muParser.o \ - muParser_lib_muParserBase.o \ - muParser_lib_muParserBytecode.o \ - muParser_lib_muParserCallback.o \ - muParser_lib_muParserDLL.o \ - muParser_lib_muParserError.o \ - muParser_lib_muParserInt.o \ - muParser_lib_muParserTest.o \ - muParser_lib_muParserTokenReader.o -MUPARSER_LIB_HEADERS = \ - include/muParser.h \ - include/muParserBase.h \ - include/muParserBytecode.h \ - include/muParserCallback.h \ - include/muParserDLL.h \ - include/muParserDef.h \ - include/muParserError.h \ - include/muParserFixes.h \ - include/muParserInt.h \ - include/muParserStack.h \ - include/muParserTemplateMagic.h \ - include/muParserTest.h \ - include/muParserToken.h \ - include/muParserTokenReader.h -MUPARSER_DLL_CXXFLAGS = $(____DEBUG) $(____SHARED) $(____SHARED_0) \ - -I$(srcdir)/include $(PIC_FLAG) $(CPPFLAGS) $(CXXFLAGS) -MUPARSER_DLL_OBJECTS = \ - muParser_dll_muParser.o \ - muParser_dll_muParserBase.o \ - muParser_dll_muParserBytecode.o \ - muParser_dll_muParserCallback.o \ - muParser_dll_muParserDLL.o \ - muParser_dll_muParserError.o \ - muParser_dll_muParserInt.o \ - muParser_dll_muParserTest.o \ - muParser_dll_muParserTokenReader.o -MUPARSER_DLL_HEADERS = \ - include/muParser.h \ - include/muParserBase.h \ - include/muParserBytecode.h \ - include/muParserCallback.h \ - include/muParserDLL.h \ - include/muParserDef.h \ - include/muParserError.h \ - include/muParserFixes.h \ - include/muParserInt.h \ - include/muParserStack.h \ - include/muParserTemplateMagic.h \ - include/muParserTest.h \ - include/muParserToken.h \ - include/muParserTokenReader.h -EXAMPLE1_CXXFLAGS = $(____DEBUG) -I$(srcdir)/include $(CPPFLAGS) $(CXXFLAGS) -EXAMPLE1_OBJECTS = \ - example1_example1.o - -### Conditionally set variables: ### - -@COND_DEPS_TRACKING_0@CXXC = $(CXX) -@COND_DEPS_TRACKING_1@CXXC = $(BK_DEPS) $(CXX) -@COND_DEBUG_0@DEBUG_BUILD_POSTFIX = -@COND_DEBUG_1@DEBUG_BUILD_POSTFIX = d -@COND_SHARED_0@__muParser_lib___depname = \ -@COND_SHARED_0@ $(top_builddir)/lib/$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(LIBEXT) -@COND_SHARED_0@__install_muParser_lib___depname = install_muParser_lib -@COND_SHARED_0@__uninstall_muParser_lib___depname = uninstall_muParser_lib -@COND_SHARED_0@__install_muParser_lib_headers___depname = \ -@COND_SHARED_0@ install_muParser_lib_headers -@COND_SHARED_0@__uninstall_muParser_lib_headers___depname = \ -@COND_SHARED_0@ uninstall_muParser_lib_headers -COND_SHARED_1___muParser_dll___depname = \ - $(top_builddir)/lib/$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf3) -@COND_SHARED_1@__muParser_dll___depname = $(COND_SHARED_1___muParser_dll___depname) -@COND_SHARED_1@__install_muParser_dll___depname = install_muParser_dll -@COND_SHARED_1@__uninstall_muParser_dll___depname = uninstall_muParser_dll -COND_PLATFORM_MACOSX_1___muParser_dll___macinstnamecmd = -install_name \ - $(libdir)/$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf2) -@COND_PLATFORM_MACOSX_1@__muParser_dll___macinstnamecmd = $(COND_PLATFORM_MACOSX_1___muParser_dll___macinstnamecmd) -@COND_SHARED_1@__install_muParser_dll_headers___depname = \ -@COND_SHARED_1@ install_muParser_dll_headers -@COND_SHARED_1@__uninstall_muParser_dll_headers___depname = \ -@COND_SHARED_1@ uninstall_muParser_dll_headers -COND_PLATFORM_OS2_1___muParser_dll___importlib = -import \ - $(top_builddir)/lib/$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX) -@COND_PLATFORM_OS2_1@__muParser_dll___importlib = $(COND_PLATFORM_OS2_1___muParser_dll___importlib) -COND_WINDOWS_IMPLIB_1___muParser_dll___importlib = \ - -Wl,--out-implib=$(top_builddir)/lib/$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX) -@COND_WINDOWS_IMPLIB_1@__muParser_dll___importlib = $(COND_WINDOWS_IMPLIB_1___muParser_dll___importlib) -@COND_PLATFORM_MACOSX_0_USE_SOVERSION_1@__muParser_dll___targetsuf2 \ -@COND_PLATFORM_MACOSX_0_USE_SOVERSION_1@ = .$(SO_SUFFIX).2 -@COND_PLATFORM_MACOSX_1_USE_SOVERSION_1@__muParser_dll___targetsuf2 \ -@COND_PLATFORM_MACOSX_1_USE_SOVERSION_1@ = .2.$(SO_SUFFIX) -@COND_USE_SOVERSION_0@__muParser_dll___targetsuf2 = .$(SO_SUFFIX) -@COND_PLATFORM_MACOSX_0_USE_SOVERCYGWIN_0_USE_SOVERSION_1@__muParser_dll___targetsuf3 \ -@COND_PLATFORM_MACOSX_0_USE_SOVERCYGWIN_0_USE_SOVERSION_1@ = \ -@COND_PLATFORM_MACOSX_0_USE_SOVERCYGWIN_0_USE_SOVERSION_1@ .$(SO_SUFFIX).2.2.4 -@COND_PLATFORM_MACOSX_1_USE_SOVERSION_1@__muParser_dll___targetsuf3 \ -@COND_PLATFORM_MACOSX_1_USE_SOVERSION_1@ = .2.2.4.$(SO_SUFFIX) -@COND_USE_SOVERSION_1_USE_SOVERSOLARIS_1@__muParser_dll___targetsuf3 \ -@COND_USE_SOVERSION_1_USE_SOVERSOLARIS_1@ = .$(SO_SUFFIX).2 -@COND_USE_SOVERCYGWIN_1_USE_SOVERSION_1@__muParser_dll___targetsuf3 \ -@COND_USE_SOVERCYGWIN_1_USE_SOVERSION_1@ = -2.$(SO_SUFFIX) -@COND_USE_SOVERSION_0@__muParser_dll___targetsuf3 = .$(SO_SUFFIX) -COND_USE_SOVERLINUX_1___muParser_dll___soname_flags = \ - $(SONAME_FLAG)$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf2) -@COND_USE_SOVERLINUX_1@__muParser_dll___soname_flags = $(COND_USE_SOVERLINUX_1___muParser_dll___soname_flags) -COND_USE_SOVERSOLARIS_1___muParser_dll___soname_flags = \ - $(SONAME_FLAG)$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf3) -@COND_USE_SOVERSOLARIS_1@__muParser_dll___soname_flags = $(COND_USE_SOVERSOLARIS_1___muParser_dll___soname_flags) -COND_USE_SOTWOSYMLINKS_1___muParser_dll___so_symlinks_cmd = (cd \ - $(top_builddir)/lib/; rm -f \ - $(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX) \ - $(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf2); \ - $(LN_S) \ - $(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf3) \ - $(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf2); \ - $(LN_S) \ - $(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf2) \ - $(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX)) -@COND_USE_SOTWOSYMLINKS_1@__muParser_dll___so_symlinks_cmd = $(COND_USE_SOTWOSYMLINKS_1___muParser_dll___so_symlinks_cmd) -COND_USE_SOVERSOLARIS_1___muParser_dll___so_symlinks_cmd = (cd \ - $(top_builddir)/lib/; rm -f \ - $(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX); $(LN_S) \ - $(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf3) \ - $(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX)) -@COND_USE_SOVERSOLARIS_1@__muParser_dll___so_symlinks_cmd = $(COND_USE_SOVERSOLARIS_1___muParser_dll___so_symlinks_cmd) -COND_USE_SOTWOSYMLINKS_1___muParser_dll___so_symlinks_inst_cmd = rm -f \ - $(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX) \ - $(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf2); \ - $(LN_S) \ - $(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf3) \ - $(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf2); \ - $(LN_S) \ - $(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf2) \ - $(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX) -@COND_USE_SOTWOSYMLINKS_1@__muParser_dll___so_symlinks_inst_cmd = $(COND_USE_SOTWOSYMLINKS_1___muParser_dll___so_symlinks_inst_cmd) -COND_USE_SOVERSOLARIS_1___muParser_dll___so_symlinks_inst_cmd = rm -f \ - $(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX); $(LN_S) \ - $(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf3) \ - $(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX); -@COND_USE_SOVERSOLARIS_1@__muParser_dll___so_symlinks_inst_cmd = $(COND_USE_SOVERSOLARIS_1___muParser_dll___so_symlinks_inst_cmd) -COND_USE_SOTWOSYMLINKS_1___muParser_dll___so_symlinks_uninst_cmd = rm -f \ - $(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf2) \ - $(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX) -@COND_USE_SOTWOSYMLINKS_1@__muParser_dll___so_symlinks_uninst_cmd = $(COND_USE_SOTWOSYMLINKS_1___muParser_dll___so_symlinks_uninst_cmd) -@COND_USE_SOVERSOLARIS_1@__muParser_dll___so_symlinks_uninst_cmd \ -@COND_USE_SOVERSOLARIS_1@ = rm -f \ -@COND_USE_SOVERSOLARIS_1@ $(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX) -@COND_PLATFORM_MACOSX_1@__muParser_dll___macver = \ -@COND_PLATFORM_MACOSX_1@ -compatibility_version 1 -current_version 1 -@COND_SAMPLES_1@__example1___depname = \ -@COND_SAMPLES_1@ $(top_builddir)/samples/example1/example1$(EXEEXT) -@COND_PLATFORM_MAC_0@__example1___mac_setfilecmd = @true -@COND_PLATFORM_MAC_1@__example1___mac_setfilecmd = \ -@COND_PLATFORM_MAC_1@ $(SETFILE) -t APPL \ -@COND_PLATFORM_MAC_1@ $(top_builddir)/samples/example1/example1$(EXEEXT) -@COND_SHARED_0@____SHARED = -@COND_SHARED_1@____SHARED = -DMUPARSER_DLL -@COND_SHARED_0@____SHARED_0 = -@COND_SHARED_1@____SHARED_0 = -DMUPARSERLIB_EXPORTS -@COND_DEBUG_0@____DEBUG = -DNDEBUG -@COND_DEBUG_1@____DEBUG = - -### Targets: ### - -all: $(__muParser_lib___depname) $(__muParser_dll___depname) $(__example1___depname) - -install: $(__install_muParser_lib___depname) $(__install_muParser_lib_headers___depname) $(__install_muParser_dll___depname) $(__install_muParser_dll_headers___depname) - $(INSTALL_DIR) $(DESTDIR)$(libdir)/pkgconfig - $(INSTALL_DATA) build/autoconf/muparser.pc $(DESTDIR)$(libdir)/pkgconfig - -uninstall: $(__uninstall_muParser_lib___depname) $(__uninstall_muParser_lib_headers___depname) $(__uninstall_muParser_dll___depname) $(__uninstall_muParser_dll_headers___depname) - -install-strip: install - $(STRIP) $(DESTDIR)$(libdir)/$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf3) - -clean: - rm -rf ./.deps ./.pch - rm -f ./*.o - rm -f $(top_builddir)/lib/$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(LIBEXT) - rm -f $(top_builddir)/lib/$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf3) - rm -f $(top_builddir)/lib/$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX) - rm -f $(top_builddir)/lib/$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX) $(top_builddir)/lib/$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf2) - rm -f $(top_builddir)/samples/example1/example1$(EXEEXT) - -distclean: clean - rm -f config.cache config.log config.status bk-deps bk-make-pch shared-ld-sh Makefile - rm -f build/autoconf/muparser.pc - -@COND_SHARED_0@$(top_builddir)/lib/$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(LIBEXT): $(MUPARSER_LIB_OBJECTS) -@COND_SHARED_0@ rm -f $@ -@COND_SHARED_0@ $(AR) $(AROPTIONS) $@ $(MUPARSER_LIB_OBJECTS) -@COND_SHARED_0@ $(RANLIB) $@ - -@COND_SHARED_0@install_muParser_lib: $(__muParser_lib___depname) -@COND_SHARED_0@ $(INSTALL_DIR) $(DESTDIR)$(libdir) -@COND_SHARED_0@ $(INSTALL_DATA) $(top_builddir)/lib/$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(LIBEXT) $(DESTDIR)$(libdir) - -@COND_SHARED_0@uninstall_muParser_lib: -@COND_SHARED_0@ rm -f $(DESTDIR)$(libdir)/$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(LIBEXT) - -@COND_SHARED_0@install_muParser_lib_headers: -@COND_SHARED_0@ $(INSTALL_DIR) $(DESTDIR)$(prefix) -@COND_SHARED_0@ for f in $(MUPARSER_LIB_HEADERS); do \ -@COND_SHARED_0@ if test ! -d $(DESTDIR)$(prefix)/`dirname $$f` ; then \ -@COND_SHARED_0@ $(INSTALL_DIR) $(DESTDIR)$(prefix)/`dirname $$f`; \ -@COND_SHARED_0@ fi; \ -@COND_SHARED_0@ $(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(prefix)/$$f; \ -@COND_SHARED_0@ done - -@COND_SHARED_0@uninstall_muParser_lib_headers: -@COND_SHARED_0@ for f in $(MUPARSER_LIB_HEADERS); do \ -@COND_SHARED_0@ rm -f $(DESTDIR)$(prefix)/$$f; \ -@COND_SHARED_0@ done - -@COND_SHARED_1@$(top_builddir)/lib/$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf3): $(MUPARSER_DLL_OBJECTS) -@COND_SHARED_1@ $(SHARED_LD_CXX) $@ $(MUPARSER_DLL_OBJECTS) $(__muParser_dll___macinstnamecmd) $(__muParser_dll___importlib) $(__muParser_dll___soname_flags) $(__muParser_dll___macver) $(LDFLAGS) $(LIBS) -@COND_SHARED_1@ -@COND_SHARED_1@ $(__muParser_dll___so_symlinks_cmd) - -@COND_SHARED_1@install_muParser_dll: $(__muParser_dll___depname) -@COND_SHARED_1@ $(INSTALL_DIR) $(DESTDIR)$(libdir) -@COND_SHARED_1@ $(INSTALL_DATA) $(top_builddir)/lib/$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX) $(DESTDIR)$(libdir) -@COND_SHARED_1@ $(INSTALL_PROGRAM) $(top_builddir)/lib/$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf3) $(DESTDIR)$(libdir) -@COND_SHARED_1@ (cd $(DESTDIR)$(libdir) ; $(__muParser_dll___so_symlinks_inst_cmd)) - -@COND_SHARED_1@uninstall_muParser_dll: -@COND_SHARED_1@ rm -f $(DESTDIR)$(libdir)/$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX) -@COND_SHARED_1@ rm -f $(DESTDIR)$(libdir)/$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf3) -@COND_SHARED_1@ (cd $(DESTDIR)$(libdir) ; $(__muParser_dll___so_symlinks_uninst_cmd)) - -@COND_SHARED_1@install_muParser_dll_headers: -@COND_SHARED_1@ $(INSTALL_DIR) $(DESTDIR)$(prefix) -@COND_SHARED_1@ for f in $(MUPARSER_DLL_HEADERS); do \ -@COND_SHARED_1@ if test ! -d $(DESTDIR)$(prefix)/`dirname $$f` ; then \ -@COND_SHARED_1@ $(INSTALL_DIR) $(DESTDIR)$(prefix)/`dirname $$f`; \ -@COND_SHARED_1@ fi; \ -@COND_SHARED_1@ $(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(prefix)/$$f; \ -@COND_SHARED_1@ done - -@COND_SHARED_1@uninstall_muParser_dll_headers: -@COND_SHARED_1@ for f in $(MUPARSER_DLL_HEADERS); do \ -@COND_SHARED_1@ rm -f $(DESTDIR)$(prefix)/$$f; \ -@COND_SHARED_1@ done - -@COND_SAMPLES_1@$(top_builddir)/samples/example1/example1$(EXEEXT): $(EXAMPLE1_OBJECTS) $(__muParser_lib___depname) -@COND_SAMPLES_1@ $(CXX) -o $@ $(EXAMPLE1_OBJECTS) -L$(top_builddir)/lib -L$(srcdir)/lib $(LDFLAGS) -lmuparser$(DEBUG_BUILD_POSTFIX) $(LIBS) -@COND_SAMPLES_1@ -@COND_SAMPLES_1@ $(__example1___mac_setfilecmd) - -lib: $(__muParser_lib___depname) $(__muParser_dll___depname) - -samples: $(__example1___depname) - -documentation: - ( cd $(srcdir)/docs && doxygen ) - -muParser_lib_muParser.o: $(srcdir)/src/muParser.cpp - $(CXXC) -c -o $@ $(MUPARSER_LIB_CXXFLAGS) $(srcdir)/src/muParser.cpp - -muParser_lib_muParserBase.o: $(srcdir)/src/muParserBase.cpp - $(CXXC) -c -o $@ $(MUPARSER_LIB_CXXFLAGS) $(srcdir)/src/muParserBase.cpp - -muParser_lib_muParserBytecode.o: $(srcdir)/src/muParserBytecode.cpp - $(CXXC) -c -o $@ $(MUPARSER_LIB_CXXFLAGS) $(srcdir)/src/muParserBytecode.cpp - -muParser_lib_muParserCallback.o: $(srcdir)/src/muParserCallback.cpp - $(CXXC) -c -o $@ $(MUPARSER_LIB_CXXFLAGS) $(srcdir)/src/muParserCallback.cpp - -muParser_lib_muParserDLL.o: $(srcdir)/src/muParserDLL.cpp - $(CXXC) -c -o $@ $(MUPARSER_LIB_CXXFLAGS) $(srcdir)/src/muParserDLL.cpp - -muParser_lib_muParserError.o: $(srcdir)/src/muParserError.cpp - $(CXXC) -c -o $@ $(MUPARSER_LIB_CXXFLAGS) $(srcdir)/src/muParserError.cpp - -muParser_lib_muParserInt.o: $(srcdir)/src/muParserInt.cpp - $(CXXC) -c -o $@ $(MUPARSER_LIB_CXXFLAGS) $(srcdir)/src/muParserInt.cpp - -muParser_lib_muParserTest.o: $(srcdir)/src/muParserTest.cpp - $(CXXC) -c -o $@ $(MUPARSER_LIB_CXXFLAGS) $(srcdir)/src/muParserTest.cpp - -muParser_lib_muParserTokenReader.o: $(srcdir)/src/muParserTokenReader.cpp - $(CXXC) -c -o $@ $(MUPARSER_LIB_CXXFLAGS) $(srcdir)/src/muParserTokenReader.cpp - -muParser_dll_muParser.o: $(srcdir)/src/muParser.cpp - $(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParser.cpp - -muParser_dll_muParserBase.o: $(srcdir)/src/muParserBase.cpp - $(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParserBase.cpp - -muParser_dll_muParserBytecode.o: $(srcdir)/src/muParserBytecode.cpp - $(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParserBytecode.cpp - -muParser_dll_muParserCallback.o: $(srcdir)/src/muParserCallback.cpp - $(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParserCallback.cpp - -muParser_dll_muParserDLL.o: $(srcdir)/src/muParserDLL.cpp - $(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParserDLL.cpp - -muParser_dll_muParserError.o: $(srcdir)/src/muParserError.cpp - $(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParserError.cpp - -muParser_dll_muParserInt.o: $(srcdir)/src/muParserInt.cpp - $(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParserInt.cpp - -muParser_dll_muParserTest.o: $(srcdir)/src/muParserTest.cpp - $(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParserTest.cpp - -muParser_dll_muParserTokenReader.o: $(srcdir)/src/muParserTokenReader.cpp - $(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParserTokenReader.cpp - -example1_example1.o: $(srcdir)/samples/example1/example1.cpp - $(CXXC) -c -o $@ $(EXAMPLE1_CXXFLAGS) $(srcdir)/samples/example1/example1.cpp - - -# Include dependency info, if present: -@IF_GNU_MAKE@-include ./.deps/*.d - -.PHONY: all install uninstall clean distclean install_muParser_lib \ - uninstall_muParser_lib install_muParser_lib_headers \ - uninstall_muParser_lib_headers install_muParser_dll uninstall_muParser_dll \ - install_muParser_dll_headers uninstall_muParser_dll_headers lib samples diff --git a/external/muparser/include/muParser.h b/external/muparser/include/muParser.h deleted file mode 100644 index c1baf798..00000000 --- a/external/muparser/include/muParser.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2013 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -#ifndef MU_PARSER_H -#define MU_PARSER_H - -//--- Standard includes ------------------------------------------------------------------------ -#include - -//--- Parser includes -------------------------------------------------------------------------- -#include "muParserBase.h" -#include "muParserTemplateMagic.h" - -// Get the random number generator type from here. -#include "../../../randnum/RNG.h" - -extern moose::RNG rng; - -/** \file - \brief Definition of the standard floating point parser. -*/ - -namespace mu -{ - /** \brief Mathematical expressions parser. - - Standard implementation of the mathematical expressions parser. - Can be used as a reference implementation for subclassing the parser. - - - (C) 2011 Ingo Berg
- muparser(at)beltoforion.de -
- */ - /* final */ class Parser : public ParserBase - { - public: - - Parser(); - - virtual void InitCharSets(); - virtual void InitFun(); - virtual void InitConst(); - virtual void InitOprt(); - virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd); - - value_type Diff(value_type *a_Var, - value_type a_fPos, - value_type a_fEpsilon = 0) const; - - protected: - - // Trigonometric functions - static value_type Sin(value_type); - static value_type Cos(value_type); - static value_type Tan(value_type); - static value_type Tan2(value_type, value_type); - // arcus functions - static value_type ASin(value_type); - static value_type ACos(value_type); - static value_type ATan(value_type); - static value_type ATan2(value_type, value_type); - - // hyperbolic functions - static value_type Sinh(value_type); - static value_type Cosh(value_type); - static value_type Tanh(value_type); - // arcus hyperbolic functions - static value_type ASinh(value_type); - static value_type ACosh(value_type); - static value_type ATanh(value_type); - // Logarithm functions - static value_type Log2(value_type); // Logarithm Base 2 - static value_type Log10(value_type); // Logarithm Base 10 - static value_type Ln(value_type); // Logarithm Base e (natural logarithm) - // misc - static value_type Exp(value_type); - static value_type Abs(value_type); - static value_type Sqrt(value_type); - static value_type Rint(value_type); - static value_type Sign(value_type); - static value_type Fmod(value_type, value_type); - static value_type Quot(value_type, value_type); - - // Random between a and b, with fixed seed. - static value_type Rand2(value_type, value_type, value_type); - - // Random number between 0 and 1, non-deterministic seed. - static value_type Rand( value_type seed ); - static value_type Rnd( ); - - // Prefix operators - // !!! Unary Minus is a MUST if you want to use negative signs !!! - static value_type UnaryMinus(value_type); - static value_type UnaryPlus(value_type); - - // Functions with variable number of arguments - static value_type Sum(const value_type*, int); // sum - static value_type Avg(const value_type*, int); // mean value - static value_type Min(const value_type*, int); // minimum - static value_type Max(const value_type*, int); // maximum - - static int IsVal(const char_type* a_szExpr, int *a_iPos, value_type *a_fVal); - }; -} // namespace mu - -#endif - diff --git a/external/muparser/include/muParserBase.h b/external/muparser/include/muParserBase.h deleted file mode 100644 index e7cfa6ae..00000000 --- a/external/muparser/include/muParserBase.h +++ /dev/null @@ -1,317 +0,0 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2013 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -#ifndef MU_PARSER_BASE_H -#define MU_PARSER_BASE_H - -//--- Standard includes ------------------------------------------------------------------------ -#include -#include -#include -#include -#include -#include -#include - -//--- Parser includes -------------------------------------------------------------------------- -#include "muParserDef.h" -#include "muParserStack.h" -#include "muParserTokenReader.h" -#include "muParserBytecode.h" -#include "muParserError.h" - - -namespace mu -{ -/** \file - \brief This file contains the class definition of the muparser engine. -*/ - -//-------------------------------------------------------------------------------------------------- -/** \brief Mathematical expressions parser (base parser engine). - \author (C) 2013 Ingo Berg - - This is the implementation of a bytecode based mathematical expressions parser. - The formula will be parsed from string and converted into a bytecode. - Future calculations will be done with the bytecode instead the formula string - resulting in a significant performance increase. - Complementary to a set of internally implemented functions the parser is able to handle - user defined functions and variables. -*/ -class ParserBase -{ -friend class ParserTokenReader; - -private: - - /** \brief Typedef for the parse functions. - - The parse function do the actual work. The parser exchanges - the function pointer to the parser function depending on - which state it is in. (i.e. bytecode parser vs. string parser) - */ - typedef value_type (ParserBase::*ParseFunction)() const; - - /** \brief Type used for storing an array of values. */ - typedef std::vector valbuf_type; - - /** \brief Type for a vector of strings. */ - typedef std::vector stringbuf_type; - - /** \brief Typedef for the token reader. */ - typedef ParserTokenReader token_reader_type; - - /** \brief Type used for parser tokens. */ - typedef ParserToken token_type; - - /** \brief Maximum number of threads spawned by OpenMP when using the bulk mode. */ - static const int s_MaxNumOpenMPThreads = 16; - - public: - - /** \brief Type of the error class. - - Included for backwards compatibility. - */ - typedef ParserError exception_type; - - static void EnableDebugDump(bool bDumpCmd, bool bDumpStack); - - ParserBase(); - ParserBase(const ParserBase &a_Parser); - ParserBase& operator=(const ParserBase &a_Parser); - - virtual ~ParserBase(); - - value_type Eval() const; - value_type* Eval(int &nStackSize) const; - void Eval(value_type *results, int nBulkSize); - - int GetNumResults() const; - - void SetExpr(const string_type &a_sExpr); - void SetVarFactory(facfun_type a_pFactory, void *pUserData = NULL); - - void SetDecSep(char_type cDecSep); - void SetThousandsSep(char_type cThousandsSep = 0); - void ResetLocale(); - - void EnableOptimizer(bool a_bIsOn=true); - void EnableBuiltInOprt(bool a_bIsOn=true); - - bool HasBuiltInOprt() const; - void AddValIdent(identfun_type a_pCallback); - - /** \fn void mu::ParserBase::DefineFun(const string_type &a_strName, fun_type0 a_pFun, bool a_bAllowOpt = true) - \brief Define a parser function without arguments. - \param a_strName Name of the function - \param a_pFun Pointer to the callback function - \param a_bAllowOpt A flag indicating this function may be optimized - */ - template - void DefineFun(const string_type &a_strName, T a_pFun, bool a_bAllowOpt = true) - { - AddCallback( a_strName, ParserCallback(a_pFun, a_bAllowOpt), m_FunDef, ValidNameChars() ); - } - - void DefineOprt(const string_type &a_strName, - fun_type2 a_pFun, - unsigned a_iPri=0, - EOprtAssociativity a_eAssociativity = oaLEFT, - bool a_bAllowOpt = false); - void DefineConst(const string_type &a_sName, value_type a_fVal); - void DefineStrConst(const string_type &a_sName, const string_type &a_strVal); - void DefineVar(const string_type &a_sName, value_type *a_fVar); - void DefinePostfixOprt(const string_type &a_strFun, fun_type1 a_pOprt, bool a_bAllowOpt=true); - void DefineInfixOprt(const string_type &a_strName, fun_type1 a_pOprt, int a_iPrec=prINFIX, bool a_bAllowOpt=true); - - // Clear user defined variables, constants or functions - void ClearVar(); - void ClearFun(); - void ClearConst(); - void ClearInfixOprt(); - void ClearPostfixOprt(); - void ClearOprt(); - - void RemoveVar(const string_type &a_strVarName); - const varmap_type& GetUsedVar() const; - const varmap_type& GetVar() const; - const valmap_type& GetConst() const; - const string_type& GetExpr() const; - const funmap_type& GetFunDef() const; - string_type GetVersion(EParserVersionInfo eInfo = pviFULL) const; - - const char_type ** GetOprtDef() const; - void DefineNameChars(const char_type *a_szCharset); - void DefineOprtChars(const char_type *a_szCharset); - void DefineInfixOprtChars(const char_type *a_szCharset); - - const char_type* ValidNameChars() const; - const char_type* ValidOprtChars() const; - const char_type* ValidInfixOprtChars() const; - - void SetArgSep(char_type cArgSep); - char_type GetArgSep() const; - - void Error(EErrorCodes a_iErrc, - int a_iPos = (int)mu::string_type::npos, - const string_type &a_strTok = string_type() ) const; - - protected: - - void Init(); - - virtual void InitCharSets() = 0; - virtual void InitFun() = 0; - virtual void InitConst() = 0; - virtual void InitOprt() = 0; - - virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd); - - static const char_type *c_DefaultOprt[]; - static std::locale s_locale; ///< The locale used by the parser - static bool g_DbgDumpCmdCode; - static bool g_DbgDumpStack; - - /** \brief A facet class used to change decimal and thousands separator. */ - template - class change_dec_sep : public std::numpunct - { - public: - - explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3) - :std::numpunct() - ,m_nGroup(nGroup) - ,m_cDecPoint(cDecSep) - ,m_cThousandsSep(cThousandsSep) - {} - - protected: - - virtual char_type do_decimal_point() const - { - return m_cDecPoint; - } - - virtual char_type do_thousands_sep() const - { - return m_cThousandsSep; - } - - virtual std::string do_grouping() const - { - // fix for issue 4: https://code.google.com/p/muparser/issues/detail?id=4 - // courtesy of Jens Bartsch - // original code: - // return std::string(1, (char)m_nGroup); - // new code: - return std::string(1, (char)(m_cThousandsSep > 0 ? m_nGroup : CHAR_MAX)); - } - - private: - - int m_nGroup; - char_type m_cDecPoint; - char_type m_cThousandsSep; - }; - - private: - - void Assign(const ParserBase &a_Parser); - void InitTokenReader(); - void ReInit() const; - - void AddCallback( const string_type &a_strName, - const ParserCallback &a_Callback, - funmap_type &a_Storage, - const char_type *a_szCharSet ); - - void ApplyRemainingOprt(ParserStack &a_stOpt, - ParserStack &a_stVal) const; - void ApplyBinOprt(ParserStack &a_stOpt, - ParserStack &a_stVal) const; - - void ApplyIfElse(ParserStack &a_stOpt, - ParserStack &a_stVal) const; - - void ApplyFunc(ParserStack &a_stOpt, - ParserStack &a_stVal, - int iArgCount) const; - - token_type ApplyStrFunc(const token_type &a_FunTok, - const std::vector &a_vArg) const; - - int GetOprtPrecedence(const token_type &a_Tok) const; - EOprtAssociativity GetOprtAssociativity(const token_type &a_Tok) const; - - void CreateRPN() const; - - value_type ParseString() const; - value_type ParseCmdCode() const; - value_type ParseCmdCodeBulk(int nOffset, int nThreadID) const; - - void CheckName(const string_type &a_strName, const string_type &a_CharSet) const; - void CheckOprt(const string_type &a_sName, - const ParserCallback &a_Callback, - const string_type &a_szCharSet) const; - - void StackDump(const ParserStack &a_stVal, - const ParserStack &a_stOprt) const; - - /** \brief Pointer to the parser function. - - Eval() calls the function whose address is stored there. - */ - mutable ParseFunction m_pParseFormula; - mutable ParserByteCode m_vRPN; ///< The Bytecode class. - mutable stringbuf_type m_vStringBuf; ///< String buffer, used for storing string function arguments - stringbuf_type m_vStringVarBuf; - - std::shared_ptr m_pTokenReader; ///< Managed pointer to the token reader object. - - funmap_type m_FunDef; ///< Map of function names and pointers. - funmap_type m_PostOprtDef; ///< Postfix operator callbacks - funmap_type m_InfixOprtDef; ///< unary infix operator. - funmap_type m_OprtDef; ///< Binary operator callbacks - valmap_type m_ConstDef; ///< user constants. - strmap_type m_StrVarDef; ///< user defined string constants - varmap_type m_VarDef; ///< user defind variables. - - bool m_bBuiltInOp; ///< Flag that can be used for switching built in operators on and off - - string_type m_sNameChars; ///< Charset for names - string_type m_sOprtChars; ///< Charset for postfix/ binary operator tokens - string_type m_sInfixOprtChars; ///< Charset for infix operator tokens - - mutable int m_nIfElseCounter; ///< Internal counter for keeping track of nested if-then-else clauses - - // items merely used for caching state information - mutable valbuf_type m_vStackBuffer; ///< This is merely a buffer used for the stack in the cmd parsing routine - mutable int m_nFinalResultIdx; -}; - -} // namespace mu - -#endif - diff --git a/external/muparser/include/muParserBytecode.h b/external/muparser/include/muParserBytecode.h deleted file mode 100644 index 6f931f9c..00000000 --- a/external/muparser/include/muParserBytecode.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2004-2013 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -#ifndef MU_PARSER_BYTECODE_H -#define MU_PARSER_BYTECODE_H - -#include -#include -#include -#include - -#include "muParserDef.h" -#include "muParserError.h" -#include "muParserToken.h" - -/** \file - \brief Definition of the parser bytecode class. -*/ - - -namespace mu -{ - struct SToken - { - ECmdCode Cmd; - int StackPos; - - union - { - struct //SValData - { - value_type *ptr; - value_type data; - value_type data2; - } Val; - - struct //SFunData - { - // Note: generic_fun_type is merely a placeholder. The real type could be - // anything between gun_type1 and fun_type9. I can't use a void - // pointer due to constraints in the ANSI standard which allows - // data pointers and function pointers to differ in size. - generic_fun_type ptr; - int argc; - int idx; - } Fun; - - struct //SOprtData - { - value_type *ptr; - int offset; - } Oprt; - }; - }; - - - /** \brief Bytecode implementation of the Math Parser. - - The bytecode contains the formula converted to revers polish notation stored in a continious - memory area. Associated with this data are operator codes, variable pointers, constant - values and function pointers. Those are necessary in order to calculate the result. - All those data items will be casted to the underlying datatype of the bytecode. - - \author (C) 2004-2013 Ingo Berg -*/ -class ParserByteCode -{ -private: - - /** \brief Token type for internal use only. */ - typedef ParserToken token_type; - - /** \brief Token vector for storing the RPN. */ - typedef std::vector rpn_type; - - /** \brief Position in the Calculation array. */ - unsigned m_iStackPos; - - /** \brief Maximum size needed for the stack. */ - std::size_t m_iMaxStackSize; - - /** \brief The actual rpn storage. */ - rpn_type m_vRPN; - - bool m_bEnableOptimizer; - - void ConstantFolding(ECmdCode a_Oprt); - -public: - - ParserByteCode(); - ParserByteCode(const ParserByteCode &a_ByteCode); - ParserByteCode& operator=(const ParserByteCode &a_ByteCode); - void Assign(const ParserByteCode &a_ByteCode); - - void AddVar(value_type *a_pVar); - void AddVal(value_type a_fVal); - void AddOp(ECmdCode a_Oprt); - void AddIfElse(ECmdCode a_Oprt); - void AddAssignOp(value_type *a_pVar); - void AddFun(generic_fun_type a_pFun, int a_iArgc); - void AddBulkFun(generic_fun_type a_pFun, int a_iArgc); - void AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx); - - void EnableOptimizer(bool bStat); - - void Finalize(); - void clear(); - std::size_t GetMaxStackSize() const; - std::size_t GetSize() const; - - const SToken* GetBase() const; - void AsciiDump(); -}; - -} // namespace mu - -#endif - - diff --git a/external/muparser/include/muParserCallback.h b/external/muparser/include/muParserCallback.h deleted file mode 100644 index 9ecd61a6..00000000 --- a/external/muparser/include/muParserCallback.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2004-2011 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef MU_PARSER_CALLBACK_H -#define MU_PARSER_CALLBACK_H - -#include "muParserDef.h" - -/** \file - \brief Definition of the parser callback class. -*/ - -namespace mu -{ - -/** \brief Encapsulation of prototypes for a numerical parser function. - - Encapsulates the prototyp for numerical parser functions. The class - stores the number of arguments for parser functions as well - as additional flags indication the function is non optimizeable. - The pointer to the callback function pointer is stored as void* - and needs to be casted according to the argument count. - Negative argument counts indicate a parser function with a variable number - of arguments. - - \author (C) 2004-2011 Ingo Berg -*/ -class ParserCallback -{ -public: - ParserCallback(fun_type0 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec = -1, ECmdCode a_iCode=cmFUNC); - ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti, int a_iPrec, EOprtAssociativity a_eAssociativity); - ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type3 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type4 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type5 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type6 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type7 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type8 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type9 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti); - - ParserCallback(bulkfun_type0 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type1 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type2 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type3 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type4 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type5 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type6 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type7 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type8 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type9 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti); - - ParserCallback(multfun_type a_pFun, bool a_bAllowOpti); - ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti); - ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti); - ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti); - ParserCallback(); - ParserCallback(const ParserCallback &a_Fun); - - ParserCallback* Clone() const; - - bool IsOptimizable() const; - void* GetAddr() const; - ECmdCode GetCode() const; - ETypeCode GetType() const; - int GetPri() const; - EOprtAssociativity GetAssociativity() const; - int GetArgc() const; - -private: - void *m_pFun; ///< Pointer to the callback function, casted to void - - /** \brief Number of numeric function arguments - - This number is negative for functions with variable number of arguments. in this cases - they represent the actual number of arguments found. - */ - int m_iArgc; - int m_iPri; ///< Valid only for binary and infix operators; Operator precedence. - EOprtAssociativity m_eOprtAsct; ///< Operator associativity; Valid only for binary operators - ECmdCode m_iCode; - ETypeCode m_iType; - bool m_bAllowOpti; ///< Flag indication optimizeability -}; - -//------------------------------------------------------------------------------ -/** \brief Container for Callback objects. */ -typedef std::map funmap_type; - -} // namespace mu - -#endif - diff --git a/external/muparser/include/muParserDLL.h b/external/muparser/include/muParserDLL.h deleted file mode 100644 index dc0709c7..00000000 --- a/external/muparser/include/muParserDLL.h +++ /dev/null @@ -1,241 +0,0 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2011 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -#ifndef MU_PARSER_DLL_H -#define MU_PARSER_DLL_H - -#if defined(WIN32) || defined(_WIN32) - #ifdef MUPARSERLIB_EXPORTS - #define API_EXPORT(TYPE) __declspec(dllexport) TYPE __cdecl - #else - #define API_EXPORT(TYPE) __declspec(dllimport) TYPE __cdecl - #endif -#else - #define API_EXPORT(TYPE) TYPE -#endif - - -#ifdef __cplusplus -extern "C" -{ -#endif - -/** \file - \brief This file contains the DLL interface of muparser. -*/ - -// Basic types -typedef void* muParserHandle_t; // parser handle - -#ifndef _UNICODE - typedef char muChar_t; // character type -#else - typedef wchar_t muChar_t; // character type -#endif - -typedef int muBool_t; // boolean type -typedef int muInt_t; // integer type -typedef double muFloat_t; // floating point type - -// function types for calculation -typedef muFloat_t (*muFun0_t )(); -typedef muFloat_t (*muFun1_t )(muFloat_t); -typedef muFloat_t (*muFun2_t )(muFloat_t, muFloat_t); -typedef muFloat_t (*muFun3_t )(muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muFun4_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muFun5_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muFun6_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muFun7_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muFun8_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muFun9_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muFun10_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); - -// Function prototypes for bulkmode functions -typedef muFloat_t (*muBulkFun0_t )(int, int); -typedef muFloat_t (*muBulkFun1_t )(int, int, muFloat_t); -typedef muFloat_t (*muBulkFun2_t )(int, int, muFloat_t, muFloat_t); -typedef muFloat_t (*muBulkFun3_t )(int, int, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muBulkFun4_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muBulkFun5_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muBulkFun6_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muBulkFun7_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muBulkFun8_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muBulkFun9_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muBulkFun10_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); - -typedef muFloat_t (*muMultFun_t)(const muFloat_t*, muInt_t); -typedef muFloat_t (*muStrFun1_t)(const muChar_t*); -typedef muFloat_t (*muStrFun2_t)(const muChar_t*, muFloat_t); -typedef muFloat_t (*muStrFun3_t)(const muChar_t*, muFloat_t, muFloat_t); - -// Functions for parser management -typedef void (*muErrorHandler_t)(muParserHandle_t a_hParser); // [optional] callback to an error handler -typedef muFloat_t* (*muFacFun_t)(const muChar_t*, void*); // [optional] callback for creating new variables -typedef muInt_t (*muIdentFun_t)(const muChar_t*, muInt_t*, muFloat_t*); // [optional] value identification callbacks - -//----------------------------------------------------------------------------------------------------- -// Constants -static const int muOPRT_ASCT_LEFT = 0; -static const int muOPRT_ASCT_RIGHT = 1; - -static const int muBASETYPE_FLOAT = 0; -static const int muBASETYPE_INT = 1; - -//----------------------------------------------------------------------------------------------------- -// -// -// muParser C compatible bindings -// -// -//----------------------------------------------------------------------------------------------------- - - -// Basic operations / initialization -API_EXPORT(muParserHandle_t) mupCreate(int nBaseType); -API_EXPORT(void) mupRelease(muParserHandle_t a_hParser); -API_EXPORT(const muChar_t*) mupGetExpr(muParserHandle_t a_hParser); -API_EXPORT(void) mupSetExpr(muParserHandle_t a_hParser, const muChar_t *a_szExpr); -API_EXPORT(void) mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void* pUserData); -API_EXPORT(const muChar_t*) mupGetVersion(muParserHandle_t a_hParser); -API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser); -API_EXPORT(muFloat_t*) mupEvalMulti(muParserHandle_t a_hParser, int *nNum); -API_EXPORT(void) mupEvalBulk(muParserHandle_t a_hParser, muFloat_t *a_fResult, int nSize); - -// Defining callbacks / variables / constants -API_EXPORT(void) mupDefineFun0(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun0_t a_pFun, muBool_t a_bOptimize); -API_EXPORT(void) mupDefineFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun1_t a_pFun, muBool_t a_bOptimize); -API_EXPORT(void) mupDefineFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun2_t a_pFun, muBool_t a_bOptimize); -API_EXPORT(void) mupDefineFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun3_t a_pFun, muBool_t a_bOptimize); -API_EXPORT(void) mupDefineFun4(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun4_t a_pFun, muBool_t a_bOptimize); -API_EXPORT(void) mupDefineFun5(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun5_t a_pFun, muBool_t a_bOptimize); -API_EXPORT(void) mupDefineFun6(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun6_t a_pFun, muBool_t a_bOptimize); -API_EXPORT(void) mupDefineFun7(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun7_t a_pFun, muBool_t a_bOptimize); -API_EXPORT(void) mupDefineFun8(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun8_t a_pFun, muBool_t a_bOptimize); -API_EXPORT(void) mupDefineFun9(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun9_t a_pFun, muBool_t a_bOptimize); -API_EXPORT(void) mupDefineFun10(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun10_t a_pFun, muBool_t a_bOptimize); - -// Defining bulkmode functions -API_EXPORT(void) mupDefineBulkFun0(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun0_t a_pFun); -API_EXPORT(void) mupDefineBulkFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun1_t a_pFun); -API_EXPORT(void) mupDefineBulkFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun2_t a_pFun); -API_EXPORT(void) mupDefineBulkFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun3_t a_pFun); -API_EXPORT(void) mupDefineBulkFun4(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun4_t a_pFun); -API_EXPORT(void) mupDefineBulkFun5(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun5_t a_pFun); -API_EXPORT(void) mupDefineBulkFun6(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun6_t a_pFun); -API_EXPORT(void) mupDefineBulkFun7(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun7_t a_pFun); -API_EXPORT(void) mupDefineBulkFun8(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun8_t a_pFun); -API_EXPORT(void) mupDefineBulkFun9(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun9_t a_pFun); -API_EXPORT(void) mupDefineBulkFun10(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun10_t a_pFun); - -// string functions -API_EXPORT(void) mupDefineStrFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun1_t a_pFun); -API_EXPORT(void) mupDefineStrFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun2_t a_pFun); -API_EXPORT(void) mupDefineStrFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun3_t a_pFun); - -API_EXPORT(void) mupDefineMultFun( muParserHandle_t a_hParser, - const muChar_t* a_szName, - muMultFun_t a_pFun, - muBool_t a_bOptimize); - -API_EXPORT(void) mupDefineOprt( muParserHandle_t a_hParser, - const muChar_t* a_szName, - muFun2_t a_pFun, - muInt_t a_nPrec, - muInt_t a_nOprtAsct, - muBool_t a_bOptimize); - -API_EXPORT(void) mupDefineConst( muParserHandle_t a_hParser, - const muChar_t* a_szName, - muFloat_t a_fVal ); - -API_EXPORT(void) mupDefineStrConst( muParserHandle_t a_hParser, - const muChar_t* a_szName, - const muChar_t *a_sVal ); - -API_EXPORT(void) mupDefineVar( muParserHandle_t a_hParser, - const muChar_t* a_szName, - muFloat_t *a_fVar); - -API_EXPORT(void) mupDefineBulkVar( muParserHandle_t a_hParser, - const muChar_t* a_szName, - muFloat_t *a_fVar); - -API_EXPORT(void) mupDefinePostfixOprt( muParserHandle_t a_hParser, - const muChar_t* a_szName, - muFun1_t a_pOprt, - muBool_t a_bOptimize); - - -API_EXPORT(void) mupDefineInfixOprt( muParserHandle_t a_hParser, - const muChar_t* a_szName, - muFun1_t a_pOprt, - muBool_t a_bOptimize); - -// Define character sets for identifiers -API_EXPORT(void) mupDefineNameChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset); -API_EXPORT(void) mupDefineOprtChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset); -API_EXPORT(void) mupDefineInfixOprtChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset); - -// Remove all / single variables -API_EXPORT(void) mupRemoveVar(muParserHandle_t a_hParser, const muChar_t* a_szName); -API_EXPORT(void) mupClearVar(muParserHandle_t a_hParser); -API_EXPORT(void) mupClearConst(muParserHandle_t a_hParser); -API_EXPORT(void) mupClearOprt(muParserHandle_t a_hParser); -API_EXPORT(void) mupClearFun(muParserHandle_t a_hParser); - -// Querying variables / expression variables / constants -API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser); -API_EXPORT(int) mupGetVarNum(muParserHandle_t a_hParser); -API_EXPORT(int) mupGetConstNum(muParserHandle_t a_hParser); -API_EXPORT(void) mupGetExprVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t** a_pVar); -API_EXPORT(void) mupGetVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t** a_pVar); -API_EXPORT(void) mupGetConst(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t* a_pVar); -API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep); -API_EXPORT(void) mupSetDecSep(muParserHandle_t a_hParser, const muChar_t cArgSep); -API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t cArgSep); -API_EXPORT(void) mupResetLocale(muParserHandle_t a_hParser); - -// Add value recognition callbacks -API_EXPORT(void) mupAddValIdent(muParserHandle_t a_hParser, muIdentFun_t); - -// Error handling -API_EXPORT(muBool_t) mupError(muParserHandle_t a_hParser); -API_EXPORT(void) mupErrorReset(muParserHandle_t a_hParser); -API_EXPORT(void) mupSetErrorHandler(muParserHandle_t a_hParser, muErrorHandler_t a_pErrHandler); -API_EXPORT(const muChar_t*) mupGetErrorMsg(muParserHandle_t a_hParser); -API_EXPORT(muInt_t) mupGetErrorCode(muParserHandle_t a_hParser); -API_EXPORT(muInt_t) mupGetErrorPos(muParserHandle_t a_hParser); -API_EXPORT(const muChar_t*) mupGetErrorToken(muParserHandle_t a_hParser); -//API_EXPORT(const muChar_t*) mupGetErrorExpr(muParserHandle_t a_hParser); - -// This is used for .NET only. It creates a new variable allowing the dll to -// manage the variable rather than the .NET garbage collector. -API_EXPORT(muFloat_t*) mupCreateVar(); -API_EXPORT(void) mupReleaseVar(muFloat_t*); - -#ifdef __cplusplus -} -#endif - -#endif // include guard diff --git a/external/muparser/include/muParserDef.h b/external/muparser/include/muParserDef.h deleted file mode 100644 index f4427455..00000000 --- a/external/muparser/include/muParserDef.h +++ /dev/null @@ -1,368 +0,0 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2014 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -#ifndef MUP_DEF_H -#define MUP_DEF_H - -#include -#include -#include -#include - -#include "muParserFixes.h" - -/** \file - \brief This file contains standard definitions used by the parser. -*/ - -#define MUP_VERSION _T("2.2.5") -#define MUP_VERSION_DATE _T("20150427; GC") - -#define MUP_CHARS _T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") - -/** \brief If this macro is defined mathematical exceptions (div by zero) will be thrown as exceptions. */ -//#define MUP_MATH_EXCEPTIONS - -/** \brief Define the base datatype for values. - - This datatype must be a built in value type. You can not use custom classes. - It should be working with all types except "int"! -*/ -#define MUP_BASETYPE double - -/** \brief Activate this option in order to compile with OpenMP support. - - OpenMP is used only in the bulk mode it may increase the performance a bit. -*/ -//#define MUP_USE_OPENMP - -#if defined(_UNICODE) - /** \brief Definition of the basic parser string type. */ - #define MUP_STRING_TYPE std::wstring - - #if !defined(_T) - #define _T(x) L##x - #endif // not defined _T -#else - #ifndef _T - #define _T(x) x - #endif - - /** \brief Definition of the basic parser string type. */ - #define MUP_STRING_TYPE std::string -#endif - -#if defined(_DEBUG) - /** \brief Debug macro to force an abortion of the programm with a certain message. - */ - #define MUP_FAIL(MSG) \ - { \ - bool MSG=false; \ - assert(MSG); \ - } - - /** \brief An assertion that does not kill the program. - - This macro is neutralised in UNICODE builds. It's - too difficult to translate. - */ - #define MUP_ASSERT(COND) \ - if (!(COND)) \ - { \ - stringstream_type ss; \ - ss << _T("Assertion \"") _T(#COND) _T("\" failed: ") \ - << __FILE__ << _T(" line ") \ - << __LINE__ << _T("."); \ - throw ParserError( ss.str() ); \ - } -#else - #define MUP_FAIL(MSG) - #define MUP_ASSERT(COND) -#endif - - -namespace mu -{ -#if defined(_UNICODE) - - //------------------------------------------------------------------------------ - /** \brief Encapsulate wcout. */ - inline std::wostream& console() - { - return std::wcout; - } - - /** \brief Encapsulate cin. */ - inline std::wistream& console_in() - { - return std::wcin; - } - -#else - - /** \brief Encapsulate cout. - - Used for supporting UNICODE more easily. - */ - inline std::ostream& console() - { - return std::cout; - } - - /** \brief Encapsulate cin. - - Used for supporting UNICODE more easily. - */ - inline std::istream& console_in() - { - return std::cin; - } - -#endif - - //------------------------------------------------------------------------------ - /** \brief Bytecode values. - - \attention The order of the operator entries must match the order in ParserBase::c_DefaultOprt! - */ - enum ECmdCode - { - // The following are codes for built in binary operators - // apart from built in operators the user has the opportunity to - // add user defined operators. - cmLE = 0, ///< Operator item: less or equal - cmGE = 1, ///< Operator item: greater or equal - cmNEQ = 2, ///< Operator item: not equal - cmEQ = 3, ///< Operator item: equals - cmLT = 4, ///< Operator item: less than - cmGT = 5, ///< Operator item: greater than - cmADD = 6, ///< Operator item: add - cmSUB = 7, ///< Operator item: subtract - cmMUL = 8, ///< Operator item: multiply - cmDIV = 9, ///< Operator item: division - cmPOW = 10, ///< Operator item: y to the power of ... - cmLAND = 11, - cmLOR = 12, - cmASSIGN = 13, ///< Operator item: Assignment operator - cmBO = 14, ///< Operator item: opening bracket - cmBC = 15, ///< Operator item: closing bracket - cmIF = 16, ///< For use in the ternary if-then-else operator - cmELSE = 17, ///< For use in the ternary if-then-else operator - cmENDIF = 18, ///< For use in the ternary if-then-else operator - cmARG_SEP = 19, ///< function argument separator - cmVAR = 20, ///< variable item - cmVAL = 21, ///< value item - - // For optimization purposes - cmVARPOW2, - cmVARPOW3, - cmVARPOW4, - cmVARMUL, - cmPOW2, - - // operators and functions - cmFUNC, ///< Code for a generic function item - cmFUNC_STR, ///< Code for a function with a string parameter - cmFUNC_BULK, ///< Special callbacks for Bulk mode with an additional parameter for the bulk index - cmSTRING, ///< Code for a string token - cmOPRT_BIN, ///< user defined binary operator - cmOPRT_POSTFIX, ///< code for postfix operators - cmOPRT_INFIX, ///< code for infix operators - cmEND, ///< end of formula - cmUNKNOWN ///< uninitialized item - }; - - //------------------------------------------------------------------------------ - /** \brief Types internally used by the parser. - */ - enum ETypeCode - { - tpSTR = 0, ///< String type (Function arguments and constants only, no string variables) - tpDBL = 1, ///< Floating point variables - tpVOID = 2 ///< Undefined type. - }; - - //------------------------------------------------------------------------------ - enum EParserVersionInfo - { - pviBRIEF, - pviFULL - }; - - //------------------------------------------------------------------------------ - /** \brief Parser operator precedence values. */ - enum EOprtAssociativity - { - oaLEFT = 0, - oaRIGHT = 1, - oaNONE = 2 - }; - - //------------------------------------------------------------------------------ - /** \brief Parser operator precedence values. */ - enum EOprtPrecedence - { - // binary operators - prLOR = 1, - prLAND = 2, - prLOGIC = 3, ///< logic operators - prCMP = 4, ///< comparsion operators - prADD_SUB = 5, ///< addition - prMUL_DIV = 6, ///< multiplication/division - prPOW = 7, ///< power operator priority (highest) - - // infix operators - prINFIX = 6, ///< Signs have a higher priority than ADD_SUB, but lower than power operator - prPOSTFIX = 6 ///< Postfix operator priority (currently unused) - }; - - //------------------------------------------------------------------------------ - // basic types - - /** \brief The numeric datatype used by the parser. - - Normally this is a floating point type either single or double precision. - */ - typedef MUP_BASETYPE value_type; - - /** \brief The stringtype used by the parser. - - Depends on wether UNICODE is used or not. - */ - typedef MUP_STRING_TYPE string_type; - - /** \brief The character type used by the parser. - - Depends on wether UNICODE is used or not. - */ - typedef string_type::value_type char_type; - - /** \brief Typedef for easily using stringstream that respect the parser stringtype. */ - typedef std::basic_stringstream, - std::allocator > stringstream_type; - - // Data container types - - /** \brief Type used for storing variables. */ - typedef std::map varmap_type; - - /** \brief Type used for storing constants. */ - typedef std::map valmap_type; - - /** \brief Type for assigning a string name to an index in the internal string table. */ - typedef std::map strmap_type; - - // Parser callbacks - - /** \brief Callback type used for functions without arguments. */ - typedef value_type (*generic_fun_type)(); - - /** \brief Callback type used for functions without arguments. */ - typedef value_type (*fun_type0)(); - - /** \brief Callback type used for functions with a single arguments. */ - typedef value_type (*fun_type1)(value_type); - - /** \brief Callback type used for functions with two arguments. */ - typedef value_type (*fun_type2)(value_type, value_type); - - /** \brief Callback type used for functions with three arguments. */ - typedef value_type (*fun_type3)(value_type, value_type, value_type); - - /** \brief Callback type used for functions with four arguments. */ - typedef value_type (*fun_type4)(value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*fun_type5)(value_type, value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*fun_type6)(value_type, value_type, value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*fun_type7)(value_type, value_type, value_type, value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*fun_type8)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*fun_type9)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*fun_type10)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions without arguments. */ - typedef value_type (*bulkfun_type0)(int, int); - - /** \brief Callback type used for functions with a single arguments. */ - typedef value_type (*bulkfun_type1)(int, int, value_type); - - /** \brief Callback type used for functions with two arguments. */ - typedef value_type (*bulkfun_type2)(int, int, value_type, value_type); - - /** \brief Callback type used for functions with three arguments. */ - typedef value_type (*bulkfun_type3)(int, int, value_type, value_type, value_type); - - /** \brief Callback type used for functions with four arguments. */ - typedef value_type (*bulkfun_type4)(int, int, value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*bulkfun_type5)(int, int, value_type, value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*bulkfun_type6)(int, int, value_type, value_type, value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*bulkfun_type7)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*bulkfun_type8)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*bulkfun_type9)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*bulkfun_type10)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); - - /** \brief Callback type used for functions with a variable argument list. */ - typedef value_type (*multfun_type)(const value_type*, int); - - /** \brief Callback type used for functions taking a string as an argument. */ - typedef value_type (*strfun_type1)(const char_type*); - - /** \brief Callback type used for functions taking a string and a value as arguments. */ - typedef value_type (*strfun_type2)(const char_type*, value_type); - - /** \brief Callback type used for functions taking a string and two values as arguments. */ - typedef value_type (*strfun_type3)(const char_type*, value_type, value_type); - - /** \brief Callback used for functions that identify values in a string. */ - typedef int (*identfun_type)(const char_type *sExpr, int *nPos, value_type *fVal); - - /** \brief Callback used for variable creation factory functions. */ - typedef value_type* (*facfun_type)(const char_type*, void*); -} // end of namespace - -#endif - diff --git a/external/muparser/include/muParserError.h b/external/muparser/include/muParserError.h deleted file mode 100644 index fe817d87..00000000 --- a/external/muparser/include/muParserError.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2004-2011 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef MU_PARSER_ERROR_H -#define MU_PARSER_ERROR_H - -#include -#include -#include -#include -#include -#include - -#include "muParserDef.h" - -/** \file - \brief This file defines the error class used by the parser. -*/ - -namespace mu -{ - -/** \brief Error codes. */ -enum EErrorCodes -{ - // Formula syntax errors - ecUNEXPECTED_OPERATOR = 0, ///< Unexpected binary operator found - ecUNASSIGNABLE_TOKEN = 1, ///< Token cant be identified. - ecUNEXPECTED_EOF = 2, ///< Unexpected end of formula. (Example: "2+sin(") - ecUNEXPECTED_ARG_SEP = 3, ///< An unexpected comma has been found. (Example: "1,23") - ecUNEXPECTED_ARG = 4, ///< An unexpected argument has been found - ecUNEXPECTED_VAL = 5, ///< An unexpected value token has been found - ecUNEXPECTED_VAR = 6, ///< An unexpected variable token has been found - ecUNEXPECTED_PARENS = 7, ///< Unexpected Parenthesis, opening or closing - ecUNEXPECTED_STR = 8, ///< A string has been found at an inapropriate position - ecSTRING_EXPECTED = 9, ///< A string function has been called with a different type of argument - ecVAL_EXPECTED = 10, ///< A numerical function has been called with a non value type of argument - ecMISSING_PARENS = 11, ///< Missing parens. (Example: "3*sin(3") - ecUNEXPECTED_FUN = 12, ///< Unexpected function found. (Example: "sin(8)cos(9)") - ecUNTERMINATED_STRING = 13, ///< unterminated string constant. (Example: "3*valueof("hello)") - ecTOO_MANY_PARAMS = 14, ///< Too many function parameters - ecTOO_FEW_PARAMS = 15, ///< Too few function parameters. (Example: "ite(1<2,2)") - ecOPRT_TYPE_CONFLICT = 16, ///< binary operators may only be applied to value items of the same type - ecSTR_RESULT = 17, ///< result is a string - - // Invalid Parser input Parameters - ecINVALID_NAME = 18, ///< Invalid function, variable or constant name. - ecINVALID_BINOP_IDENT = 19, ///< Invalid binary operator identifier - ecINVALID_INFIX_IDENT = 20, ///< Invalid function, variable or constant name. - ecINVALID_POSTFIX_IDENT = 21, ///< Invalid function, variable or constant name. - - ecBUILTIN_OVERLOAD = 22, ///< Trying to overload builtin operator - ecINVALID_FUN_PTR = 23, ///< Invalid callback function pointer - ecINVALID_VAR_PTR = 24, ///< Invalid variable pointer - ecEMPTY_EXPRESSION = 25, ///< The Expression is empty - ecNAME_CONFLICT = 26, ///< Name conflict - ecOPT_PRI = 27, ///< Invalid operator priority - // - ecDOMAIN_ERROR = 28, ///< catch division by zero, sqrt(-1), log(0) (currently unused) - ecDIV_BY_ZERO = 29, ///< Division by zero (currently unused) - ecGENERIC = 30, ///< Generic error - ecLOCALE = 31, ///< Conflict with current locale - - ecUNEXPECTED_CONDITIONAL = 32, - ecMISSING_ELSE_CLAUSE = 33, - ecMISPLACED_COLON = 34, - - ecUNREASONABLE_NUMBER_OF_COMPUTATIONS = 35, - - // internal errors - ecINTERNAL_ERROR = 36, ///< Internal error of any kind. - - // The last two are special entries - ecCOUNT, ///< This is no error code, It just stores just the total number of error codes - ecUNDEFINED = -1 ///< Undefined message, placeholder to detect unassigned error messages -}; - -//--------------------------------------------------------------------------- -/** \brief A class that handles the error messages. -*/ -class ParserErrorMsg -{ -public: - typedef ParserErrorMsg self_type; - - ParserErrorMsg& operator=(const ParserErrorMsg &); - ParserErrorMsg(const ParserErrorMsg&); - ParserErrorMsg(); - - ~ParserErrorMsg(); - - static const ParserErrorMsg& Instance(); - string_type operator[](unsigned a_iIdx) const; - -private: - std::vector m_vErrMsg; ///< A vector with the predefined error messages - static const self_type m_Instance; ///< The instance pointer -}; - -//--------------------------------------------------------------------------- -/** \brief Error class of the parser. - \author Ingo Berg - - Part of the math parser package. -*/ -class ParserError -{ -private: - - /** \brief Replace all ocuurences of a substring with another string. */ - void ReplaceSubString( string_type &strSource, - const string_type &strFind, - const string_type &strReplaceWith); - void Reset(); - -public: - - ParserError(); - explicit ParserError(EErrorCodes a_iErrc); - explicit ParserError(const string_type &sMsg); - ParserError( EErrorCodes a_iErrc, - const string_type &sTok, - const string_type &sFormula = string_type(), - int a_iPos = -1); - ParserError( EErrorCodes a_iErrc, - int a_iPos, - const string_type &sTok); - ParserError( const char_type *a_szMsg, - int a_iPos = -1, - const string_type &sTok = string_type()); - ParserError(const ParserError &a_Obj); - ParserError& operator=(const ParserError &a_Obj); - ~ParserError(); - - void SetFormula(const string_type &a_strFormula); - const string_type& GetExpr() const; - const string_type& GetMsg() const; - int GetPos() const; - const string_type& GetToken() const; - EErrorCodes GetCode() const; - -private: - string_type m_strMsg; ///< The message string - string_type m_strFormula; ///< Formula string - string_type m_strTok; ///< Token related with the error - int m_iPos; ///< Formula position related to the error - EErrorCodes m_iErrc; ///< Error code - const ParserErrorMsg &m_ErrMsg; -}; - -} // namespace mu - -#endif - diff --git a/external/muparser/include/muParserFixes.h b/external/muparser/include/muParserFixes.h deleted file mode 100644 index 31d9c144..00000000 --- a/external/muparser/include/muParserFixes.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2013 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef MU_PARSER_FIXES_H -#define MU_PARSER_FIXES_H - -/** \file - \brief This file contains compatibility fixes for some platforms. -*/ - -// -// Compatibility fixes -// - -//--------------------------------------------------------------------------- -// -// Intel Compiler -// -//--------------------------------------------------------------------------- - -#ifdef __INTEL_COMPILER - -// remark #981: operands are evaluated in unspecified order -// disabled -> completely pointless if the functions do not have side effects -// -#pragma warning(disable:981) - -// remark #383: value copied to temporary, reference to temporary used -#pragma warning(disable:383) - -// remark #1572: floating-point equality and inequality comparisons are unreliable -// disabled -> everyone knows it, the parser passes this problem -// deliberately to the user -#pragma warning(disable:1572) - -#endif - -#endif // include guard - - diff --git a/external/muparser/include/muParserInt.h b/external/muparser/include/muParserInt.h deleted file mode 100644 index 8833b995..00000000 --- a/external/muparser/include/muParserInt.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2004-2013 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef MU_PARSER_INT_H -#define MU_PARSER_INT_H - -#include "muParserBase.h" -#include - - -/** \file - \brief Definition of a parser using integer value. -*/ - - -namespace mu -{ - -/** \brief Mathematical expressions parser. - - This version of the parser handles only integer numbers. It disables the built in operators thus it is - slower than muParser. Integer values are stored in the double value_type and converted if needed. -*/ -class ParserInt : public ParserBase -{ -private: - static int Round(value_type v) { return (int)(v + ((v>=0) ? 0.5 : -0.5) ); }; - - static value_type Abs(value_type); - static value_type Sign(value_type); - static value_type Ite(value_type, value_type, value_type); - // !! The unary Minus is a MUST, otherwise you cant use negative signs !! - static value_type UnaryMinus(value_type); - // Functions with variable number of arguments - static value_type Sum(const value_type* a_afArg, int a_iArgc); // sum - static value_type Min(const value_type* a_afArg, int a_iArgc); // minimum - static value_type Max(const value_type* a_afArg, int a_iArgc); // maximum - // binary operator callbacks - static value_type Add(value_type v1, value_type v2); - static value_type Sub(value_type v1, value_type v2); - static value_type Mul(value_type v1, value_type v2); - static value_type Div(value_type v1, value_type v2); - static value_type Mod(value_type v1, value_type v2); - static value_type Pow(value_type v1, value_type v2); - static value_type Shr(value_type v1, value_type v2); - static value_type Shl(value_type v1, value_type v2); - static value_type LogAnd(value_type v1, value_type v2); - static value_type LogOr(value_type v1, value_type v2); - static value_type And(value_type v1, value_type v2); - static value_type Or(value_type v1, value_type v2); - static value_type Xor(value_type v1, value_type v2); - static value_type Less(value_type v1, value_type v2); - static value_type Greater(value_type v1, value_type v2); - static value_type LessEq(value_type v1, value_type v2); - static value_type GreaterEq(value_type v1, value_type v2); - static value_type Equal(value_type v1, value_type v2); - static value_type NotEqual(value_type v1, value_type v2); - static value_type Not(value_type v1); - - static int IsHexVal(const char_type* a_szExpr, int *a_iPos, value_type *a_iVal); - static int IsBinVal(const char_type* a_szExpr, int *a_iPos, value_type *a_iVal); - static int IsVal (const char_type* a_szExpr, int *a_iPos, value_type *a_iVal); - - /** \brief A facet class used to change decimal and thousands separator. */ - template - class change_dec_sep : public std::numpunct - { - public: - - explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3) - :std::numpunct() - ,m_cDecPoint(cDecSep) - ,m_cThousandsSep(cThousandsSep) - ,m_nGroup(nGroup) - {} - - protected: - - virtual char_type do_decimal_point() const - { - return m_cDecPoint; - } - - virtual char_type do_thousands_sep() const - { - return m_cThousandsSep; - } - - virtual std::string do_grouping() const - { - // fix for issue 4: https://code.google.com/p/muparser/issues/detail?id=4 - // courtesy of Jens Bartsch - // original code: - // return std::string(1, (char)m_nGroup); - // new code: - return std::string(1, (char)(m_cThousandsSep > 0 ? m_nGroup : CHAR_MAX)); - } - - private: - - int m_nGroup; - char_type m_cDecPoint; - char_type m_cThousandsSep; - }; - -public: - ParserInt(); - - virtual void InitFun(); - virtual void InitOprt(); - virtual void InitConst(); - virtual void InitCharSets(); -}; - -} // namespace mu - -#endif - diff --git a/external/muparser/include/muParserStack.h b/external/muparser/include/muParserStack.h deleted file mode 100644 index 40a9908e..00000000 --- a/external/muparser/include/muParserStack.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2004-2011 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef MU_PARSER_STACK_H -#define MU_PARSER_STACK_H - -#include -#include -#include -#include - -#include "muParserError.h" -#include "muParserToken.h" - -/** \file - \brief This file defines the stack used by muparser. -*/ - -namespace mu -{ - - /** \brief Parser stack implementation. - - Stack implementation based on a std::stack. The behaviour of pop() had been - slightly changed in order to get an error code if the stack is empty. - The stack is used within the Parser both as a value stack and as an operator stack. - - \author (C) 2004-2011 Ingo Berg - */ - template - class ParserStack - { - private: - - /** \brief Type of the underlying stack implementation. */ - typedef std::stack > impl_type; - - impl_type m_Stack; ///< This is the actual stack. - - public: - - //--------------------------------------------------------------------------- - ParserStack() - :m_Stack() - {} - - //--------------------------------------------------------------------------- - virtual ~ParserStack() - {} - - //--------------------------------------------------------------------------- - /** \brief Pop a value from the stack. - - Unlike the standard implementation this function will return the value that - is going to be taken from the stack. - - \throw ParserException in case the stack is empty. - \sa pop(int &a_iErrc) - */ - TValueType pop() - { - if (empty()) - throw ParserError( _T("stack is empty.") ); - - TValueType el = top(); - m_Stack.pop(); - return el; - } - - /** \brief Push an object into the stack. - - \param a_Val object to push into the stack. - \throw nothrow - */ - void push(const TValueType& a_Val) - { - m_Stack.push(a_Val); - } - - /** \brief Return the number of stored elements. */ - unsigned size() const - { - return (unsigned)m_Stack.size(); - } - - /** \brief Returns true if stack is empty false otherwise. */ - bool empty() const - { - return m_Stack.empty(); - } - - /** \brief Return reference to the top object in the stack. - - The top object is the one pushed most recently. - */ - TValueType& top() - { - return m_Stack.top(); - } - }; -} // namespace MathUtils - -#endif diff --git a/external/muparser/include/muParserTemplateMagic.h b/external/muparser/include/muParserTemplateMagic.h deleted file mode 100644 index d212fda2..00000000 --- a/external/muparser/include/muParserTemplateMagic.h +++ /dev/null @@ -1,113 +0,0 @@ -#ifndef MU_PARSER_TEMPLATE_MAGIC_H -#define MU_PARSER_TEMPLATE_MAGIC_H - -#include -#include "muParserError.h" - - -namespace mu -{ - //----------------------------------------------------------------------------------------------- - // - // Compile time type detection - // - //----------------------------------------------------------------------------------------------- - - /** \brief A class singling out integer types at compile time using - template meta programming. - */ - template - struct TypeInfo - { - static bool IsInteger() { return false; } - }; - - template<> - struct TypeInfo - { - static bool IsInteger() { return true; } - }; - - template<> - struct TypeInfo - { - static bool IsInteger() { return true; } - }; - - template<> - struct TypeInfo - { - static bool IsInteger() { return true; } - }; - - template<> - struct TypeInfo - { - static bool IsInteger() { return true; } - }; - - template<> - struct TypeInfo - { - static bool IsInteger() { return true; } - }; - - template<> - struct TypeInfo - { - static bool IsInteger() { return true; } - }; - - template<> - struct TypeInfo - { - static bool IsInteger() { return true; } - }; - - template<> - struct TypeInfo - { - static bool IsInteger() { return true; } - }; - - - //----------------------------------------------------------------------------------------------- - // - // Standard math functions with dummy overload for integer types - // - //----------------------------------------------------------------------------------------------- - - /** \brief A template class for providing wrappers for essential math functions. - - This template is spezialized for several types in order to provide a unified interface - for parser internal math function calls regardless of the data type. - */ - template - struct MathImpl - { - static T Sin(T v) { return sin(v); } - static T Cos(T v) { return cos(v); } - static T Tan(T v) { return tan(v); } - static T ASin(T v) { return asin(v); } - static T ACos(T v) { return acos(v); } - static T ATan(T v) { return atan(v); } - static T ATan2(T v1, T v2) { return atan2(v1, v2); } - static T Sinh(T v) { return sinh(v); } - static T Cosh(T v) { return cosh(v); } - static T Tanh(T v) { return tanh(v); } - static T ASinh(T v) { return log(v + sqrt(v * v + 1)); } - static T ACosh(T v) { return log(v + sqrt(v * v - 1)); } - static T ATanh(T v) { return ((T)0.5 * log((1 + v) / (1 - v))); } - static T Log(T v) { return log(v); } - static T Log2(T v) { return log(v)/log((T)2); } // Logarithm base 2 - static T Log10(T v) { return log10(v); } // Logarithm base 10 - static T Exp(T v) { return exp(v); } - static T Abs(T v) { return (v>=0) ? v : -v; } - static T Sqrt(T v) { return sqrt(v); } - static T Rint(T v) { return floor(v + (T)0.5); } - static T Sign(T v) { return (T)((v<0) ? -1 : (v>0) ? 1 : 0); } - static T Pow(T v1, T v2) { return std::pow(v1, v2); } - }; -} - -#endif diff --git a/external/muparser/include/muParserTest.h b/external/muparser/include/muParserTest.h deleted file mode 100644 index 1e2b4d0b..00000000 --- a/external/muparser/include/muParserTest.h +++ /dev/null @@ -1,214 +0,0 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2013 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef MU_PARSER_TEST_H -#define MU_PARSER_TEST_H - -#include -#include -#include // for accumulate -#include "muParser.h" -#include "muParserInt.h" - -/** \file - \brief This file contains the parser test class. -*/ - -namespace mu -{ - /** \brief Namespace for test cases. */ - namespace Test - { - //------------------------------------------------------------------------------ - /** \brief Test cases for unit testing. - - (C) 2004-2011 Ingo Berg - */ - class ParserTester // final - { - private: - static int c_iCount; - - // Multiarg callbacks - static value_type f1of1(value_type v) { return v;}; - - static value_type f1of2(value_type v, value_type ) {return v;}; - static value_type f2of2(value_type , value_type v) {return v;}; - - static value_type f1of3(value_type v, value_type , value_type ) {return v;}; - static value_type f2of3(value_type , value_type v, value_type ) {return v;}; - static value_type f3of3(value_type , value_type , value_type v) {return v;}; - - static value_type f1of4(value_type v, value_type, value_type , value_type ) {return v;} - static value_type f2of4(value_type , value_type v, value_type , value_type ) {return v;} - static value_type f3of4(value_type , value_type, value_type v, value_type ) {return v;} - static value_type f4of4(value_type , value_type, value_type , value_type v) {return v;} - - static value_type f1of5(value_type v, value_type, value_type , value_type , value_type ) { return v; } - static value_type f2of5(value_type , value_type v, value_type , value_type , value_type ) { return v; } - static value_type f3of5(value_type , value_type, value_type v, value_type , value_type ) { return v; } - static value_type f4of5(value_type , value_type, value_type , value_type v, value_type ) { return v; } - static value_type f5of5(value_type , value_type, value_type , value_type , value_type v) { return v; } - - static value_type Min(value_type a_fVal1, value_type a_fVal2) { return (a_fVal1a_fVal2) ? a_fVal1 : a_fVal2; } - - static value_type plus2(value_type v1) { return v1+2; } - static value_type times3(value_type v1) { return v1*3; } - static value_type sqr(value_type v1) { return v1*v1; } - static value_type sign(value_type v) { return -v; } - static value_type add(value_type v1, value_type v2) { return v1+v2; } - static value_type land(value_type v1, value_type v2) { return (int)v1 & (int)v2; } - - - static value_type FirstArg(const value_type* a_afArg, int a_iArgc) - { - if (!a_iArgc) - throw mu::Parser::exception_type( _T("too few arguments for function FirstArg.") ); - - return a_afArg[0]; - } - - static value_type LastArg(const value_type* a_afArg, int a_iArgc) - { - if (!a_iArgc) - throw mu::Parser::exception_type( _T("too few arguments for function LastArg.") ); - - return a_afArg[a_iArgc-1]; - } - - static value_type Sum(const value_type* a_afArg, int a_iArgc) - { - if (!a_iArgc) - throw mu::Parser::exception_type( _T("too few arguments for function sum.") ); - - value_type fRes=0; - for (int i=0; i> val; - return (value_type)val; - } - - static value_type StrFun2(const char_type* v1, value_type v2) - { - int val(0); - stringstream_type(v1) >> val; - return (value_type)(val + v2); - } - - static value_type StrFun3(const char_type* v1, value_type v2, value_type v3) - { - int val(0); - stringstream_type(v1) >> val; - return val + v2 + v3; - } - - static value_type StrToFloat(const char_type* a_szMsg) - { - value_type val(0); - stringstream_type(a_szMsg) >> val; - return val; - } - - // postfix operator callback - static value_type Mega(value_type a_fVal) { return a_fVal * (value_type)1e6; } - static value_type Micro(value_type a_fVal) { return a_fVal * (value_type)1e-6; } - static value_type Milli(value_type a_fVal) { return a_fVal / (value_type)1e3; } - - // Custom value recognition - static int IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal); - - int TestNames(); - int TestSyntax(); - int TestMultiArg(); - int TestPostFix(); - int TestExpression(); - int TestInfixOprt(); - int TestBinOprt(); - int TestVarConst(); - int TestInterface(); - int TestException(); - int TestStrArg(); - int TestIfThenElse(); - int TestBulkMode(); - - void Abort() const; - - public: - typedef int (ParserTester::*testfun_type)(); - - ParserTester(); - void Run(); - - private: - std::vector m_vTestFun; - void AddTest(testfun_type a_pFun); - - // Test Double Parser - int EqnTest(const string_type& a_str, double a_fRes, bool a_fPass); - int EqnTestWithVarChange(const string_type& a_str, - double a_fRes1, - double a_fVar1, - double a_fRes2, - double a_fVar2); - int ThrowTest(const string_type& a_str, int a_iErrc, bool a_bFail = true); - - // Test Int Parser - int EqnTestInt(const string_type& a_str, double a_fRes, bool a_fPass); - - // Test Bulkmode - int EqnTestBulk(const string_type& a_str, double a_fRes[4], bool a_fPass); - }; - } // namespace Test -} // namespace mu - -#endif - - diff --git a/external/muparser/include/muParserToken.h b/external/muparser/include/muParserToken.h deleted file mode 100644 index 25a40163..00000000 --- a/external/muparser/include/muParserToken.h +++ /dev/null @@ -1,401 +0,0 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2004-2013 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef MU_PARSER_TOKEN_H -#define MU_PARSER_TOKEN_H - -#include -#include -#include -#include -#include - -#include "muParserError.h" -#include "muParserCallback.h" - -/** \file - \brief This file contains the parser token definition. -*/ - -namespace mu -{ - /** \brief Encapsulation of the data for a single formula token. - - Formula token implementation. Part of the Math Parser Package. - Formula tokens can be either one of the following: -
    -
  • value
  • -
  • variable
  • -
  • function with numerical arguments
  • -
  • functions with a string as argument
  • -
  • prefix operators
  • -
  • infix operators
  • -
  • binary operator
  • -
- - \author (C) 2004-2013 Ingo Berg - */ - template - class ParserToken - { - private: - - ECmdCode m_iCode; ///< Type of the token; The token type is a constant of type #ECmdCode. - ETypeCode m_iType; - void *m_pTok; ///< Stores Token pointer; not applicable for all tokens - int m_iIdx; ///< An otional index to an external buffer storing the token data - TString m_strTok; ///< Token string - TString m_strVal; ///< Value for string variables - value_type m_fVal; ///< the value - std::unique_ptr m_pCallback; - - public: - - //--------------------------------------------------------------------------- - /** \brief Constructor (default). - - Sets token to an neutral state of type cmUNKNOWN. - \throw nothrow - \sa ECmdCode - */ - ParserToken() - :m_iCode(cmUNKNOWN) - ,m_iType(tpVOID) - ,m_pTok(0) - ,m_iIdx(-1) - ,m_strTok() - ,m_strVal() - ,m_fVal(0) - ,m_pCallback() - {} - - //------------------------------------------------------------------------------ - /** \brief Create token from another one. - - Implemented by calling Assign(...) - \throw nothrow - \post m_iType==cmUNKNOWN - \sa #Assign - */ - ParserToken(const ParserToken &a_Tok) - { - Assign(a_Tok); - } - - //------------------------------------------------------------------------------ - /** \brief Assignement operator. - - Copy token state from another token and return this. - Implemented by calling Assign(...). - \throw nothrow - */ - ParserToken& operator=(const ParserToken &a_Tok) - { - Assign(a_Tok); - return *this; - } - - //------------------------------------------------------------------------------ - /** \brief Copy token information from argument. - - \throw nothrow - */ - void Assign(const ParserToken &a_Tok) - { - m_iCode = a_Tok.m_iCode; - m_pTok = a_Tok.m_pTok; - m_strTok = a_Tok.m_strTok; - m_iIdx = a_Tok.m_iIdx; - m_strVal = a_Tok.m_strVal; - m_iType = a_Tok.m_iType; - m_fVal = a_Tok.m_fVal; - // create new callback object if a_Tok has one - m_pCallback.reset(a_Tok.m_pCallback.get() ? a_Tok.m_pCallback->Clone() : 0); - } - - //------------------------------------------------------------------------------ - /** \brief Assign a token type. - - Token may not be of type value, variable or function. Those have seperate set functions. - - \pre [assert] a_iType!=cmVAR - \pre [assert] a_iType!=cmVAL - \pre [assert] a_iType!=cmFUNC - \post m_fVal = 0 - \post m_pTok = 0 - */ - ParserToken& Set(ECmdCode a_iType, const TString &a_strTok=TString()) - { - // The following types cant be set this way, they have special Set functions - assert(a_iType!=cmVAR); - assert(a_iType!=cmVAL); - assert(a_iType!=cmFUNC); - - m_iCode = a_iType; - m_iType = tpVOID; - m_pTok = 0; - m_strTok = a_strTok; - m_iIdx = -1; - - return *this; - } - - //------------------------------------------------------------------------------ - /** \brief Set Callback type. */ - ParserToken& Set(const ParserCallback &a_pCallback, const TString &a_sTok) - { - assert(a_pCallback.GetAddr()); - - m_iCode = a_pCallback.GetCode(); - m_iType = tpVOID; - m_strTok = a_sTok; - m_pCallback.reset(new ParserCallback(a_pCallback)); - - m_pTok = 0; - m_iIdx = -1; - - return *this; - } - - //------------------------------------------------------------------------------ - /** \brief Make this token a value token. - - Member variables not necessary for value tokens will be invalidated. - \throw nothrow - */ - ParserToken& SetVal(TBase a_fVal, const TString &a_strTok=TString()) - { - m_iCode = cmVAL; - m_iType = tpDBL; - m_fVal = a_fVal; - m_strTok = a_strTok; - m_iIdx = -1; - - m_pTok = 0; - m_pCallback.reset(0); - - return *this; - } - - //------------------------------------------------------------------------------ - /** \brief make this token a variable token. - - Member variables not necessary for variable tokens will be invalidated. - \throw nothrow - */ - ParserToken& SetVar(TBase *a_pVar, const TString &a_strTok) - { - m_iCode = cmVAR; - m_iType = tpDBL; - m_strTok = a_strTok; - m_iIdx = -1; - m_pTok = (void*)a_pVar; - m_pCallback.reset(0); - return *this; - } - - //------------------------------------------------------------------------------ - /** \brief Make this token a variable token. - - Member variables not necessary for variable tokens will be invalidated. - \throw nothrow - */ - ParserToken& SetString(const TString &a_strTok, std::size_t a_iSize) - { - m_iCode = cmSTRING; - m_iType = tpSTR; - m_strTok = a_strTok; - m_iIdx = static_cast(a_iSize); - - m_pTok = 0; - m_pCallback.reset(0); - return *this; - } - - //------------------------------------------------------------------------------ - /** \brief Set an index associated with the token related data. - - In cmSTRFUNC - This is the index to a string table in the main parser. - \param a_iIdx The index the string function result will take in the bytecode parser. - \throw exception_type if #a_iIdx<0 or #m_iType!=cmSTRING - */ - void SetIdx(int a_iIdx) - { - if (m_iCode!=cmSTRING || a_iIdx<0) - throw ParserError(ecINTERNAL_ERROR); - - m_iIdx = a_iIdx; - } - - //------------------------------------------------------------------------------ - /** \brief Return Index associated with the token related data. - - In cmSTRFUNC - This is the index to a string table in the main parser. - - \throw exception_type if #m_iIdx<0 or #m_iType!=cmSTRING - \return The index the result will take in the Bytecode calculatin array (#m_iIdx). - */ - int GetIdx() const - { - if (m_iIdx<0 || m_iCode!=cmSTRING ) - throw ParserError(ecINTERNAL_ERROR); - - return m_iIdx; - } - - //------------------------------------------------------------------------------ - /** \brief Return the token type. - - \return #m_iType - \throw nothrow - */ - ECmdCode GetCode() const - { - if (m_pCallback.get()) - { - return m_pCallback->GetCode(); - } - else - { - return m_iCode; - } - } - - //------------------------------------------------------------------------------ - ETypeCode GetType() const - { - if (m_pCallback.get()) - { - return m_pCallback->GetType(); - } - else - { - return m_iType; - } - } - - //------------------------------------------------------------------------------ - int GetPri() const - { - if ( !m_pCallback.get()) - throw ParserError(ecINTERNAL_ERROR); - - if ( m_pCallback->GetCode()!=cmOPRT_BIN && m_pCallback->GetCode()!=cmOPRT_INFIX) - throw ParserError(ecINTERNAL_ERROR); - - return m_pCallback->GetPri(); - } - - //------------------------------------------------------------------------------ - EOprtAssociativity GetAssociativity() const - { - if (m_pCallback.get()==NULL || m_pCallback->GetCode()!=cmOPRT_BIN) - throw ParserError(ecINTERNAL_ERROR); - - return m_pCallback->GetAssociativity(); - } - - //------------------------------------------------------------------------------ - /** \brief Return the address of the callback function assoziated with - function and operator tokens. - - \return The pointer stored in #m_pTok. - \throw exception_type if token type is non of: -
    -
  • cmFUNC
  • -
  • cmSTRFUNC
  • -
  • cmPOSTOP
  • -
  • cmINFIXOP
  • -
  • cmOPRT_BIN
  • -
- \sa ECmdCode - */ - generic_fun_type GetFuncAddr() const - { - return (m_pCallback.get()) ? (generic_fun_type)m_pCallback->GetAddr() : 0; - } - - //------------------------------------------------------------------------------ - /** \biref Get value of the token. - - Only applicable to variable and value tokens. - \throw exception_type if token is no value/variable token. - */ - TBase GetVal() const - { - switch (m_iCode) - { - case cmVAL: return m_fVal; - case cmVAR: return *((TBase*)m_pTok); - default: throw ParserError(ecVAL_EXPECTED); - } - } - - //------------------------------------------------------------------------------ - /** \brief Get address of a variable token. - - Valid only if m_iType==CmdVar. - \throw exception_type if token is no variable token. - */ - TBase* GetVar() const - { - if (m_iCode!=cmVAR) - throw ParserError(ecINTERNAL_ERROR); - - return (TBase*)m_pTok; - } - - //------------------------------------------------------------------------------ - /** \brief Return the number of function arguments. - - Valid only if m_iType==CmdFUNC. - */ - int GetArgCount() const - { - assert(m_pCallback.get()); - - if (!m_pCallback->GetAddr()) - throw ParserError(ecINTERNAL_ERROR); - - return m_pCallback->GetArgc(); - } - - //------------------------------------------------------------------------------ - /** \brief Return the token identifier. - - If #m_iType is cmSTRING the token identifier is the value of the string argument - for a string function. - \return #m_strTok - \throw nothrow - \sa m_strTok - */ - const TString& GetAsString() const - { - return m_strTok; - } - }; -} // namespace mu - -#endif diff --git a/external/muparser/include/muParserTokenReader.h b/external/muparser/include/muParserTokenReader.h deleted file mode 100644 index 52b3c1ad..00000000 --- a/external/muparser/include/muParserTokenReader.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2004-2013 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef MU_PARSER_TOKEN_READER_H -#define MU_PARSER_TOKEN_READER_H - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "muParserDef.h" -#include "muParserToken.h" - -/** \file - \brief This file contains the parser token reader definition. -*/ - - -namespace mu -{ - // Forward declaration - class ParserBase; - - /** \brief Token reader for the ParserBase class. - - */ - class ParserTokenReader - { - private: - - typedef ParserToken token_type; - - public: - - ParserTokenReader(ParserBase *a_pParent); - ParserTokenReader* Clone(ParserBase *a_pParent) const; - - void AddValIdent(identfun_type a_pCallback); - void SetVarCreator(facfun_type a_pFactory, void *pUserData); - void SetFormula(const string_type &a_strFormula); - void SetArgSep(char_type cArgSep); - - int GetPos() const; - const string_type& GetExpr() const; - varmap_type& GetUsedVar(); - char_type GetArgSep() const; - - void IgnoreUndefVar(bool bIgnore); - void ReInit(); - token_type ReadNextToken(); - - private: - - /** \brief Syntax codes. - - The syntax codes control the syntax check done during the first time parsing of - the expression string. They are flags that indicate which tokens are allowed next - if certain tokens are identified. - */ - enum ESynCodes - { - noBO = 1 << 0, ///< to avoid i.e. "cos(7)(" - noBC = 1 << 1, ///< to avoid i.e. "sin)" or "()" - noVAL = 1 << 2, ///< to avoid i.e. "tan 2" or "sin(8)3.14" - noVAR = 1 << 3, ///< to avoid i.e. "sin a" or "sin(8)a" - noARG_SEP = 1 << 4, ///< to avoid i.e. ",," or "+," ... - noFUN = 1 << 5, ///< to avoid i.e. "sqrt cos" or "(1)sin" - noOPT = 1 << 6, ///< to avoid i.e. "(+)" - noPOSTOP = 1 << 7, ///< to avoid i.e. "(5!!)" "sin!" - noINFIXOP = 1 << 8, ///< to avoid i.e. "++4" "!!4" - noEND = 1 << 9, ///< to avoid unexpected end of formula - noSTR = 1 << 10, ///< to block numeric arguments on string functions - noASSIGN = 1 << 11, ///< to block assignement to constant i.e. "4=7" - noIF = 1 << 12, - noELSE = 1 << 13, - sfSTART_OF_LINE = noOPT | noBC | noPOSTOP | noASSIGN | noIF | noELSE | noARG_SEP, - noANY = ~0 ///< All of he above flags set - }; - - ParserTokenReader(const ParserTokenReader &a_Reader); - ParserTokenReader& operator=(const ParserTokenReader &a_Reader); - void Assign(const ParserTokenReader &a_Reader); - - void SetParent(ParserBase *a_pParent); - int ExtractToken(const char_type *a_szCharSet, - string_type &a_strTok, - int a_iPos) const; - int ExtractOperatorToken(string_type &a_sTok, int a_iPos) const; - - bool IsBuiltIn(token_type &a_Tok); - bool IsArgSep(token_type &a_Tok); - bool IsEOF(token_type &a_Tok); - bool IsInfixOpTok(token_type &a_Tok); - bool IsFunTok(token_type &a_Tok); - bool IsPostOpTok(token_type &a_Tok); - bool IsOprt(token_type &a_Tok); - bool IsValTok(token_type &a_Tok); - bool IsVarTok(token_type &a_Tok); - bool IsStrVarTok(token_type &a_Tok); - bool IsUndefVarTok(token_type &a_Tok); - bool IsString(token_type &a_Tok); - void Error(EErrorCodes a_iErrc, - int a_iPos = -1, - const string_type &a_sTok = string_type() ) const; - - token_type& SaveBeforeReturn(const token_type &tok); - - ParserBase *m_pParser; - string_type m_strFormula; - int m_iPos; - int m_iSynFlags; - bool m_bIgnoreUndefVar; - - const funmap_type *m_pFunDef; - const funmap_type *m_pPostOprtDef; - const funmap_type *m_pInfixOprtDef; - const funmap_type *m_pOprtDef; - const valmap_type *m_pConstDef; - const strmap_type *m_pStrVarDef; - varmap_type *m_pVarDef; ///< The only non const pointer to parser internals - facfun_type m_pFactory; - void *m_pFactoryData; - std::list m_vIdentFun; ///< Value token identification function - varmap_type m_UsedVar; - value_type m_fZero; ///< Dummy value of zero, referenced by undefined variables - int m_iBrackets; - token_type m_lastTok; - char_type m_cArgSep; ///< The character used for separating function arguments - }; -} // namespace mu - -#endif - - diff --git a/external/muparser/src/muParser.cpp b/external/muparser/src/muParser.cpp deleted file mode 100644 index 2f9321ee..00000000 --- a/external/muparser/src/muParser.cpp +++ /dev/null @@ -1,444 +0,0 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - - Copyright (C) 2013 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -#include "../include/muParser.h" -#include "../include/muParserTemplateMagic.h" -#include "../../../basecode/global.h" - -//--- Standard includes ------------------------------------------------------------------------ -#include -#include -#include -#include - -/** \brief Pi (what else?). */ -#define PARSER_CONST_PI 3.141592653589793238462643 - -/** \brief The Eulerian number. */ -#define PARSER_CONST_E 2.718281828459045235360287 - -using namespace std; - -/** \file - \brief Implementation of the standard floating point parser. -*/ - - - -/** \brief Namespace for mathematical applications. */ -namespace mu -{ - - // Initialize the RNG with random time. - moose::RNG rng; - - //--------------------------------------------------------------------------- - // Trigonometric function - value_type Parser::Sin(value_type v) { return MathImpl::Sin(v); } - value_type Parser::Cos(value_type v) { return MathImpl::Cos(v); } - value_type Parser::Tan(value_type v) { return MathImpl::Tan(v); } - value_type Parser::ASin(value_type v) { return MathImpl::ASin(v); } - value_type Parser::ACos(value_type v) { return MathImpl::ACos(v); } - value_type Parser::ATan(value_type v) { return MathImpl::ATan(v); } - value_type Parser::ATan2(value_type v1, value_type v2) { return MathImpl::ATan2(v1, v2); } - value_type Parser::Sinh(value_type v) { return MathImpl::Sinh(v); } - value_type Parser::Cosh(value_type v) { return MathImpl::Cosh(v); } - value_type Parser::Tanh(value_type v) { return MathImpl::Tanh(v); } - value_type Parser::ASinh(value_type v) { return MathImpl::ASinh(v); } - value_type Parser::ACosh(value_type v) { return MathImpl::ACosh(v); } - value_type Parser::ATanh(value_type v) { return MathImpl::ATanh(v); } - - //--------------------------------------------------------------------------- - // Logarithm functions - - // Logarithm base 2 - value_type Parser::Log2(value_type v) - { - #ifdef MUP_MATH_EXCEPTIONS - if (v<=0) - throw ParserError(ecDOMAIN_ERROR, _T("Log2")); - #endif - - return MathImpl::Log2(v); - } - - // Logarithm base 10 - value_type Parser::Log10(value_type v) - { - #ifdef MUP_MATH_EXCEPTIONS - if (v<=0) - throw ParserError(ecDOMAIN_ERROR, _T("Log10")); - #endif - - return MathImpl::Log10(v); - } - -// Logarithm base e (natural logarithm) - value_type Parser::Ln(value_type v) - { - #ifdef MUP_MATH_EXCEPTIONS - if (v<=0) - throw ParserError(ecDOMAIN_ERROR, _T("Ln")); - #endif - - return MathImpl::Log(v); - } - - //--------------------------------------------------------------------------- - // misc - value_type Parser::Exp(value_type v) { return MathImpl::Exp(v); } - value_type Parser::Abs(value_type v) { return MathImpl::Abs(v); } - value_type Parser::Fmod(value_type v1, value_type v2) { return fmod(v1, v2); } - value_type Parser::Quot(value_type v1, value_type v2) { return (int)(v1 / v2); } - - value_type Parser::Rand( value_type seed = -1 ) - { - static bool isSeedSet_ = false; - - if( ! isSeedSet_ ) - { - mu::rng.setSeed( seed ); - isSeedSet_ = true; - } - return rng.uniform( ); /* Between 0 and 1 */ - } - - // If no seed is given, - value_type Parser::Rnd( ) - { - static bool isSeedSet_ = false; - // check if global seed is set - size_t seed = moose::getGlobalSeed(); - if( ! isSeedSet_ ) - { - mu::rng.setSeed( seed ); - isSeedSet_ = true; - } - return rng.uniform( ); /* Between 0 and 1 */ - } - - value_type Parser::Rand2(value_type v1, value_type v2, value_type seed = -1 ) { - static bool isSeedSet = false; - if( ! isSeedSet ) { - mu::rng.setSeed( seed ); - isSeedSet = true; - } - return mu::rng.uniform( v1, v2 ); /* Between a and b */ - } - - value_type Parser::Sqrt(value_type v) - { - #ifdef MUP_MATH_EXCEPTIONS - if (v<0) - throw ParserError(ecDOMAIN_ERROR, _T("sqrt")); - #endif - - return MathImpl::Sqrt(v); - } - value_type Parser::Rint(value_type v) { return MathImpl::Rint(v); } - value_type Parser::Sign(value_type v) { return MathImpl::Sign(v); } - - //--------------------------------------------------------------------------- - /** \brief Callback for the unary minus operator. - \param v The value to negate - \return -v - */ - value_type Parser::UnaryMinus(value_type v) - { - return -v; - } - - //--------------------------------------------------------------------------- - /** \brief Callback for the unary minus operator. - \param v The value to negate - \return -v - */ - value_type Parser::UnaryPlus(value_type v) - { - return v; - } - - //--------------------------------------------------------------------------- - /** \brief Callback for adding multiple values. - \param [in] a_afArg Vector with the function arguments - \param [in] a_iArgc The size of a_afArg - */ - value_type Parser::Sum(const value_type *a_afArg, int a_iArgc) - { - if (!a_iArgc) - throw exception_type(_T("too few arguments for function sum.")); - - value_type fRes=0; - for (int i=0; i> fVal; - stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading - - if (iEnd==(stringstream_type::pos_type)-1) - return 0; - - *a_iPos += (int)iEnd; - *a_fVal = fVal; - return 1; - } - - - //--------------------------------------------------------------------------- - /** \brief Constructor. - - Call ParserBase class constructor and trigger Function, Operator and Constant initialization. - */ - Parser::Parser() - :ParserBase() - { - AddValIdent(IsVal); - - InitCharSets(); - InitFun(); - InitConst(); - InitOprt(); - } - - //--------------------------------------------------------------------------- - /** \brief Define the character sets. - \sa DefineNameChars, DefineOprtChars, DefineInfixOprtChars - - This function is used for initializing the default character sets that define - the characters to be useable in function and variable names and operators. - */ - void Parser::InitCharSets() - { - DefineNameChars( _T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") ); - DefineOprtChars( _T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-*^/?<>=#!$%&|~'_{}") ); - DefineInfixOprtChars( _T("/+-*^?<>=#!$%&|~'_") ); - } - - //--------------------------------------------------------------------------- - /** \brief Initialize the default functions. */ - void Parser::InitFun() - { - if (mu::TypeInfo::IsInteger()) - { - // When setting MUP_BASETYPE to an integer type - // Place functions for dealing with integer values here - // ... - // ... - // ... - } - else - { - // trigonometric functions - DefineFun(_T("sin"), Sin); - DefineFun(_T("cos"), Cos); - DefineFun(_T("tan"), Tan); - // arcus functions - DefineFun(_T("asin"), ASin); - DefineFun(_T("acos"), ACos); - DefineFun(_T("atan"), ATan); - DefineFun(_T("atan2"), ATan2); - // hyperbolic functions - DefineFun(_T("sinh"), Sinh); - DefineFun(_T("cosh"), Cosh); - DefineFun(_T("tanh"), Tanh); - // arcus hyperbolic functions - DefineFun(_T("asinh"), ASinh); - DefineFun(_T("acosh"), ACosh); - DefineFun(_T("atanh"), ATanh); - // Logarithm functions - DefineFun(_T("log2"), Log2); - DefineFun(_T("log10"), Log10); - DefineFun(_T("log"), Ln); - DefineFun(_T("ln"), Ln); - // misc - DefineFun(_T("exp"), Exp); - DefineFun(_T("sqrt"), Sqrt); - DefineFun(_T("sign"), Sign); - DefineFun(_T("rint"), Rint); - DefineFun(_T("abs"), Abs); - DefineFun(_T("fmod"), Fmod); - DefineFun(_T("rnd"), Rnd); - DefineFun(_T("rand"), Rand); - DefineFun(_T("rand2"), Rand2); - // Functions with variable number of arguments - DefineFun(_T("sum"), Sum); - DefineFun(_T("avg"), Avg); - DefineFun(_T("min"), Min); - DefineFun(_T("max"), Max); - DefineFun(_T("quot"), Quot); - } - } - - //--------------------------------------------------------------------------- - /** \brief Initialize constants. - - By default the parser recognizes two constants. Pi ("pi") and the Eulerian - number ("_e"). - */ - void Parser::InitConst() - { - DefineConst(_T("_pi"), (value_type)PARSER_CONST_PI); - DefineConst(_T("_e"), (value_type)PARSER_CONST_E); - } - - //--------------------------------------------------------------------------- - /** \brief Initialize operators. - - By default only the unary minus operator is added. - */ - void Parser::InitOprt() - { - DefineInfixOprt(_T("-"), UnaryMinus); - DefineInfixOprt(_T("+"), UnaryPlus); - } - - //--------------------------------------------------------------------------- - void Parser::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/) - { - // this is just sample code to illustrate modifying variable names on the fly. - // I'm not sure anyone really needs such a feature... - /* - - - string sVar(pExpr->begin()+nStart, pExpr->begin()+nEnd); - string sRepl = std::string("_") + sVar + "_"; - - int nOrigVarEnd = nEnd; - cout << "variable detected!\n"; - cout << " Expr: " << *pExpr << "\n"; - cout << " Start: " << nStart << "\n"; - cout << " End: " << nEnd << "\n"; - cout << " Var: \"" << sVar << "\"\n"; - cout << " Repl: \"" << sRepl << "\"\n"; - nEnd = nStart + sRepl.length(); - cout << " End: " << nEnd << "\n"; - pExpr->replace(pExpr->begin()+nStart, pExpr->begin()+nOrigVarEnd, sRepl); - cout << " New expr: " << *pExpr << "\n"; - */ - } - - //--------------------------------------------------------------------------- - /** \brief Numerically differentiate with regard to a variable. - \param [in] a_Var Pointer to the differentiation variable. - \param [in] a_fPos Position at which the differentiation should take place. - \param [in] a_fEpsilon Epsilon used for the numerical differentiation. - - Numerical differentiation uses a 5 point operator yielding a 4th order - formula. The default value for epsilon is 0.00074 which is - numeric_limits::epsilon() ^ (1/5) as suggested in the muparser - forum: - - http://sourceforge.net/forum/forum.php?thread_id=1994611&forum_id=462843 - */ - value_type Parser::Diff(value_type *a_Var, - value_type a_fPos, - value_type a_fEpsilon) const - { - value_type fRes(0), - fBuf(*a_Var), - f[4] = {0,0,0,0}, - fEpsilon(a_fEpsilon); - - // Backwards compatible calculation of epsilon inc case the user doesn't provide - // his own epsilon - if (fEpsilon==0) - fEpsilon = (a_fPos==0) ? (value_type)1e-10 : (value_type)1e-7 * a_fPos; - - *a_Var = a_fPos+2 * fEpsilon; f[0] = Eval(); - *a_Var = a_fPos+1 * fEpsilon; f[1] = Eval(); - *a_Var = a_fPos-1 * fEpsilon; f[2] = Eval(); - *a_Var = a_fPos-2 * fEpsilon; f[3] = Eval(); - *a_Var = fBuf; // restore variable - - fRes = (-f[0] + 8*f[1] - 8*f[2] + f[3]) / (12*fEpsilon); - return fRes; - } -} // namespace mu diff --git a/external/muparser/src/muParserBase.cpp b/external/muparser/src/muParserBase.cpp deleted file mode 100644 index 8b051572..00000000 --- a/external/muparser/src/muParserBase.cpp +++ /dev/null @@ -1,1779 +0,0 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2011 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "muParserBase.h" -#include "muParserTemplateMagic.h" - -//--- Standard includes ------------------------------------------------------------------------ -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef MUP_USE_OPENMP - #include -#endif - -using namespace std; - -/** \file - \brief This file contains the basic implementation of the muparser engine. -*/ - -namespace mu -{ - std::locale ParserBase::s_locale = std::locale(std::locale::classic(), new change_dec_sep('.')); - - bool ParserBase::g_DbgDumpCmdCode = false; - bool ParserBase::g_DbgDumpStack = false; - - //------------------------------------------------------------------------------ - /** \brief Identifiers for built in binary operators. - - When defining custom binary operators with #AddOprt(...) make sure not to choose - names conflicting with these definitions. - */ - const char_type* ParserBase::c_DefaultOprt[] = - { - _T("<="), _T(">="), _T("!="), - _T("=="), _T("<"), _T(">"), - _T("+"), _T("-"), _T("*"), - _T("/"), _T("^"), _T("&&"), - _T("||"), _T("="), _T("("), - _T(")"), _T("?"), _T(":"), 0 - }; - - //------------------------------------------------------------------------------ - /** \brief Constructor. - \param a_szFormula the formula to interpret. - \throw ParserException if a_szFormula is null. - */ - ParserBase::ParserBase() - :m_pParseFormula(&ParserBase::ParseString) - ,m_vRPN() - ,m_vStringBuf() - ,m_pTokenReader() - ,m_FunDef() - ,m_PostOprtDef() - ,m_InfixOprtDef() - ,m_OprtDef() - ,m_ConstDef() - ,m_StrVarDef() - ,m_VarDef() - ,m_bBuiltInOp(true) - ,m_sNameChars() - ,m_sOprtChars() - ,m_sInfixOprtChars() - ,m_nIfElseCounter(0) - ,m_vStackBuffer() - ,m_nFinalResultIdx(0) - { - InitTokenReader(); - } - - //--------------------------------------------------------------------------- - /** \brief Copy constructor. - - The parser can be safely copy constructed but the bytecode is reset during - copy construction. - */ - ParserBase::ParserBase(const ParserBase &a_Parser) - :m_pParseFormula(&ParserBase::ParseString) - ,m_vRPN() - ,m_vStringBuf() - ,m_pTokenReader() - ,m_FunDef() - ,m_PostOprtDef() - ,m_InfixOprtDef() - ,m_OprtDef() - ,m_ConstDef() - ,m_StrVarDef() - ,m_VarDef() - ,m_bBuiltInOp(true) - ,m_sNameChars() - ,m_sOprtChars() - ,m_sInfixOprtChars() - ,m_nIfElseCounter(0) - { - m_pTokenReader.reset(new token_reader_type(this)); - Assign(a_Parser); - } - - //--------------------------------------------------------------------------- - ParserBase::~ParserBase() - {} - - //--------------------------------------------------------------------------- - /** \brief Assignment operator. - - Implemented by calling Assign(a_Parser). Self assignment is suppressed. - \param a_Parser Object to copy to this. - \return *this - \throw nothrow - */ - ParserBase& ParserBase::operator=(const ParserBase &a_Parser) - { - Assign(a_Parser); - return *this; - } - - //--------------------------------------------------------------------------- - /** \brief Copy state of a parser object to this. - - Clears Variables and Functions of this parser. - Copies the states of all internal variables. - Resets parse function to string parse mode. - - \param a_Parser the source object. - */ - void ParserBase::Assign(const ParserBase &a_Parser) - { - if (&a_Parser==this) - return; - - // Don't copy bytecode instead cause the parser to create new bytecode - // by resetting the parse function. - ReInit(); - - m_ConstDef = a_Parser.m_ConstDef; // Copy user define constants - m_VarDef = a_Parser.m_VarDef; // Copy user defined variables - m_bBuiltInOp = a_Parser.m_bBuiltInOp; - m_vStringBuf = a_Parser.m_vStringBuf; - m_vStackBuffer = a_Parser.m_vStackBuffer; - m_nFinalResultIdx = a_Parser.m_nFinalResultIdx; - m_StrVarDef = a_Parser.m_StrVarDef; - m_vStringVarBuf = a_Parser.m_vStringVarBuf; - m_nIfElseCounter = a_Parser.m_nIfElseCounter; - m_pTokenReader.reset(a_Parser.m_pTokenReader->Clone(this)); - - // Copy function and operator callbacks - m_FunDef = a_Parser.m_FunDef; // Copy function definitions - m_PostOprtDef = a_Parser.m_PostOprtDef; // post value unary operators - m_InfixOprtDef = a_Parser.m_InfixOprtDef; // unary operators for infix notation - m_OprtDef = a_Parser.m_OprtDef; // binary operators - - m_sNameChars = a_Parser.m_sNameChars; - m_sOprtChars = a_Parser.m_sOprtChars; - m_sInfixOprtChars = a_Parser.m_sInfixOprtChars; - } - - //--------------------------------------------------------------------------- - /** \brief Set the decimal separator. - \param cDecSep Decimal separator as a character value. - \sa SetThousandsSep - - By default muparser uses the "C" locale. The decimal separator of this - locale is overwritten by the one provided here. - */ - void ParserBase::SetDecSep(char_type cDecSep) - { - char_type cThousandsSep = std::use_facet< change_dec_sep >(s_locale).thousands_sep(); - s_locale = std::locale(std::locale("C"), new change_dec_sep(cDecSep, cThousandsSep)); - } - - //--------------------------------------------------------------------------- - /** \brief Sets the thousands operator. - \param cThousandsSep The thousands separator as a character - \sa SetDecSep - - By default muparser uses the "C" locale. The thousands separator of this - locale is overwritten by the one provided here. - */ - void ParserBase::SetThousandsSep(char_type cThousandsSep) - { - char_type cDecSep = std::use_facet< change_dec_sep >(s_locale).decimal_point(); - s_locale = std::locale(std::locale("C"), new change_dec_sep(cDecSep, cThousandsSep)); - } - - //--------------------------------------------------------------------------- - /** \brief Resets the locale. - - The default locale used "." as decimal separator, no thousands separator and - "," as function argument separator. - */ - void ParserBase::ResetLocale() - { - s_locale = std::locale(std::locale("C"), new change_dec_sep('.')); - SetArgSep(','); - } - - //--------------------------------------------------------------------------- - /** \brief Initialize the token reader. - - Create new token reader object and submit pointers to function, operator, - constant and variable definitions. - - \post m_pTokenReader.get()!=0 - \throw nothrow - */ - void ParserBase::InitTokenReader() - { - m_pTokenReader.reset(new token_reader_type(this)); - } - - //--------------------------------------------------------------------------- - /** \brief Reset parser to string parsing mode and clear internal buffers. - - Clear bytecode, reset the token reader. - \throw nothrow - */ - void ParserBase::ReInit() const - { - m_pParseFormula = &ParserBase::ParseString; - m_vStringBuf.clear(); - m_vRPN.clear(); - m_pTokenReader->ReInit(); - m_nIfElseCounter = 0; - } - - //--------------------------------------------------------------------------- - void ParserBase::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/) - {} - - //--------------------------------------------------------------------------- - /** \brief Returns the version of muparser. - \param eInfo A flag indicating whether the full version info should be - returned or not. - - Format is as follows: "MAJOR.MINOR (COMPILER_FLAGS)" The COMPILER_FLAGS - are returned only if eInfo==pviFULL. - */ - string_type ParserBase::GetVersion(EParserVersionInfo eInfo) const - { - stringstream_type ss; - - ss << MUP_VERSION; - - if (eInfo==pviFULL) - { - ss << _T(" (") << MUP_VERSION_DATE; - ss << std::dec << _T("; ") << sizeof(void*)*8 << _T("BIT"); - -#ifdef _DEBUG - ss << _T("; DEBUG"); -#else - ss << _T("; RELEASE"); -#endif - -#ifdef _UNICODE - ss << _T("; UNICODE"); -#else - #ifdef _MBCS - ss << _T("; MBCS"); - #else - ss << _T("; ASCII"); - #endif -#endif - -#ifdef MUP_USE_OPENMP - ss << _T("; OPENMP"); -//#else -// ss << _T("; NO_OPENMP"); -#endif - -#if defined(MUP_MATH_EXCEPTIONS) - ss << _T("; MATHEXC"); -//#else -// ss << _T("; NO_MATHEXC"); -#endif - - ss << _T(")"); - } - - return ss.str(); - } - - //--------------------------------------------------------------------------- - /** \brief Add a value parsing function. - - When parsing an expression muParser tries to detect values in the expression - string using different valident callbacks. Thus it's possible to parse - for hex values, binary values and floating point values. - */ - void ParserBase::AddValIdent(identfun_type a_pCallback) - { - m_pTokenReader->AddValIdent(a_pCallback); - } - - //--------------------------------------------------------------------------- - /** \brief Set a function that can create variable pointer for unknown expression variables. - \param a_pFactory A pointer to the variable factory. - \param pUserData A user defined context pointer. - */ - void ParserBase::SetVarFactory(facfun_type a_pFactory, void *pUserData) - { - m_pTokenReader->SetVarCreator(a_pFactory, pUserData); - } - - //--------------------------------------------------------------------------- - /** \brief Add a function or operator callback to the parser. */ - void ParserBase::AddCallback( const string_type &a_strName, - const ParserCallback &a_Callback, - funmap_type &a_Storage, - const char_type *a_szCharSet ) - { - if (a_Callback.GetAddr()==0) - Error(ecINVALID_FUN_PTR); - - const funmap_type *pFunMap = &a_Storage; - - // Check for conflicting operator or function names - if ( pFunMap!=&m_FunDef && m_FunDef.find(a_strName)!=m_FunDef.end() ) - Error(ecNAME_CONFLICT, -1, a_strName); - - if ( pFunMap!=&m_PostOprtDef && m_PostOprtDef.find(a_strName)!=m_PostOprtDef.end() ) - Error(ecNAME_CONFLICT, -1, a_strName); - - if ( pFunMap!=&m_InfixOprtDef && pFunMap!=&m_OprtDef && m_InfixOprtDef.find(a_strName)!=m_InfixOprtDef.end() ) - Error(ecNAME_CONFLICT, -1, a_strName); - - if ( pFunMap!=&m_InfixOprtDef && pFunMap!=&m_OprtDef && m_OprtDef.find(a_strName)!=m_OprtDef.end() ) - Error(ecNAME_CONFLICT, -1, a_strName); - - CheckOprt(a_strName, a_Callback, a_szCharSet); - a_Storage[a_strName] = a_Callback; - ReInit(); - } - - //--------------------------------------------------------------------------- - /** \brief Check if a name contains invalid characters. - - \throw ParserException if the name contains invalid characters. - */ - void ParserBase::CheckOprt(const string_type &a_sName, - const ParserCallback &a_Callback, - const string_type &a_szCharSet) const - { - if ( !a_sName.length() || - (a_sName.find_first_not_of(a_szCharSet)!=string_type::npos) || - (a_sName[0]>='0' && a_sName[0]<='9')) - { - switch(a_Callback.GetCode()) - { - case cmOPRT_POSTFIX: Error(ecINVALID_POSTFIX_IDENT, -1, a_sName); - case cmOPRT_INFIX: Error(ecINVALID_INFIX_IDENT, -1, a_sName); - default: Error(ecINVALID_NAME, -1, a_sName); - } - } - } - - //--------------------------------------------------------------------------- - /** \brief Check if a name contains invalid characters. - - \throw ParserException if the name contains invalid characters. - */ - void ParserBase::CheckName(const string_type &a_sName, - const string_type &a_szCharSet) const - { - if ( !a_sName.length() || - (a_sName.find_first_not_of(a_szCharSet)!=string_type::npos) || - (a_sName[0]>='0' && a_sName[0]<='9')) - { - Error(ecINVALID_NAME); - } - } - - //--------------------------------------------------------------------------- - /** \brief Set the formula. - \param a_strFormula Formula as string_type - \throw ParserException in case of syntax errors. - - Triggers first time calculation thus the creation of the bytecode and - scanning of used variables. - */ - void ParserBase::SetExpr(const string_type &a_sExpr) - { - // Check locale compatibility - std::locale loc; - if (m_pTokenReader->GetArgSep()==std::use_facet >(loc).decimal_point()) - Error(ecLOCALE); - - // 20060222: Bugfix for Borland-Kylix: - // adding a space to the expression will keep Borlands KYLIX from going wild - // when calling tellg on a stringstream created from the expression after - // reading a value at the end of an expression. (mu::Parser::IsVal function) - // (tellg returns -1 otherwise causing the parser to ignore the value) - string_type sBuf(a_sExpr + _T(" ") ); - m_pTokenReader->SetFormula(sBuf); - ReInit(); - } - - //--------------------------------------------------------------------------- - /** \brief Get the default symbols used for the built in operators. - \sa c_DefaultOprt - */ - const char_type** ParserBase::GetOprtDef() const - { - return (const char_type **)(&c_DefaultOprt[0]); - } - - //--------------------------------------------------------------------------- - /** \brief Define the set of valid characters to be used in names of - functions, variables, constants. - */ - void ParserBase::DefineNameChars(const char_type *a_szCharset) - { - m_sNameChars = a_szCharset; - } - - //--------------------------------------------------------------------------- - /** \brief Define the set of valid characters to be used in names of - binary operators and postfix operators. - */ - void ParserBase::DefineOprtChars(const char_type *a_szCharset) - { - m_sOprtChars = a_szCharset; - } - - //--------------------------------------------------------------------------- - /** \brief Define the set of valid characters to be used in names of - infix operators. - */ - void ParserBase::DefineInfixOprtChars(const char_type *a_szCharset) - { - m_sInfixOprtChars = a_szCharset; - } - - //--------------------------------------------------------------------------- - /** \brief Virtual function that defines the characters allowed in name identifiers. - \sa #ValidOprtChars, #ValidPrefixOprtChars - */ - const char_type* ParserBase::ValidNameChars() const - { - assert(m_sNameChars.size()); - return m_sNameChars.c_str(); - } - - //--------------------------------------------------------------------------- - /** \brief Virtual function that defines the characters allowed in operator definitions. - \sa #ValidNameChars, #ValidPrefixOprtChars - */ - const char_type* ParserBase::ValidOprtChars() const - { - assert(m_sOprtChars.size()); - return m_sOprtChars.c_str(); - } - - //--------------------------------------------------------------------------- - /** \brief Virtual function that defines the characters allowed in infix operator definitions. - \sa #ValidNameChars, #ValidOprtChars - */ - const char_type* ParserBase::ValidInfixOprtChars() const - { - assert(m_sInfixOprtChars.size()); - return m_sInfixOprtChars.c_str(); - } - - //--------------------------------------------------------------------------- - /** \brief Add a user defined operator. - \post Will reset the Parser to string parsing mode. - */ - void ParserBase::DefinePostfixOprt(const string_type &a_sName, - fun_type1 a_pFun, - bool a_bAllowOpt) - { - AddCallback(a_sName, - ParserCallback(a_pFun, a_bAllowOpt, prPOSTFIX, cmOPRT_POSTFIX), - m_PostOprtDef, - ValidOprtChars() ); - } - - //--------------------------------------------------------------------------- - /** \brief Initialize user defined functions. - - Calls the virtual functions InitFun(), InitConst() and InitOprt(). - */ - void ParserBase::Init() - { - InitCharSets(); - InitFun(); - InitConst(); - InitOprt(); - } - - //--------------------------------------------------------------------------- - /** \brief Add a user defined operator. - \post Will reset the Parser to string parsing mode. - \param [in] a_sName operator Identifier - \param [in] a_pFun Operator callback function - \param [in] a_iPrec Operator Precedence (default=prSIGN) - \param [in] a_bAllowOpt True if operator is volatile (default=false) - \sa EPrec - */ - void ParserBase::DefineInfixOprt(const string_type &a_sName, - fun_type1 a_pFun, - int a_iPrec, - bool a_bAllowOpt) - { - AddCallback(a_sName, - ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, cmOPRT_INFIX), - m_InfixOprtDef, - ValidInfixOprtChars() ); - } - - - //--------------------------------------------------------------------------- - /** \brief Define a binary operator. - \param [in] a_sName The identifier of the operator. - \param [in] a_pFun Pointer to the callback function. - \param [in] a_iPrec Precedence of the operator. - \param [in] a_eAssociativity The associativity of the operator. - \param [in] a_bAllowOpt If this is true the operator may be optimized away. - - Adds a new Binary operator the the parser instance. - */ - void ParserBase::DefineOprt( const string_type &a_sName, - fun_type2 a_pFun, - unsigned a_iPrec, - EOprtAssociativity a_eAssociativity, - bool a_bAllowOpt ) - { - // Check for conflicts with built in operator names - for (int i=0; m_bBuiltInOp && iIgnoreUndefVar(true); - CreateRPN(); // try to create bytecode, but don't use it for any further calculations since it - // may contain references to nonexisting variables. - m_pParseFormula = &ParserBase::ParseString; - m_pTokenReader->IgnoreUndefVar(false); - } - catch(exception_type & /*e*/) - { - // Make sure to stay in string parse mode, dont call ReInit() - // because it deletes the array with the used variables - m_pParseFormula = &ParserBase::ParseString; - m_pTokenReader->IgnoreUndefVar(false); - throw; - } - - return m_pTokenReader->GetUsedVar(); - } - - //--------------------------------------------------------------------------- - /** \brief Return a map containing the used variables only. */ - const varmap_type& ParserBase::GetVar() const - { - return m_VarDef; - } - - //--------------------------------------------------------------------------- - /** \brief Return a map containing all parser constants. */ - const valmap_type& ParserBase::GetConst() const - { - return m_ConstDef; - } - - //--------------------------------------------------------------------------- - /** \brief Return prototypes of all parser functions. - \return #m_FunDef - \sa FunProt - \throw nothrow - - The return type is a map of the public type #funmap_type containing the prototype - definitions for all numerical parser functions. String functions are not part of - this map. The Prototype definition is encapsulated in objects of the class FunProt - one per parser function each associated with function names via a map construct. - */ - const funmap_type& ParserBase::GetFunDef() const - { - return m_FunDef; - } - - //--------------------------------------------------------------------------- - /** \brief Retrieve the formula. */ - const string_type& ParserBase::GetExpr() const - { - return m_pTokenReader->GetExpr(); - } - - //--------------------------------------------------------------------------- - /** \brief Execute a function that takes a single string argument. - \param a_FunTok Function token. - \throw exception_type If the function token is not a string function - */ - ParserBase::token_type ParserBase::ApplyStrFunc(const token_type &a_FunTok, - const std::vector &a_vArg) const - { - if (a_vArg.back().GetCode()!=cmSTRING) - Error(ecSTRING_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString()); - - token_type valTok; - generic_fun_type pFunc = a_FunTok.GetFuncAddr(); - assert(pFunc); - - try - { - // Check function arguments; write dummy value into valtok to represent the result - switch(a_FunTok.GetArgCount()) - { - case 0: valTok.SetVal(1); a_vArg[0].GetAsString(); break; - case 1: valTok.SetVal(1); a_vArg[1].GetAsString(); a_vArg[0].GetVal(); break; - case 2: valTok.SetVal(1); a_vArg[2].GetAsString(); a_vArg[1].GetVal(); a_vArg[0].GetVal(); break; - default: Error(ecINTERNAL_ERROR); - } - } - catch(ParserError& ) - { - Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString()); - } - - // string functions won't be optimized - m_vRPN.AddStrFun(pFunc, a_FunTok.GetArgCount(), a_vArg.back().GetIdx()); - - // Push dummy value representing the function result to the stack - return valTok; - } - - //--------------------------------------------------------------------------- - /** \brief Apply a function token. - \param iArgCount Number of Arguments actually gathered used only for multiarg functions. - \post The result is pushed to the value stack - \post The function token is removed from the stack - \throw exception_type if Argument count does not match function requirements. - */ - void ParserBase::ApplyFunc( ParserStack &a_stOpt, - ParserStack &a_stVal, - int a_iArgCount) const - { - assert(m_pTokenReader.get()); - - // Operator stack empty or does not contain tokens with callback functions - if (a_stOpt.empty() || a_stOpt.top().GetFuncAddr()==0 ) - return; - - token_type funTok = a_stOpt.pop(); - assert(funTok.GetFuncAddr()); - - // Binary operators must rely on their internal operator number - // since counting of operators relies on commas for function arguments - // binary operators do not have commas in their expression - int iArgCount = (funTok.GetCode()==cmOPRT_BIN) ? funTok.GetArgCount() : a_iArgCount; - - // determine how many parameters the function needs. To remember iArgCount includes the - // string parameter whilst GetArgCount() counts only numeric parameters. - int iArgRequired = funTok.GetArgCount() + ((funTok.GetType()==tpSTR) ? 1 : 0); - - // Thats the number of numerical parameters - int iArgNumerical = iArgCount - ((funTok.GetType()==tpSTR) ? 1 : 0); - - if (funTok.GetCode()==cmFUNC_STR && iArgCount-iArgNumerical>1) - Error(ecINTERNAL_ERROR); - - if (funTok.GetArgCount()>=0 && iArgCount>iArgRequired) - Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos()-1, funTok.GetAsString()); - - if (funTok.GetCode()!=cmOPRT_BIN && iArgCountGetPos()-1, funTok.GetAsString()); - - if (funTok.GetCode()==cmFUNC_STR && iArgCount>iArgRequired ) - Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos()-1, funTok.GetAsString()); - - // Collect the numeric function arguments from the value stack and store them - // in a vector - std::vector stArg; - for (int i=0; iGetPos(), funTok.GetAsString()); - } - - switch(funTok.GetCode()) - { - case cmFUNC_STR: - stArg.push_back(a_stVal.pop()); - - if ( stArg.back().GetType()==tpSTR && funTok.GetType()!=tpSTR ) - Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString()); - - ApplyStrFunc(funTok, stArg); - break; - - case cmFUNC_BULK: - m_vRPN.AddBulkFun(funTok.GetFuncAddr(), (int)stArg.size()); - break; - - case cmOPRT_BIN: - case cmOPRT_POSTFIX: - case cmOPRT_INFIX: - case cmFUNC: - if (funTok.GetArgCount()==-1 && iArgCount==0) - Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos(), funTok.GetAsString()); - - m_vRPN.AddFun(funTok.GetFuncAddr(), (funTok.GetArgCount()==-1) ? -iArgNumerical : iArgNumerical); - break; - } - - // Push dummy value representing the function result to the stack - token_type token; - token.SetVal(1); - a_stVal.push(token); - } - - //--------------------------------------------------------------------------- - void ParserBase::ApplyIfElse(ParserStack &a_stOpt, - ParserStack &a_stVal) const - { - // Check if there is an if Else clause to be calculated - while (a_stOpt.size() && a_stOpt.top().GetCode()==cmELSE) - { - token_type opElse = a_stOpt.pop(); - MUP_ASSERT(a_stOpt.size()>0); - - // Take the value associated with the else branch from the value stack - token_type vVal2 = a_stVal.pop(); - - MUP_ASSERT(a_stOpt.size()>0); - MUP_ASSERT(a_stVal.size()>=2); - - // it then else is a ternary operator Pop all three values from the value s - // tack and just return the right value - token_type vVal1 = a_stVal.pop(); - token_type vExpr = a_stVal.pop(); - - a_stVal.push( (vExpr.GetVal()!=0) ? vVal1 : vVal2); - - token_type opIf = a_stOpt.pop(); - MUP_ASSERT(opElse.GetCode()==cmELSE); - MUP_ASSERT(opIf.GetCode()==cmIF); - - m_vRPN.AddIfElse(cmENDIF); - } // while pending if-else-clause found - } - - //--------------------------------------------------------------------------- - /** \brief Performs the necessary steps to write code for - the execution of binary operators into the bytecode. - */ - void ParserBase::ApplyBinOprt(ParserStack &a_stOpt, - ParserStack &a_stVal) const - { - // is it a user defined binary operator? - if (a_stOpt.top().GetCode()==cmOPRT_BIN) - { - ApplyFunc(a_stOpt, a_stVal, 2); - } - else - { - MUP_ASSERT(a_stVal.size()>=2); - token_type valTok1 = a_stVal.pop(), - valTok2 = a_stVal.pop(), - optTok = a_stOpt.pop(), - resTok; - - if ( valTok1.GetType()!=valTok2.GetType() || - (valTok1.GetType()==tpSTR && valTok2.GetType()==tpSTR) ) - Error(ecOPRT_TYPE_CONFLICT, m_pTokenReader->GetPos(), optTok.GetAsString()); - - if (optTok.GetCode()==cmASSIGN) - { - if (valTok2.GetCode()!=cmVAR) - Error(ecUNEXPECTED_OPERATOR, -1, _T("=")); - - m_vRPN.AddAssignOp(valTok2.GetVar()); - } - else - m_vRPN.AddOp(optTok.GetCode()); - - resTok.SetVal(1); - a_stVal.push(resTok); - } - } - - //--------------------------------------------------------------------------- - /** \brief Apply a binary operator. - \param a_stOpt The operator stack - \param a_stVal The value stack - */ - void ParserBase::ApplyRemainingOprt(ParserStack &stOpt, - ParserStack &stVal) const - { - while (stOpt.size() && - stOpt.top().GetCode() != cmBO && - stOpt.top().GetCode() != cmIF) - { - token_type tok = stOpt.top(); - switch (tok.GetCode()) - { - case cmOPRT_INFIX: - case cmOPRT_BIN: - case cmLE: - case cmGE: - case cmNEQ: - case cmEQ: - case cmLT: - case cmGT: - case cmADD: - case cmSUB: - case cmMUL: - case cmDIV: - case cmPOW: - case cmLAND: - case cmLOR: - case cmASSIGN: - if (stOpt.top().GetCode()==cmOPRT_INFIX) - ApplyFunc(stOpt, stVal, 1); - else - ApplyBinOprt(stOpt, stVal); - break; - - case cmELSE: - ApplyIfElse(stOpt, stVal); - break; - - default: - Error(ecINTERNAL_ERROR); - } - } - } - - //--------------------------------------------------------------------------- - /** \brief Parse the command code. - \sa ParseString(...) - - Command code contains precalculated stack positions of the values and the - associated operators. The Stack is filled beginning from index one the - value at index zero is not used at all. - */ - value_type ParserBase::ParseCmdCode() const - { - return ParseCmdCodeBulk(0, 0); - } - - //--------------------------------------------------------------------------- - /** \brief Evaluate the RPN. - \param nOffset The offset added to variable addresses (for bulk mode) - \param nThreadID OpenMP Thread id of the calling thread - */ - value_type ParserBase::ParseCmdCodeBulk(int nOffset, int nThreadID) const - { - assert(nThreadID<=s_MaxNumOpenMPThreads); - - // Note: The check for nOffset==0 and nThreadID here is not necessary but - // brings a minor performance gain when not in bulk mode. - value_type *Stack = ((nOffset==0) && (nThreadID==0)) ? &m_vStackBuffer[0] : &m_vStackBuffer[nThreadID * (m_vStackBuffer.size() / s_MaxNumOpenMPThreads)]; - value_type buf; - int sidx(0); - for (const SToken *pTok = m_vRPN.GetBase(); pTok->Cmd!=cmEND ; ++pTok) - { - switch (pTok->Cmd) - { - // built in binary operators - case cmLE: --sidx; Stack[sidx] = Stack[sidx] <= Stack[sidx+1]; continue; - case cmGE: --sidx; Stack[sidx] = Stack[sidx] >= Stack[sidx+1]; continue; - case cmNEQ: --sidx; Stack[sidx] = Stack[sidx] != Stack[sidx+1]; continue; - case cmEQ: --sidx; Stack[sidx] = Stack[sidx] == Stack[sidx+1]; continue; - case cmLT: --sidx; Stack[sidx] = Stack[sidx] < Stack[sidx+1]; continue; - case cmGT: --sidx; Stack[sidx] = Stack[sidx] > Stack[sidx+1]; continue; - case cmADD: --sidx; Stack[sidx] += Stack[1+sidx]; continue; - case cmSUB: --sidx; Stack[sidx] -= Stack[1+sidx]; continue; - case cmMUL: --sidx; Stack[sidx] *= Stack[1+sidx]; continue; - case cmDIV: --sidx; - - #if defined(MUP_MATH_EXCEPTIONS) - if (Stack[1+sidx]==0) - Error(ecDIV_BY_ZERO); - #endif - Stack[sidx] /= Stack[1+sidx]; - continue; - - case cmPOW: - --sidx; Stack[sidx] = MathImpl::Pow(Stack[sidx], Stack[1+sidx]); - continue; - - case cmLAND: --sidx; Stack[sidx] = Stack[sidx] && Stack[sidx+1]; continue; - case cmLOR: --sidx; Stack[sidx] = Stack[sidx] || Stack[sidx+1]; continue; - - case cmASSIGN: - // Bugfix for Bulkmode: - // for details see: - // https://groups.google.com/forum/embed/?place=forum/muparser-dev&showsearch=true&showpopout=true&showtabs=false&parenturl=http://muparser.beltoforion.de/mup_forum.html&afterlogin&pli=1#!topic/muparser-dev/szgatgoHTws - --sidx; Stack[sidx] = *(pTok->Oprt.ptr + nOffset) = Stack[sidx + 1]; continue; - // original code: - //--sidx; Stack[sidx] = *pTok->Oprt.ptr = Stack[sidx+1]; continue; - - //case cmBO: // unused, listed for compiler optimization purposes - //case cmBC: - // MUP_FAIL(INVALID_CODE_IN_BYTECODE); - // continue; - - case cmIF: - if (Stack[sidx--]==0) - pTok += pTok->Oprt.offset; - continue; - - case cmELSE: - pTok += pTok->Oprt.offset; - continue; - - case cmENDIF: - continue; - - //case cmARG_SEP: - // MUP_FAIL(INVALID_CODE_IN_BYTECODE); - // continue; - - // value and variable tokens - case cmVAR: Stack[++sidx] = *(pTok->Val.ptr + nOffset); continue; - case cmVAL: Stack[++sidx] = pTok->Val.data2; continue; - - case cmVARPOW2: buf = *(pTok->Val.ptr + nOffset); - Stack[++sidx] = buf*buf; - continue; - - case cmVARPOW3: buf = *(pTok->Val.ptr + nOffset); - Stack[++sidx] = buf*buf*buf; - continue; - - case cmVARPOW4: buf = *(pTok->Val.ptr + nOffset); - Stack[++sidx] = buf*buf*buf*buf; - continue; - - case cmVARMUL: Stack[++sidx] = *(pTok->Val.ptr + nOffset) * pTok->Val.data + pTok->Val.data2; - continue; - - // Next is treatment of numeric functions - case cmFUNC: - { - int iArgCount = pTok->Fun.argc; - - // switch according to argument count - switch(iArgCount) - { - case 0: sidx += 1; Stack[sidx] = (*(fun_type0)pTok->Fun.ptr)(); continue; - case 1: Stack[sidx] = (*(fun_type1)pTok->Fun.ptr)(Stack[sidx]); continue; - case 2: sidx -= 1; Stack[sidx] = (*(fun_type2)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1]); continue; - case 3: sidx -= 2; Stack[sidx] = (*(fun_type3)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2]); continue; - case 4: sidx -= 3; Stack[sidx] = (*(fun_type4)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3]); continue; - case 5: sidx -= 4; Stack[sidx] = (*(fun_type5)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4]); continue; - case 6: sidx -= 5; Stack[sidx] = (*(fun_type6)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5]); continue; - case 7: sidx -= 6; Stack[sidx] = (*(fun_type7)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6]); continue; - case 8: sidx -= 7; Stack[sidx] = (*(fun_type8)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7]); continue; - case 9: sidx -= 8; Stack[sidx] = (*(fun_type9)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8]); continue; - case 10:sidx -= 9; Stack[sidx] = (*(fun_type10)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8], Stack[sidx+9]); continue; - default: - if (iArgCount>0) // function with variable arguments store the number as a negative value - Error(ecINTERNAL_ERROR, 1); - - sidx -= -iArgCount - 1; - Stack[sidx] =(*(multfun_type)pTok->Fun.ptr)(&Stack[sidx], -iArgCount); - continue; - } - } - - // Next is treatment of string functions - case cmFUNC_STR: - { - sidx -= pTok->Fun.argc -1; - - // The index of the string argument in the string table - int iIdxStack = pTok->Fun.idx; - MUP_ASSERT( iIdxStack>=0 && iIdxStack<(int)m_vStringBuf.size() ); - - switch(pTok->Fun.argc) // switch according to argument count - { - case 0: Stack[sidx] = (*(strfun_type1)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str()); continue; - case 1: Stack[sidx] = (*(strfun_type2)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx]); continue; - case 2: Stack[sidx] = (*(strfun_type3)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx], Stack[sidx+1]); continue; - } - - continue; - } - - case cmFUNC_BULK: - { - int iArgCount = pTok->Fun.argc; - - // switch according to argument count - switch(iArgCount) - { - case 0: sidx += 1; Stack[sidx] = (*(bulkfun_type0 )pTok->Fun.ptr)(nOffset, nThreadID); continue; - case 1: Stack[sidx] = (*(bulkfun_type1 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx]); continue; - case 2: sidx -= 1; Stack[sidx] = (*(bulkfun_type2 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1]); continue; - case 3: sidx -= 2; Stack[sidx] = (*(bulkfun_type3 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2]); continue; - case 4: sidx -= 3; Stack[sidx] = (*(bulkfun_type4 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3]); continue; - case 5: sidx -= 4; Stack[sidx] = (*(bulkfun_type5 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4]); continue; - case 6: sidx -= 5; Stack[sidx] = (*(bulkfun_type6 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5]); continue; - case 7: sidx -= 6; Stack[sidx] = (*(bulkfun_type7 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6]); continue; - case 8: sidx -= 7; Stack[sidx] = (*(bulkfun_type8 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7]); continue; - case 9: sidx -= 8; Stack[sidx] = (*(bulkfun_type9 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8]); continue; - case 10:sidx -= 9; Stack[sidx] = (*(bulkfun_type10)pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8], Stack[sidx+9]); continue; - default: - Error(ecINTERNAL_ERROR, 2); - continue; - } - } - - default: - Error(ecINTERNAL_ERROR, 3); - return 0; - } // switch CmdCode - } // for all bytecode tokens - - return Stack[m_nFinalResultIdx]; - } - - //--------------------------------------------------------------------------- - void ParserBase::CreateRPN() const - { - if (!m_pTokenReader->GetExpr().length()) - Error(ecUNEXPECTED_EOF, 0); - - ParserStack stOpt, stVal; - ParserStack stArgCount; - token_type opta, opt; // for storing operators - token_type val, tval; // for storing value - - ReInit(); - - // The outermost counter counts the number of separated items - // such as in "a=10,b=20,c=c+a" - stArgCount.push(1); - - for(;;) - { - opt = m_pTokenReader->ReadNextToken(); - - switch (opt.GetCode()) - { - // - // Next three are different kind of value entries - // - case cmSTRING: - opt.SetIdx((int)m_vStringBuf.size()); // Assign buffer index to token - stVal.push(opt); - m_vStringBuf.push_back(opt.GetAsString()); // Store string in internal buffer - break; - - case cmVAR: - stVal.push(opt); - m_vRPN.AddVar( static_cast(opt.GetVar()) ); - break; - - case cmVAL: - stVal.push(opt); - m_vRPN.AddVal( opt.GetVal() ); - break; - - case cmELSE: - m_nIfElseCounter--; - if (m_nIfElseCounter<0) - Error(ecMISPLACED_COLON, m_pTokenReader->GetPos()); - - ApplyRemainingOprt(stOpt, stVal); - m_vRPN.AddIfElse(cmELSE); - stOpt.push(opt); - break; - - - case cmARG_SEP: - if (stArgCount.empty()) - Error(ecUNEXPECTED_ARG_SEP, m_pTokenReader->GetPos()); - - ++stArgCount.top(); - // fallthrough intentional (no break!) - - case cmEND: - ApplyRemainingOprt(stOpt, stVal); - break; - - case cmBC: - { - // The argument count for parameterless functions is zero - // by default an opening bracket sets parameter count to 1 - // in preparation of arguments to come. If the last token - // was an opening bracket we know better... - if (opta.GetCode()==cmBO) - --stArgCount.top(); - - ApplyRemainingOprt(stOpt, stVal); - - // Check if the bracket content has been evaluated completely - if (stOpt.size() && stOpt.top().GetCode()==cmBO) - { - // if opt is ")" and opta is "(" the bracket has been evaluated, now its time to check - // if there is either a function or a sign pending - // neither the opening nor the closing bracket will be pushed back to - // the operator stack - // Check if a function is standing in front of the opening bracket, - // if yes evaluate it afterwards check for infix operators - assert(stArgCount.size()); - int iArgCount = stArgCount.pop(); - - stOpt.pop(); // Take opening bracket from stack - - if (iArgCount>1 && ( stOpt.size()==0 || - (stOpt.top().GetCode()!=cmFUNC && - stOpt.top().GetCode()!=cmFUNC_BULK && - stOpt.top().GetCode()!=cmFUNC_STR) ) ) - Error(ecUNEXPECTED_ARG, m_pTokenReader->GetPos()); - - // The opening bracket was popped from the stack now check if there - // was a function before this bracket - if (stOpt.size() && - stOpt.top().GetCode()!=cmOPRT_INFIX && - stOpt.top().GetCode()!=cmOPRT_BIN && - stOpt.top().GetFuncAddr()!=0) - { - ApplyFunc(stOpt, stVal, iArgCount); - } - } - } // if bracket content is evaluated - break; - - // - // Next are the binary operator entries - // - //case cmAND: // built in binary operators - //case cmOR: - //case cmXOR: - case cmIF: - m_nIfElseCounter++; - // fallthrough intentional (no break!) - - case cmLAND: - case cmLOR: - case cmLT: - case cmGT: - case cmLE: - case cmGE: - case cmNEQ: - case cmEQ: - case cmADD: - case cmSUB: - case cmMUL: - case cmDIV: - case cmPOW: - case cmASSIGN: - case cmOPRT_BIN: - - // A binary operator (user defined or built in) has been found. - while ( stOpt.size() && - stOpt.top().GetCode() != cmBO && - stOpt.top().GetCode() != cmELSE && - stOpt.top().GetCode() != cmIF) - { - int nPrec1 = GetOprtPrecedence(stOpt.top()), - nPrec2 = GetOprtPrecedence(opt); - - if (stOpt.top().GetCode()==opt.GetCode()) - { - - // Deal with operator associativity - EOprtAssociativity eOprtAsct = GetOprtAssociativity(opt); - if ( (eOprtAsct==oaRIGHT && (nPrec1 <= nPrec2)) || - (eOprtAsct==oaLEFT && (nPrec1 < nPrec2)) ) - { - break; - } - } - else if (nPrec1 < nPrec2) - { - // In case the operators are not equal the precedence decides alone... - break; - } - - if (stOpt.top().GetCode()==cmOPRT_INFIX) - ApplyFunc(stOpt, stVal, 1); - else - ApplyBinOprt(stOpt, stVal); - } // while ( ... ) - - if (opt.GetCode()==cmIF) - m_vRPN.AddIfElse(opt.GetCode()); - - // The operator can't be evaluated right now, push back to the operator stack - stOpt.push(opt); - break; - - // - // Last section contains functions and operators implicitly mapped to functions - // - case cmBO: - stArgCount.push(1); - stOpt.push(opt); - break; - - case cmOPRT_INFIX: - case cmFUNC: - case cmFUNC_BULK: - case cmFUNC_STR: - stOpt.push(opt); - break; - - case cmOPRT_POSTFIX: - stOpt.push(opt); - ApplyFunc(stOpt, stVal, 1); // this is the postfix operator - break; - - default: Error(ecINTERNAL_ERROR, 3); - } // end of switch operator-token - - opta = opt; - - if ( opt.GetCode() == cmEND ) - { - m_vRPN.Finalize(); - break; - } - - if (ParserBase::g_DbgDumpStack) - { - StackDump(stVal, stOpt); - m_vRPN.AsciiDump(); - } - } // while (true) - - if (ParserBase::g_DbgDumpCmdCode) - m_vRPN.AsciiDump(); - - if (m_nIfElseCounter>0) - Error(ecMISSING_ELSE_CLAUSE); - - // get the last value (= final result) from the stack - MUP_ASSERT(stArgCount.size()==1); - m_nFinalResultIdx = stArgCount.top(); - if (m_nFinalResultIdx==0) - Error(ecINTERNAL_ERROR, 9); - - if (stVal.size()==0) - Error(ecEMPTY_EXPRESSION); - - if (stVal.top().GetType()!=tpDBL) - Error(ecSTR_RESULT); - - m_vStackBuffer.resize(m_vRPN.GetMaxStackSize() * s_MaxNumOpenMPThreads); - } - - //--------------------------------------------------------------------------- - /** \brief One of the two main parse functions. - \sa ParseCmdCode(...) - - Parse expression from input string. Perform syntax checking and create - bytecode. After parsing the string and creating the bytecode the function - pointer #m_pParseFormula will be changed to the second parse routine the - uses bytecode instead of string parsing. - */ - value_type ParserBase::ParseString() const - { - try - { - CreateRPN(); - m_pParseFormula = &ParserBase::ParseCmdCode; - return (this->*m_pParseFormula)(); - } - catch(ParserError &exc) - { - exc.SetFormula(m_pTokenReader->GetExpr()); - throw; - } - } - - //--------------------------------------------------------------------------- - /** \brief Create an error containing the parse error position. - - This function will create an Parser Exception object containing the error text and - its position. - - \param a_iErrc [in] The error code of type #EErrorCodes. - \param a_iPos [in] The position where the error was detected. - \param a_strTok [in] The token string representation associated with the error. - \throw ParserException always throws thats the only purpose of this function. - */ - void ParserBase::Error(EErrorCodes a_iErrc, int a_iPos, const string_type &a_sTok) const - { - throw exception_type(a_iErrc, a_sTok, m_pTokenReader->GetExpr(), a_iPos); - } - - //------------------------------------------------------------------------------ - /** \brief Clear all user defined variables. - \throw nothrow - - Resets the parser to string parsing mode by calling #ReInit. - */ - void ParserBase::ClearVar() - { - m_VarDef.clear(); - ReInit(); - } - - //------------------------------------------------------------------------------ - /** \brief Remove a variable from internal storage. - \throw nothrow - - Removes a variable if it exists. If the Variable does not exist nothing will be done. - */ - void ParserBase::RemoveVar(const string_type &a_strVarName) - { - varmap_type::iterator item = m_VarDef.find(a_strVarName); - if (item!=m_VarDef.end()) - { - m_VarDef.erase(item); - ReInit(); - } - } - - //------------------------------------------------------------------------------ - /** \brief Clear all functions. - \post Resets the parser to string parsing mode. - \throw nothrow - */ - void ParserBase::ClearFun() - { - m_FunDef.clear(); - ReInit(); - } - - //------------------------------------------------------------------------------ - /** \brief Clear all user defined constants. - - Both numeric and string constants will be removed from the internal storage. - \post Resets the parser to string parsing mode. - \throw nothrow - */ - void ParserBase::ClearConst() - { - m_ConstDef.clear(); - m_StrVarDef.clear(); - ReInit(); - } - - //------------------------------------------------------------------------------ - /** \brief Clear all user defined postfix operators. - \post Resets the parser to string parsing mode. - \throw nothrow - */ - void ParserBase::ClearPostfixOprt() - { - m_PostOprtDef.clear(); - ReInit(); - } - - //------------------------------------------------------------------------------ - /** \brief Clear all user defined binary operators. - \post Resets the parser to string parsing mode. - \throw nothrow - */ - void ParserBase::ClearOprt() - { - m_OprtDef.clear(); - ReInit(); - } - - //------------------------------------------------------------------------------ - /** \brief Clear the user defined Prefix operators. - \post Resets the parser to string parser mode. - \throw nothrow - */ - void ParserBase::ClearInfixOprt() - { - m_InfixOprtDef.clear(); - ReInit(); - } - - //------------------------------------------------------------------------------ - /** \brief Enable or disable the formula optimization feature. - \post Resets the parser to string parser mode. - \throw nothrow - */ - void ParserBase::EnableOptimizer(bool a_bIsOn) - { - m_vRPN.EnableOptimizer(a_bIsOn); - ReInit(); - } - - //--------------------------------------------------------------------------- - /** \brief Enable the dumping of bytecode and stack content on the console. - \param bDumpCmd Flag to enable dumping of the current bytecode to the console. - \param bDumpStack Flag to enable dumping of the stack content is written to the console. - - This function is for debug purposes only! - */ - void ParserBase::EnableDebugDump(bool bDumpCmd, bool bDumpStack) - { - ParserBase::g_DbgDumpCmdCode = bDumpCmd; - ParserBase::g_DbgDumpStack = bDumpStack; - } - - //------------------------------------------------------------------------------ - /** \brief Enable or disable the built in binary operators. - \throw nothrow - \sa m_bBuiltInOp, ReInit() - - If you disable the built in binary operators there will be no binary operators - defined. Thus you must add them manually one by one. It is not possible to - disable built in operators selectively. This function will Reinitialize the - parser by calling ReInit(). - */ - void ParserBase::EnableBuiltInOprt(bool a_bIsOn) - { - m_bBuiltInOp = a_bIsOn; - ReInit(); - } - - //------------------------------------------------------------------------------ - /** \brief Query status of built in variables. - \return #m_bBuiltInOp; true if built in operators are enabled. - \throw nothrow - */ - bool ParserBase::HasBuiltInOprt() const - { - return m_bBuiltInOp; - } - - //------------------------------------------------------------------------------ - /** \brief Get the argument separator character. - */ - char_type ParserBase::GetArgSep() const - { - return m_pTokenReader->GetArgSep(); - } - - //------------------------------------------------------------------------------ - /** \brief Set argument separator. - \param cArgSep the argument separator character. - */ - void ParserBase::SetArgSep(char_type cArgSep) - { - m_pTokenReader->SetArgSep(cArgSep); - } - - //------------------------------------------------------------------------------ - /** \brief Dump stack content. - - This function is used for debugging only. - */ - void ParserBase::StackDump(const ParserStack &a_stVal, - const ParserStack &a_stOprt) const - { - ParserStack stOprt(a_stOprt), - stVal(a_stVal); - - mu::console() << _T("\nValue stack:\n"); - while ( !stVal.empty() ) - { - token_type val = stVal.pop(); - if (val.GetType()==tpSTR) - mu::console() << _T(" \"") << val.GetAsString() << _T("\" "); - else - mu::console() << _T(" ") << val.GetVal() << _T(" "); - } - mu::console() << "\nOperator stack:\n"; - - while ( !stOprt.empty() ) - { - if (stOprt.top().GetCode()<=cmASSIGN) - { - mu::console() << _T("OPRT_INTRNL \"") - << ParserBase::c_DefaultOprt[stOprt.top().GetCode()] - << _T("\" \n"); - } - else - { - switch(stOprt.top().GetCode()) - { - case cmVAR: mu::console() << _T("VAR\n"); break; - case cmVAL: mu::console() << _T("VAL\n"); break; - case cmFUNC: mu::console() << _T("FUNC \"") - << stOprt.top().GetAsString() - << _T("\"\n"); break; - case cmFUNC_BULK: mu::console() << _T("FUNC_BULK \"") - << stOprt.top().GetAsString() - << _T("\"\n"); break; - case cmOPRT_INFIX: mu::console() << _T("OPRT_INFIX \"") - << stOprt.top().GetAsString() - << _T("\"\n"); break; - case cmOPRT_BIN: mu::console() << _T("OPRT_BIN \"") - << stOprt.top().GetAsString() - << _T("\"\n"); break; - case cmFUNC_STR: mu::console() << _T("FUNC_STR\n"); break; - case cmEND: mu::console() << _T("END\n"); break; - case cmUNKNOWN: mu::console() << _T("UNKNOWN\n"); break; - case cmBO: mu::console() << _T("BRACKET \"(\"\n"); break; - case cmBC: mu::console() << _T("BRACKET \")\"\n"); break; - case cmIF: mu::console() << _T("IF\n"); break; - case cmELSE: mu::console() << _T("ELSE\n"); break; - case cmENDIF: mu::console() << _T("ENDIF\n"); break; - default: mu::console() << stOprt.top().GetCode() << _T(" "); break; - } - } - stOprt.pop(); - } - - mu::console() << dec << endl; - } - - //------------------------------------------------------------------------------ - /** \brief Evaluate an expression containing comma separated subexpressions - \param [out] nStackSize The total number of results available - \return Pointer to the array containing all expression results - - This member function can be used to retrieve all results of an expression - made up of multiple comma separated subexpressions (i.e. "x+y,sin(x),cos(y)") - */ - value_type* ParserBase::Eval(int &nStackSize) const - { - (this->*m_pParseFormula)(); - nStackSize = m_nFinalResultIdx; - - // (for historic reasons the stack starts at position 1) - return &m_vStackBuffer[1]; - } - - //--------------------------------------------------------------------------- - /** \brief Return the number of results on the calculation stack. - - If the expression contains comma separated subexpressions (i.e. "sin(y), x+y"). - There may be more than one return value. This function returns the number of - available results. - */ - int ParserBase::GetNumResults() const - { - return m_nFinalResultIdx; - } - - //--------------------------------------------------------------------------- - /** \brief Calculate the result. - - A note on const correctness: - I consider it important that Calc is a const function. - Due to caching operations Calc changes only the state of internal variables with one exception - m_UsedVar this is reset during string parsing and accessible from the outside. Instead of making - Calc non const GetUsedVar is non const because it explicitly calls Eval() forcing this update. - - \pre A formula must be set. - \pre Variables must have been set (if needed) - - \sa #m_pParseFormula - \return The evaluation result - \throw ParseException if no Formula is set or in case of any other error related to the formula. - */ - value_type ParserBase::Eval() const - { - return (this->*m_pParseFormula)(); - } - - //--------------------------------------------------------------------------- - void ParserBase::Eval(value_type *results, int nBulkSize) - { -/* Commented because it is making a unit test impossible - - // Parallelization does not make sense for fewer than 10000 computations - // due to thread creation overhead. If the bulk size is below 2000 - // computation is refused. - if (nBulkSize<2000) - { - throw ParserError(ecUNREASONABLE_NUMBER_OF_COMPUTATIONS); - } -*/ - CreateRPN(); - - int i = 0; - -#ifdef MUP_USE_OPENMP -//#define DEBUG_OMP_STUFF - #ifdef DEBUG_OMP_STUFF - int *pThread = new int[nBulkSize]; - int *pIdx = new int[nBulkSize]; - #endif - - int nMaxThreads = std::min(omp_get_max_threads(), s_MaxNumOpenMPThreads); - int nThreadID = 0, ct = 0; - omp_set_num_threads(nMaxThreads); - - #pragma omp parallel for schedule(static, nBulkSize/nMaxThreads) private(nThreadID) - for (i=0; i \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2011 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "muParserBytecode.h" - -#include -#include -#include -#include -#include -#include - -#include "muParserDef.h" -#include "muParserError.h" -#include "muParserToken.h" -#include "muParserStack.h" -#include "muParserTemplateMagic.h" - - -namespace mu -{ - //--------------------------------------------------------------------------- - /** \brief Bytecode default constructor. */ - ParserByteCode::ParserByteCode() - :m_iStackPos(0) - ,m_iMaxStackSize(0) - ,m_vRPN() - ,m_bEnableOptimizer(true) - { - m_vRPN.reserve(50); - } - - //--------------------------------------------------------------------------- - /** \brief Copy constructor. - - Implemented in Terms of Assign(const ParserByteCode &a_ByteCode) - */ - ParserByteCode::ParserByteCode(const ParserByteCode &a_ByteCode) - { - Assign(a_ByteCode); - } - - //--------------------------------------------------------------------------- - /** \brief Assignment operator. - - Implemented in Terms of Assign(const ParserByteCode &a_ByteCode) - */ - ParserByteCode& ParserByteCode::operator=(const ParserByteCode &a_ByteCode) - { - Assign(a_ByteCode); - return *this; - } - - //--------------------------------------------------------------------------- - void ParserByteCode::EnableOptimizer(bool bStat) - { - m_bEnableOptimizer = bStat; - } - - //--------------------------------------------------------------------------- - /** \brief Copy state of another object to this. - - \throw nowthrow - */ - void ParserByteCode::Assign(const ParserByteCode &a_ByteCode) - { - if (this==&a_ByteCode) - return; - - m_iStackPos = a_ByteCode.m_iStackPos; - m_vRPN = a_ByteCode.m_vRPN; - m_iMaxStackSize = a_ByteCode.m_iMaxStackSize; - m_bEnableOptimizer = a_ByteCode.m_bEnableOptimizer; - } - - //--------------------------------------------------------------------------- - /** \brief Add a Variable pointer to bytecode. - \param a_pVar Pointer to be added. - \throw nothrow - */ - void ParserByteCode::AddVar(value_type *a_pVar) - { - ++m_iStackPos; - m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); - - // optimization does not apply - SToken tok; - tok.Cmd = cmVAR; - tok.Val.ptr = a_pVar; - tok.Val.data = 1; - tok.Val.data2 = 0; - m_vRPN.push_back(tok); - } - - //--------------------------------------------------------------------------- - /** \brief Add a Variable pointer to bytecode. - - Value entries in byte code consist of: -
    -
  • value array position of the value
  • -
  • the operator code according to ParserToken::cmVAL
  • -
  • the value stored in #mc_iSizeVal number of bytecode entries.
  • -
- - \param a_pVal Value to be added. - \throw nothrow - */ - void ParserByteCode::AddVal(value_type a_fVal) - { - ++m_iStackPos; - m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); - - // If optimization does not apply - SToken tok; - tok.Cmd = cmVAL; - tok.Val.ptr = NULL; - tok.Val.data = 0; - tok.Val.data2 = a_fVal; - m_vRPN.push_back(tok); - } - - //--------------------------------------------------------------------------- - void ParserByteCode::ConstantFolding(ECmdCode a_Oprt) - { - std::size_t sz = m_vRPN.size(); - value_type &x = m_vRPN[sz-2].Val.data2, - &y = m_vRPN[sz-1].Val.data2; - switch (a_Oprt) - { - case cmLAND: x = (int)x && (int)y; m_vRPN.pop_back(); break; - case cmLOR: x = (int)x || (int)y; m_vRPN.pop_back(); break; - case cmLT: x = x < y; m_vRPN.pop_back(); break; - case cmGT: x = x > y; m_vRPN.pop_back(); break; - case cmLE: x = x <= y; m_vRPN.pop_back(); break; - case cmGE: x = x >= y; m_vRPN.pop_back(); break; - case cmNEQ: x = x != y; m_vRPN.pop_back(); break; - case cmEQ: x = x == y; m_vRPN.pop_back(); break; - case cmADD: x = x + y; m_vRPN.pop_back(); break; - case cmSUB: x = x - y; m_vRPN.pop_back(); break; - case cmMUL: x = x * y; m_vRPN.pop_back(); break; - case cmDIV: - -#if defined(MUP_MATH_EXCEPTIONS) - if (y==0) - throw ParserError(ecDIV_BY_ZERO, _T("0")); -#endif - - x = x / y; - m_vRPN.pop_back(); - break; - - case cmPOW: x = MathImpl::Pow(x, y); - m_vRPN.pop_back(); - break; - - default: - break; - } // switch opcode - } - - //--------------------------------------------------------------------------- - /** \brief Add an operator identifier to bytecode. - - Operator entries in byte code consist of: -
    -
  • value array position of the result
  • -
  • the operator code according to ParserToken::ECmdCode
  • -
- - \sa ParserToken::ECmdCode - */ - void ParserByteCode::AddOp(ECmdCode a_Oprt) - { - bool bOptimized = false; - - if (m_bEnableOptimizer) - { - std::size_t sz = m_vRPN.size(); - - // Check for foldable constants like: - // cmVAL cmVAL cmADD - // where cmADD can stand fopr any binary operator applied to - // two constant values. - if (sz>=2 && m_vRPN[sz-2].Cmd == cmVAL && m_vRPN[sz-1].Cmd == cmVAL) - { - ConstantFolding(a_Oprt); - bOptimized = true; - } - else - { - switch(a_Oprt) - { - case cmPOW: - // Optimization for polynomials of low order - if (m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-1].Cmd == cmVAL) - { - if (m_vRPN[sz-1].Val.data2==2) - m_vRPN[sz-2].Cmd = cmVARPOW2; - else if (m_vRPN[sz-1].Val.data2==3) - m_vRPN[sz-2].Cmd = cmVARPOW3; - else if (m_vRPN[sz-1].Val.data2==4) - m_vRPN[sz-2].Cmd = cmVARPOW4; - else - break; - - m_vRPN.pop_back(); - bOptimized = true; - } - break; - - case cmSUB: - case cmADD: - // Simple optimization based on pattern recognition for a shitload of different - // bytecode combinations of addition/subtraction - if ( (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAL) || - (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVAR) || - (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL) || - (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAL) || - (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) || - (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) || - (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) || - (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) ) - { - assert( (m_vRPN[sz-2].Val.ptr==NULL && m_vRPN[sz-1].Val.ptr!=NULL) || - (m_vRPN[sz-2].Val.ptr!=NULL && m_vRPN[sz-1].Val.ptr==NULL) || - (m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) ); - - m_vRPN[sz-2].Cmd = cmVARMUL; - m_vRPN[sz-2].Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr)); // variable - m_vRPN[sz-2].Val.data2 += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].Val.data2; // offset - m_vRPN[sz-2].Val.data += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].Val.data; // multiplicand - m_vRPN.pop_back(); - bOptimized = true; - } - break; - - case cmMUL: - if ( (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAL) || - (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVAR) ) - { - m_vRPN[sz-2].Cmd = cmVARMUL; - m_vRPN[sz-2].Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr)); - m_vRPN[sz-2].Val.data = m_vRPN[sz-2].Val.data2 + m_vRPN[sz-1].Val.data2; - m_vRPN[sz-2].Val.data2 = 0; - m_vRPN.pop_back(); - bOptimized = true; - } - else if ( (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL) || - (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAL) ) - { - // Optimization: 2*(3*b+1) or (3*b+1)*2 -> 6*b+2 - m_vRPN[sz-2].Cmd = cmVARMUL; - m_vRPN[sz-2].Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr)); - if (m_vRPN[sz-1].Cmd == cmVAL) - { - m_vRPN[sz-2].Val.data *= m_vRPN[sz-1].Val.data2; - m_vRPN[sz-2].Val.data2 *= m_vRPN[sz-1].Val.data2; - } - else - { - m_vRPN[sz-2].Val.data = m_vRPN[sz-1].Val.data * m_vRPN[sz-2].Val.data2; - m_vRPN[sz-2].Val.data2 = m_vRPN[sz-1].Val.data2 * m_vRPN[sz-2].Val.data2; - } - m_vRPN.pop_back(); - bOptimized = true; - } - else if (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAR && - m_vRPN[sz-1].Val.ptr == m_vRPN[sz-2].Val.ptr) - { - // Optimization: a*a -> a^2 - m_vRPN[sz-2].Cmd = cmVARPOW2; - m_vRPN.pop_back(); - bOptimized = true; - } - break; - - case cmDIV: - if (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-1].Val.data2!=0) - { - // Optimization: 4*a/2 -> 2*a - m_vRPN[sz-2].Val.data /= m_vRPN[sz-1].Val.data2; - m_vRPN[sz-2].Val.data2 /= m_vRPN[sz-1].Val.data2; - m_vRPN.pop_back(); - bOptimized = true; - } - break; - - } // switch a_Oprt - } - } - - // If optimization can't be applied just write the value - if (!bOptimized) - { - --m_iStackPos; - SToken tok; - tok.Cmd = a_Oprt; - m_vRPN.push_back(tok); - } - } - - //--------------------------------------------------------------------------- - void ParserByteCode::AddIfElse(ECmdCode a_Oprt) - { - SToken tok; - tok.Cmd = a_Oprt; - m_vRPN.push_back(tok); - } - - //--------------------------------------------------------------------------- - /** \brief Add an assignment operator - - Operator entries in byte code consist of: -
    -
  • cmASSIGN code
  • -
  • the pointer of the destination variable
  • -
- - \sa ParserToken::ECmdCode - */ - void ParserByteCode::AddAssignOp(value_type *a_pVar) - { - --m_iStackPos; - - SToken tok; - tok.Cmd = cmASSIGN; - tok.Oprt.ptr = a_pVar; - m_vRPN.push_back(tok); - } - - //--------------------------------------------------------------------------- - /** \brief Add function to bytecode. - - \param a_iArgc Number of arguments, negative numbers indicate multiarg functions. - \param a_pFun Pointer to function callback. - */ - void ParserByteCode::AddFun(generic_fun_type a_pFun, int a_iArgc) - { - if (a_iArgc>=0) - { - m_iStackPos = m_iStackPos - a_iArgc + 1; - } - else - { - // function with unlimited number of arguments - m_iStackPos = m_iStackPos + a_iArgc + 1; - } - m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); - - SToken tok; - tok.Cmd = cmFUNC; - tok.Fun.argc = a_iArgc; - tok.Fun.ptr = a_pFun; - m_vRPN.push_back(tok); - } - - //--------------------------------------------------------------------------- - /** \brief Add a bulk function to bytecode. - - \param a_iArgc Number of arguments, negative numbers indicate multiarg functions. - \param a_pFun Pointer to function callback. - */ - void ParserByteCode::AddBulkFun(generic_fun_type a_pFun, int a_iArgc) - { - m_iStackPos = m_iStackPos - a_iArgc + 1; - m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); - - SToken tok; - tok.Cmd = cmFUNC_BULK; - tok.Fun.argc = a_iArgc; - tok.Fun.ptr = a_pFun; - m_vRPN.push_back(tok); - } - - //--------------------------------------------------------------------------- - /** \brief Add Strung function entry to the parser bytecode. - \throw nothrow - - A string function entry consists of the stack position of the return value, - followed by a cmSTRFUNC code, the function pointer and an index into the - string buffer maintained by the parser. - */ - void ParserByteCode::AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx) - { - m_iStackPos = m_iStackPos - a_iArgc + 1; - - SToken tok; - tok.Cmd = cmFUNC_STR; - tok.Fun.argc = a_iArgc; - tok.Fun.idx = a_iIdx; - tok.Fun.ptr = a_pFun; - m_vRPN.push_back(tok); - - m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); - } - - //--------------------------------------------------------------------------- - /** \brief Add end marker to bytecode. - - \throw nothrow - */ - void ParserByteCode::Finalize() - { - SToken tok; - tok.Cmd = cmEND; - m_vRPN.push_back(tok); - rpn_type(m_vRPN).swap(m_vRPN); // shrink bytecode vector to fit - - // Determine the if-then-else jump offsets - ParserStack stIf, stElse; - int idx; - for (int i=0; i<(int)m_vRPN.size(); ++i) - { - switch(m_vRPN[i].Cmd) - { - case cmIF: - stIf.push(i); - break; - - case cmELSE: - stElse.push(i); - idx = stIf.pop(); - m_vRPN[idx].Oprt.offset = i - idx; - break; - - case cmENDIF: - idx = stElse.pop(); - m_vRPN[idx].Oprt.offset = i - idx; - break; - - default: - break; - } - } - } - - //--------------------------------------------------------------------------- - const SToken* ParserByteCode::GetBase() const - { - if (m_vRPN.size()==0) - throw ParserError(ecINTERNAL_ERROR); - else - return &m_vRPN[0]; - } - - //--------------------------------------------------------------------------- - std::size_t ParserByteCode::GetMaxStackSize() const - { - return m_iMaxStackSize+1; - } - - //--------------------------------------------------------------------------- - /** \brief Returns the number of entries in the bytecode. */ - std::size_t ParserByteCode::GetSize() const - { - return m_vRPN.size(); - } - - //--------------------------------------------------------------------------- - /** \brief Delete the bytecode. - - \throw nothrow - - The name of this function is a violation of my own coding guidelines - but this way it's more in line with the STL functions thus more - intuitive. - */ - void ParserByteCode::clear() - { - m_vRPN.clear(); - m_iStackPos = 0; - m_iMaxStackSize = 0; - } - - //--------------------------------------------------------------------------- - /** \brief Dump bytecode (for debugging only!). */ - void ParserByteCode::AsciiDump() - { - if (!m_vRPN.size()) - { - mu::console() << _T("No bytecode available\n"); - return; - } - - mu::console() << _T("Number of RPN tokens:") << (int)m_vRPN.size() << _T("\n"); - for (std::size_t i=0; i \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2004-2011 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "muParserCallback.h" - -/** \file - \brief Implementation of the parser callback class. -*/ - - -namespace mu -{ - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type0 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(0) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec, ECmdCode a_iCode) - :m_pFun((void*)a_pFun) - ,m_iArgc(1) - ,m_iPri(a_iPrec) - ,m_eOprtAsct(oaNONE) - ,m_iCode(a_iCode) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - /** \brief Constructor for constructing function callbacks taking two arguments. - \throw nothrow - */ - ParserCallback::ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(2) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - /** \brief Constructor for constructing binary operator callbacks. - \param a_pFun Pointer to a static function taking two arguments - \param a_bAllowOpti A flag indicating this function can be optimized - \param a_iPrec The operator precedence - \param a_eOprtAsct The operators associativity - \throw nothrow - */ - ParserCallback::ParserCallback(fun_type2 a_pFun, - bool a_bAllowOpti, - int a_iPrec, - EOprtAssociativity a_eOprtAsct) - :m_pFun((void*)a_pFun) - ,m_iArgc(2) - ,m_iPri(a_iPrec) - ,m_eOprtAsct(a_eOprtAsct) - ,m_iCode(cmOPRT_BIN) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type3 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(3) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type4 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(4) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type5 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(5) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type6 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(6) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type7 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(7) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type8 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(8) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type9 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(9) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(10) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type0 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(0) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type1 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(1) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - /** \brief Constructor for constructing function callbacks taking two arguments. - \throw nothrow - */ - ParserCallback::ParserCallback(bulkfun_type2 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(2) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type3 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(3) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type4 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(4) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type5 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(5) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type6 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(6) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type7 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(7) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type8 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(8) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type9 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(9) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(10) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(multfun_type a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(-1) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(0) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_STR) - ,m_iType(tpSTR) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(1) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_STR) - ,m_iType(tpSTR) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(2) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_STR) - ,m_iType(tpSTR) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - /** \brief Default constructor. - \throw nothrow - */ - ParserCallback::ParserCallback() - :m_pFun(0) - ,m_iArgc(0) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmUNKNOWN) - ,m_iType(tpVOID) - ,m_bAllowOpti(0) - {} - - - //--------------------------------------------------------------------------- - /** \brief Copy constructor. - \throw nothrow - */ - ParserCallback::ParserCallback(const ParserCallback &ref) - { - m_pFun = ref.m_pFun; - m_iArgc = ref.m_iArgc; - m_bAllowOpti = ref.m_bAllowOpti; - m_iCode = ref.m_iCode; - m_iType = ref.m_iType; - m_iPri = ref.m_iPri; - m_eOprtAsct = ref.m_eOprtAsct; - } - - //--------------------------------------------------------------------------- - /** \brief Clone this instance and return a pointer to the new instance. */ - ParserCallback* ParserCallback::Clone() const - { - return new ParserCallback(*this); - } - - //--------------------------------------------------------------------------- - /** \brief Return tru if the function is conservative. - - Conservative functions return always the same result for the same argument. - \throw nothrow - */ - bool ParserCallback::IsOptimizable() const - { - return m_bAllowOpti; - } - - //--------------------------------------------------------------------------- - /** \brief Get the callback address for the parser function. - - The type of the address is void. It needs to be recasted according to the - argument number to the right type. - - \throw nothrow - \return #pFun - */ - void* ParserCallback::GetAddr() const - { - return m_pFun; - } - - //--------------------------------------------------------------------------- - /** \brief Return the callback code. */ - ECmdCode ParserCallback::GetCode() const - { - return m_iCode; - } - - //--------------------------------------------------------------------------- - ETypeCode ParserCallback::GetType() const - { - return m_iType; - } - - - //--------------------------------------------------------------------------- - /** \brief Return the operator precedence. - \throw nothrown - - Only valid if the callback token is an operator token (binary or infix). - */ - int ParserCallback::GetPri() const - { - return m_iPri; - } - - //--------------------------------------------------------------------------- - /** \brief Return the operators associativity. - \throw nothrown - - Only valid if the callback token is a binary operator token. - */ - EOprtAssociativity ParserCallback::GetAssociativity() const - { - return m_eOprtAsct; - } - - //--------------------------------------------------------------------------- - /** \brief Returns the number of function Arguments. */ - int ParserCallback::GetArgc() const - { - return m_iArgc; - } -} // namespace mu diff --git a/external/muparser/src/muParserDLL.cpp b/external/muparser/src/muParserDLL.cpp deleted file mode 100644 index d91a1582..00000000 --- a/external/muparser/src/muParserDLL.cpp +++ /dev/null @@ -1,1096 +0,0 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2004-2011 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -#if defined(MUPARSER_DLL) - -#if defined(_WIN32) -#define WIN32_LEAN_AND_MEAN -#include -#endif - -#include "muParserDLL.h" -#include "muParser.h" -#include "muParserInt.h" -#include "muParserError.h" - - -#define MU_TRY \ - try \ - { - -#define MU_CATCH \ - } \ - catch (muError_t &e) \ - { \ - ParserTag *pTag = static_cast(a_hParser); \ - pTag->exc = e; \ - pTag->bError = true; \ -if (pTag->errHandler) \ - (pTag->errHandler)(a_hParser); \ - } \ - catch (...) \ - { \ - ParserTag *pTag = static_cast(a_hParser); \ - pTag->exc = muError_t(mu::ecINTERNAL_ERROR); \ - pTag->bError = true; \ -if (pTag->errHandler) \ - (pTag->errHandler)(a_hParser); \ - } - -/** \file - \brief This file contains the implementation of the DLL interface of muparser. - */ - -//--------------------------------------------------------------------------- -// private types -typedef mu::ParserBase::exception_type muError_t; -typedef mu::ParserBase muParser_t; - -int g_nBulkSize; - -//--------------------------------------------------------------------------- -class ParserTag -{ -public: - ParserTag(int nType) - :pParser((nType == muBASETYPE_FLOAT) ? (mu::ParserBase*)new mu::Parser() : - (nType == muBASETYPE_INT) ? (mu::ParserBase*)new mu::ParserInt() : NULL) - , exc() - , errHandler(NULL) - , bError(false) - , m_nParserType(nType) - {} - - ~ParserTag() - { - delete pParser; - } - - mu::ParserBase *pParser; - mu::ParserBase::exception_type exc; - muErrorHandler_t errHandler; - bool bError; - -private: - ParserTag(const ParserTag &ref); - ParserTag& operator=(const ParserTag &ref); - - int m_nParserType; -}; - -static muChar_t s_tmpOutBuf[2048]; - -//--------------------------------------------------------------------------- -// -// -// unexported functions -// -// -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -muParser_t* AsParser(muParserHandle_t a_hParser) -{ - return static_cast(a_hParser)->pParser; -} - -//--------------------------------------------------------------------------- -ParserTag* AsParserTag(muParserHandle_t a_hParser) -{ - return static_cast(a_hParser); -} - -//--------------------------------------------------------------------------- -#if defined(_WIN32) -#define _CRT_SECURE_NO_DEPRECATE - -BOOL APIENTRY DllMain(HANDLE /*hModule*/, - DWORD ul_reason_for_call, - LPVOID /*lpReserved*/) -{ - switch (ul_reason_for_call) - { - case DLL_PROCESS_ATTACH: - break; - - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: - break; - } - - return TRUE; -} - -#endif - -//--------------------------------------------------------------------------- -// -// -// exported functions -// -// -//--------------------------------------------------------------------------- - -API_EXPORT(void) mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void *pUserData) -{ - MU_TRY - muParser_t* p(AsParser(a_hParser)); - p->SetVarFactory(a_pFactory, pUserData); - MU_CATCH -} - -//--------------------------------------------------------------------------- -/** \brief Create a new Parser instance and return its handle. -*/ -API_EXPORT(muParserHandle_t) mupCreate(int nBaseType) -{ - switch (nBaseType) - { - case muBASETYPE_FLOAT: return (void*)(new ParserTag(muBASETYPE_FLOAT)); - case muBASETYPE_INT: return (void*)(new ParserTag(muBASETYPE_INT)); - default: return NULL; - } -} - -//--------------------------------------------------------------------------- -/** \brief Release the parser instance related with a parser handle. -*/ -API_EXPORT(void) mupRelease(muParserHandle_t a_hParser) -{ - MU_TRY - ParserTag* p = static_cast(a_hParser); - delete p; - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(const muChar_t*) mupGetVersion(muParserHandle_t a_hParser) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - -#ifndef _UNICODE - sprintf(s_tmpOutBuf, "%s", p->GetVersion().c_str()); -#else - wsprintf(s_tmpOutBuf, _T("%s"), p->GetVersion().c_str()); -#endif - - return s_tmpOutBuf; - MU_CATCH - - return _T(""); -} - -//--------------------------------------------------------------------------- -/** \brief Evaluate the expression. -*/ -API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - return p->Eval(); - MU_CATCH - - return 0; -} - -//--------------------------------------------------------------------------- -API_EXPORT(muFloat_t*) mupEvalMulti(muParserHandle_t a_hParser, int *nNum) -{ - MU_TRY - assert(nNum != NULL); - - muParser_t* const p(AsParser(a_hParser)); - return p->Eval(*nNum); - MU_CATCH - - return 0; -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupEvalBulk(muParserHandle_t a_hParser, muFloat_t *a_res, int nSize) -{ - MU_TRY - muParser_t* p(AsParser(a_hParser)); - p->Eval(a_res, nSize); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupSetExpr(muParserHandle_t a_hParser, const muChar_t* a_szExpr) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->SetExpr(a_szExpr); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupRemoveVar(muParserHandle_t a_hParser, const muChar_t* a_szName) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->RemoveVar(a_szName); - MU_CATCH -} - -//--------------------------------------------------------------------------- -/** \brief Release all parser variables. - \param a_hParser Handle to the parser instance. - */ -API_EXPORT(void) mupClearVar(muParserHandle_t a_hParser) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->ClearVar(); - MU_CATCH -} - -//--------------------------------------------------------------------------- -/** \brief Release all parser variables. - \param a_hParser Handle to the parser instance. - */ -API_EXPORT(void) mupClearConst(muParserHandle_t a_hParser) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->ClearConst(); - MU_CATCH -} - -//--------------------------------------------------------------------------- -/** \brief Clear all user defined operators. - \param a_hParser Handle to the parser instance. - */ -API_EXPORT(void) mupClearOprt(muParserHandle_t a_hParser) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->ClearOprt(); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupClearFun(muParserHandle_t a_hParser) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->ClearFun(); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineFun0(muParserHandle_t a_hParser, - const muChar_t* a_szName, - muFun0_t a_pFun, - muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineFun1(muParserHandle_t a_hParser, - const muChar_t* a_szName, - muFun1_t a_pFun, - muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineFun2(muParserHandle_t a_hParser, - const muChar_t* a_szName, - muFun2_t a_pFun, - muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineFun3(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muFun3_t a_pFun, - muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineFun4(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muFun4_t a_pFun, - muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineFun5(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muFun5_t a_pFun, - muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineFun6(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muFun6_t a_pFun, - muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineFun7(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muFun7_t a_pFun, - muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineFun8(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muFun8_t a_pFun, - muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineFun9(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muFun9_t a_pFun, - muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineFun10(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muFun10_t a_pFun, - muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineBulkFun0(muParserHandle_t a_hParser, - const muChar_t* a_szName, - muBulkFun0_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineBulkFun1(muParserHandle_t a_hParser, - const muChar_t* a_szName, - muBulkFun1_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineBulkFun2(muParserHandle_t a_hParser, - const muChar_t* a_szName, - muBulkFun2_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineBulkFun3(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muBulkFun3_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineBulkFun4(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muBulkFun4_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineBulkFun5(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muBulkFun5_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineBulkFun6(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muBulkFun6_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineBulkFun7(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muBulkFun7_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineBulkFun8(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muBulkFun8_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineBulkFun9(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muBulkFun9_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineBulkFun10(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muBulkFun10_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineStrFun1(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muStrFun1_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineStrFun2(muParserHandle_t a_hParser, - const muChar_t* a_szName, - muStrFun2_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineStrFun3(muParserHandle_t a_hParser, - const muChar_t* a_szName, - muStrFun3_t a_pFun) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineMultFun(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muMultFun_t a_pFun, - muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineOprt(muParserHandle_t a_hParser, - const muChar_t* a_szName, - muFun2_t a_pFun, - muInt_t a_nPrec, - muInt_t a_nOprtAsct, - muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineOprt(a_szName, - a_pFun, - a_nPrec, - (mu::EOprtAssociativity)a_nOprtAsct, - a_bAllowOpt != 0); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineVar(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muFloat_t *a_pVar) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineVar(a_szName, a_pVar); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineBulkVar(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muFloat_t *a_pVar) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineVar(a_szName, a_pVar); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineConst(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muFloat_t a_fVal) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineConst(a_szName, a_fVal); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineStrConst(muParserHandle_t a_hParser, - const muChar_t *a_szName, - const muChar_t *a_szVal) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineStrConst(a_szName, a_szVal); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(const muChar_t*) mupGetExpr(muParserHandle_t a_hParser) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - - // C# explodes when pMsg is returned directly. For some reason it can't access - // the memory where the message lies directly. -#ifndef _UNICODE - sprintf(s_tmpOutBuf, "%s", p->GetExpr().c_str()); -#else - wsprintf(s_tmpOutBuf, _T("%s"), p->GetExpr().c_str()); -#endif - - return s_tmpOutBuf; - - MU_CATCH - - return _T(""); -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefinePostfixOprt(muParserHandle_t a_hParser, - const muChar_t* a_szName, - muFun1_t a_pOprt, - muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefinePostfixOprt(a_szName, a_pOprt, a_bAllowOpt != 0); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineInfixOprt(muParserHandle_t a_hParser, - const muChar_t* a_szName, - muFun1_t a_pOprt, - muBool_t a_bAllowOpt) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineInfixOprt(a_szName, a_pOprt, a_bAllowOpt != 0); - MU_CATCH -} - -// Define character sets for identifiers -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineNameChars(muParserHandle_t a_hParser, - const muChar_t* a_szCharset) -{ - muParser_t* const p(AsParser(a_hParser)); - p->DefineNameChars(a_szCharset); -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineOprtChars(muParserHandle_t a_hParser, - const muChar_t* a_szCharset) -{ - muParser_t* const p(AsParser(a_hParser)); - p->DefineOprtChars(a_szCharset); -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineInfixOprtChars(muParserHandle_t a_hParser, - const muChar_t *a_szCharset) -{ - muParser_t* const p(AsParser(a_hParser)); - p->DefineInfixOprtChars(a_szCharset); -} - -//--------------------------------------------------------------------------- -/** \brief Get the number of variables defined in the parser. - \param a_hParser [in] Must be a valid parser handle. - \return The number of used variables. - \sa mupGetExprVar - */ -API_EXPORT(int) mupGetVarNum(muParserHandle_t a_hParser) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - const mu::varmap_type VarMap = p->GetVar(); - return (int)VarMap.size(); - MU_CATCH - - return 0; // never reached -} - -//--------------------------------------------------------------------------- -/** \brief Return a variable that is used in an expression. - \param a_hParser [in] A valid parser handle. - \param a_iVar [in] The index of the variable to return. - \param a_szName [out] Pointer to the variable name. - \param a_pVar [out] Pointer to the variable. - \throw nothrow - - Prior to calling this function call mupGetExprVarNum in order to get the - number of variables in the expression. If the parameter a_iVar is greater - than the number of variables both a_szName and a_pVar will be set to zero. - As a side effect this function will trigger an internal calculation of the - expression undefined variables will be set to zero during this calculation. - During the calculation user defined callback functions present in the expression - will be called, this is unavoidable. - */ -API_EXPORT(void) mupGetVar(muParserHandle_t a_hParser, - unsigned a_iVar, - const muChar_t **a_szName, - muFloat_t **a_pVar) -{ - // A static buffer is needed for the name since i cant return the - // pointer from the map. - static muChar_t szName[1024]; - - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - const mu::varmap_type VarMap = p->GetVar(); - - if (a_iVar >= VarMap.size()) - { - *a_szName = 0; - *a_pVar = 0; - return; - } - mu::varmap_type::const_iterator item; - - item = VarMap.begin(); - for (unsigned i = 0; i < a_iVar; ++i) - ++item; - -#ifndef _UNICODE - strncpy(szName, item->first.c_str(), sizeof(szName)); -#else - wcsncpy(szName, item->first.c_str(), sizeof(szName)); -#endif - - szName[sizeof(szName)-1] = 0; - - *a_szName = &szName[0]; - *a_pVar = item->second; - return; - - MU_CATCH - - *a_szName = 0; - *a_pVar = 0; -} - -//--------------------------------------------------------------------------- -/** \brief Get the number of variables used in the expression currently set in the parser. - \param a_hParser [in] Must be a valid parser handle. - \return The number of used variables. - \sa mupGetExprVar - */ -API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - const mu::varmap_type VarMap = p->GetUsedVar(); - return (int)VarMap.size(); - MU_CATCH - - return 0; // never reached -} - -//--------------------------------------------------------------------------- -/** \brief Return a variable that is used in an expression. - - Prior to calling this function call mupGetExprVarNum in order to get the - number of variables in the expression. If the parameter a_iVar is greater - than the number of variables both a_szName and a_pVar will be set to zero. - As a side effect this function will trigger an internal calculation of the - expression undefined variables will be set to zero during this calculation. - During the calculation user defined callback functions present in the expression - will be called, this is unavoidable. - - \param a_hParser [in] A valid parser handle. - \param a_iVar [in] The index of the variable to return. - \param a_szName [out] Pointer to the variable name. - \param a_pVar [out] Pointer to the variable. - \throw nothrow - */ -API_EXPORT(void) mupGetExprVar(muParserHandle_t a_hParser, - unsigned a_iVar, - const muChar_t **a_szName, - muFloat_t **a_pVar) -{ - // A static buffer is needed for the name since i cant return the - // pointer from the map. - static muChar_t szName[1024]; - - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - const mu::varmap_type VarMap = p->GetUsedVar(); - - if (a_iVar >= VarMap.size()) - { - *a_szName = 0; - *a_pVar = 0; - return; - } - mu::varmap_type::const_iterator item; - - item = VarMap.begin(); - for (unsigned i = 0; i < a_iVar; ++i) - ++item; - -#ifndef _UNICODE - strncpy(szName, item->first.c_str(), sizeof(szName)); -#else - wcsncpy(szName, item->first.c_str(), sizeof(szName)); -#endif - - szName[sizeof(szName)-1] = 0; - - *a_szName = &szName[0]; - *a_pVar = item->second; - return; - - MU_CATCH - - *a_szName = 0; - *a_pVar = 0; -} - -//--------------------------------------------------------------------------- -/** \brief Return the number of constants defined in a parser. */ -API_EXPORT(int) mupGetConstNum(muParserHandle_t a_hParser) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - const mu::valmap_type ValMap = p->GetConst(); - return (int)ValMap.size(); - MU_CATCH - - return 0; // never reached -} - -//----------------------------------------------------------------------------------------------------- -API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->SetArgSep(cArgSep); - MU_CATCH -} - -//----------------------------------------------------------------------------------------------------- -API_EXPORT(void) mupResetLocale(muParserHandle_t a_hParser) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->ResetLocale(); - MU_CATCH -} - -//----------------------------------------------------------------------------------------------------- -API_EXPORT(void) mupSetDecSep(muParserHandle_t a_hParser, const muChar_t cDecSep) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->SetDecSep(cDecSep); - MU_CATCH -} - -//----------------------------------------------------------------------------------------------------- -API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t cThousandsSep) -{ - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->SetThousandsSep(cThousandsSep); - MU_CATCH -} - -//--------------------------------------------------------------------------- -/** \brief Retrieve name and value of a single parser constant. - \param a_hParser [in] a valid parser handle - \param a_iVar [in] Index of the constant to query - \param a_pszName [out] pointer to a null terminated string with the constant name - \param [out] The constant value - */ -API_EXPORT(void) mupGetConst(muParserHandle_t a_hParser, - unsigned a_iVar, - const muChar_t **a_pszName, - muFloat_t *a_fVal) -{ - // A static buffer is needed for the name since i cant return the - // pointer from the map. - static muChar_t szName[1024]; - - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - const mu::valmap_type ValMap = p->GetConst(); - - if (a_iVar >= ValMap.size()) - { - *a_pszName = 0; - *a_fVal = 0; - return; - } - - mu::valmap_type::const_iterator item; - item = ValMap.begin(); - for (unsigned i = 0; i < a_iVar; ++i) - ++item; - -#ifndef _UNICODE - strncpy(szName, item->first.c_str(), sizeof(szName)); -#else - wcsncpy(szName, item->first.c_str(), sizeof(szName)); -#endif - - szName[sizeof(szName)-1] = 0; - - *a_pszName = &szName[0]; - *a_fVal = item->second; - return; - - MU_CATCH - - *a_pszName = 0; - *a_fVal = 0; -} - -//--------------------------------------------------------------------------- -/** \brief Add a custom value recognition function. -*/ -API_EXPORT(void) mupAddValIdent(muParserHandle_t a_hParser, - muIdentFun_t a_pFun) -{ - MU_TRY - muParser_t* p(AsParser(a_hParser)); - p->AddValIdent(a_pFun); - MU_CATCH -} - -//--------------------------------------------------------------------------- -/** \brief Query if an error occurred. - - After querying the internal error bit will be reset. So a consecutive call - will return false. - */ -API_EXPORT(muBool_t) mupError(muParserHandle_t a_hParser) -{ - bool bError(AsParserTag(a_hParser)->bError); - AsParserTag(a_hParser)->bError = false; - return bError; -} - -//--------------------------------------------------------------------------- -/** \brief Reset the internal error flag. -*/ -API_EXPORT(void) mupErrorReset(muParserHandle_t a_hParser) -{ - AsParserTag(a_hParser)->bError = false; -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupSetErrorHandler(muParserHandle_t a_hParser, muErrorHandler_t a_pHandler) -{ - AsParserTag(a_hParser)->errHandler = a_pHandler; -} - -//--------------------------------------------------------------------------- -/** \brief Return the message associated with the last error. -*/ -API_EXPORT(const muChar_t*) mupGetErrorMsg(muParserHandle_t a_hParser) -{ - ParserTag* const p(AsParserTag(a_hParser)); - const muChar_t *pMsg = p->exc.GetMsg().c_str(); - - // C# explodes when pMsg is returned directly. For some reason it can't access - // the memory where the message lies directly. -#ifndef _UNICODE - sprintf(s_tmpOutBuf, "%s", pMsg); -#else - wsprintf(s_tmpOutBuf, _T("%s"), pMsg); -#endif - - return s_tmpOutBuf; -} - -//--------------------------------------------------------------------------- -/** \brief Return the message associated with the last error. -*/ -API_EXPORT(const muChar_t*) mupGetErrorToken(muParserHandle_t a_hParser) -{ - ParserTag* const p(AsParserTag(a_hParser)); - const muChar_t *pToken = p->exc.GetToken().c_str(); - - // C# explodes when pMsg is returned directly. For some reason it can't access - // the memory where the message lies directly. -#ifndef _UNICODE - sprintf(s_tmpOutBuf, "%s", pToken); -#else - wsprintf(s_tmpOutBuf, _T("%s"), pToken); -#endif - - return s_tmpOutBuf; -} - -//--------------------------------------------------------------------------- -/** \brief Return the code associated with the last error. -*/ -API_EXPORT(int) mupGetErrorCode(muParserHandle_t a_hParser) -{ - return AsParserTag(a_hParser)->exc.GetCode(); -} - -//--------------------------------------------------------------------------- -/** \brief Return the position associated with the last error. */ -API_EXPORT(int) mupGetErrorPos(muParserHandle_t a_hParser) -{ - return (int)AsParserTag(a_hParser)->exc.GetPos(); -} - -////----------------------------------------------------------------------------------------------------- -//API_EXPORT(const muChar_t*) mupGetErrorExpr(muParserHandle_t a_hParser) -//{ -// return AsParserTag(a_hParser)->exc.GetExpr().c_str(); -//} - -//----------------------------------------------------------------------------------------------------- -API_EXPORT(muFloat_t*) mupCreateVar() -{ - return new muFloat_t(0); -} - -//----------------------------------------------------------------------------------------------------- -API_EXPORT(void) mupReleaseVar(muFloat_t *ptr) -{ - delete ptr; -} - -#endif // MUPARSER_DLL diff --git a/external/muparser/src/muParserError.cpp b/external/muparser/src/muParserError.cpp deleted file mode 100644 index 76a05cc4..00000000 --- a/external/muparser/src/muParserError.cpp +++ /dev/null @@ -1,337 +0,0 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2011 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -#include "muParserError.h" - - -namespace mu -{ - const ParserErrorMsg ParserErrorMsg::m_Instance; - - //------------------------------------------------------------------------------ - const ParserErrorMsg& ParserErrorMsg::Instance() - { - return m_Instance; - } - - //------------------------------------------------------------------------------ - string_type ParserErrorMsg::operator[](unsigned a_iIdx) const - { - return (a_iIdx \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2011 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "muParserInt.h" - -#include -#include -#include - -using namespace std; - -/** \file - \brief Implementation of a parser using integer value. -*/ - -/** \brief Namespace for mathematical applications. */ -namespace mu -{ -value_type ParserInt::Abs(value_type v) { return (value_type)Round(fabs((double)v)); } -value_type ParserInt::Sign(value_type v) { return (Round(v)<0) ? -1 : (Round(v)>0) ? 1 : 0; } -value_type ParserInt::Ite(value_type v1, - value_type v2, - value_type v3) { return (Round(v1)==1) ? Round(v2) : Round(v3); } -value_type ParserInt::Add(value_type v1, value_type v2) { return Round(v1) + Round(v2); } -value_type ParserInt::Sub(value_type v1, value_type v2) { return Round(v1) - Round(v2); } -value_type ParserInt::Mul(value_type v1, value_type v2) { return Round(v1) * Round(v2); } -value_type ParserInt::Div(value_type v1, value_type v2) { return Round(v1) / Round(v2); } -value_type ParserInt::Mod(value_type v1, value_type v2) { return Round(v1) % Round(v2); } -value_type ParserInt::Shr(value_type v1, value_type v2) { return Round(v1) >> Round(v2); } -value_type ParserInt::Shl(value_type v1, value_type v2) { return Round(v1) << Round(v2); } -value_type ParserInt::LogAnd(value_type v1, value_type v2) { return Round(v1) & Round(v2); } -value_type ParserInt::LogOr(value_type v1, value_type v2) { return Round(v1) | Round(v2); } -value_type ParserInt::And(value_type v1, value_type v2) { return Round(v1) && Round(v2); } -value_type ParserInt::Or(value_type v1, value_type v2) { return Round(v1) || Round(v2); } -value_type ParserInt::Less(value_type v1, value_type v2) { return Round(v1) < Round(v2); } -value_type ParserInt::Greater(value_type v1, value_type v2) { return Round(v1) > Round(v2); } -value_type ParserInt::LessEq(value_type v1, value_type v2) { return Round(v1) <= Round(v2); } -value_type ParserInt::GreaterEq(value_type v1, value_type v2) { return Round(v1) >= Round(v2); } -value_type ParserInt::Equal(value_type v1, value_type v2) { return Round(v1) == Round(v2); } -value_type ParserInt::NotEqual(value_type v1, value_type v2) { return Round(v1) != Round(v2); } -value_type ParserInt::Not(value_type v) { return !Round(v); } - -value_type ParserInt::Pow(value_type v1, value_type v2) -{ - return std::pow((double)Round(v1), (double)Round(v2)); -} - -//--------------------------------------------------------------------------- -// Unary operator Callbacks: Infix operators -value_type ParserInt::UnaryMinus(value_type v) -{ - return -Round(v); -} - -//--------------------------------------------------------------------------- -value_type ParserInt::Sum(const value_type* a_afArg, int a_iArgc) -{ - if (!a_iArgc) - throw ParserError(_T("too few arguments for function sum.")); - - value_type fRes=0; - for (int i=0; i> iVal; - if (stream.fail()) - return 0; - - stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading - if (stream.fail()) - iEnd = stream.str().length(); - - if (iEnd==(stringstream_type::pos_type)-1) - return 0; - - *a_iPos += (int)iEnd; - *a_fVal = (value_type)iVal; - return 1; -} - -//--------------------------------------------------------------------------- -/** \brief Check a given position in the expression for the presence of - a hex value. - \param a_szExpr Pointer to the expression string - \param [in/out] a_iPos Pointer to an integer value holding the current parsing - position in the expression. - \param [out] a_fVal Pointer to the position where the detected value shall be stored. - - Hey values must be prefixed with "0x" in order to be detected properly. -*/ -int ParserInt::IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal) -{ - if (a_szExpr[1]==0 || (a_szExpr[0]!='0' || a_szExpr[1]!='x') ) - return 0; - - unsigned iVal(0); - - // New code based on streams for UNICODE compliance: - stringstream_type::pos_type nPos(0); - stringstream_type ss(a_szExpr + 2); - ss >> std::hex >> iVal; - nPos = ss.tellg(); - - if (nPos==(stringstream_type::pos_type)0) - return 1; - - *a_iPos += (int)(2 + nPos); - *a_fVal = (value_type)iVal; - return 1; -} - -//--------------------------------------------------------------------------- -int ParserInt::IsBinVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal) -{ - if (a_szExpr[0]!='#') - return 0; - - unsigned iVal(0), - iBits(sizeof(iVal)*8), - i(0); - - for (i=0; (a_szExpr[i+1]=='0' || a_szExpr[i+1]=='1') && i> (iBits-i) ); - *a_iPos += i+1; - - return 1; -} - -//--------------------------------------------------------------------------- -/** \brief Constructor. - - Call ParserBase class constructor and trigger Function, Operator and Constant initialization. -*/ -ParserInt::ParserInt() - :ParserBase() -{ - AddValIdent(IsVal); // lowest priority - AddValIdent(IsBinVal); - AddValIdent(IsHexVal); // highest priority - - InitCharSets(); - InitFun(); - InitOprt(); -} - -//--------------------------------------------------------------------------- -void ParserInt::InitConst() -{ -} - -//--------------------------------------------------------------------------- -void ParserInt::InitCharSets() -{ - DefineNameChars( _T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") ); - DefineOprtChars( _T("+-*^/?<>=!%&|~'_") ); - DefineInfixOprtChars( _T("/+-*^?<>=!%&|~'_") ); -} - -//--------------------------------------------------------------------------- -/** \brief Initialize the default functions. */ -void ParserInt::InitFun() -{ - DefineFun( _T("sign"), Sign); - DefineFun( _T("abs"), Abs); - DefineFun( _T("if"), Ite); - DefineFun( _T("sum"), Sum); - DefineFun( _T("min"), Min); - DefineFun( _T("max"), Max); -} - -//--------------------------------------------------------------------------- -/** \brief Initialize operators. */ -void ParserInt::InitOprt() -{ - // disable all built in operators, not all of them useful for integer numbers - // (they don't do rounding of values) - EnableBuiltInOprt(false); - - // Disable all built in operators, they wont work with integer numbers - // since they are designed for floating point numbers - DefineInfixOprt( _T("-"), UnaryMinus); - DefineInfixOprt( _T("!"), Not); - - DefineOprt( _T("&"), LogAnd, prLOGIC); - DefineOprt( _T("|"), LogOr, prLOGIC); - DefineOprt( _T("&&"), And, prLOGIC); - DefineOprt( _T("||"), Or, prLOGIC); - - DefineOprt( _T("<"), Less, prCMP); - DefineOprt( _T(">"), Greater, prCMP); - DefineOprt( _T("<="), LessEq, prCMP); - DefineOprt( _T(">="), GreaterEq, prCMP); - DefineOprt( _T("=="), Equal, prCMP); - DefineOprt( _T("!="), NotEqual, prCMP); - - DefineOprt( _T("+"), Add, prADD_SUB); - DefineOprt( _T("-"), Sub, prADD_SUB); - - DefineOprt( _T("*"), Mul, prMUL_DIV); - DefineOprt( _T("/"), Div, prMUL_DIV); - DefineOprt( _T("%"), Mod, prMUL_DIV); - - DefineOprt( _T("^"), Pow, prPOW, oaRIGHT); - DefineOprt( _T(">>"), Shr, prMUL_DIV+1); - DefineOprt( _T("<<"), Shl, prMUL_DIV+1); -} - -} // namespace mu diff --git a/external/muparser/src/muParserTest.cpp b/external/muparser/src/muParserTest.cpp deleted file mode 100644 index 3b1dec6c..00000000 --- a/external/muparser/src/muParserTest.cpp +++ /dev/null @@ -1,1552 +0,0 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2013 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "muParserTest.h" - -#include -#include -#include -#include - -#define PARSER_CONST_PI 3.141592653589793238462643 -#define PARSER_CONST_E 2.718281828459045235360287 - -using namespace std; - -/** \file - \brief This file contains the implementation of parser test cases. -*/ - -namespace mu -{ - namespace Test - { - int ParserTester::c_iCount = 0; - - //--------------------------------------------------------------------------------------------- - ParserTester::ParserTester() - :m_vTestFun() - { - AddTest(&ParserTester::TestNames); - AddTest(&ParserTester::TestSyntax); - AddTest(&ParserTester::TestPostFix); - AddTest(&ParserTester::TestInfixOprt); - AddTest(&ParserTester::TestVarConst); - AddTest(&ParserTester::TestMultiArg); - AddTest(&ParserTester::TestExpression); - AddTest(&ParserTester::TestIfThenElse); - AddTest(&ParserTester::TestInterface); - AddTest(&ParserTester::TestBinOprt); - AddTest(&ParserTester::TestException); - AddTest(&ParserTester::TestStrArg); - AddTest(&ParserTester::TestBulkMode); - - ParserTester::c_iCount = 0; - } - - //--------------------------------------------------------------------------------------------- - int ParserTester::IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal) - { - if (a_szExpr[1]==0 || (a_szExpr[0]!='0' || a_szExpr[1]!='x') ) - return 0; - - unsigned iVal(0); - - // New code based on streams for UNICODE compliance: - stringstream_type::pos_type nPos(0); - stringstream_type ss(a_szExpr + 2); - ss >> std::hex >> iVal; - nPos = ss.tellg(); - - if (nPos==(stringstream_type::pos_type)0) - return 1; - - *a_iPos += (int)(2 + nPos); - *a_fVal = (value_type)iVal; - return 1; - } - - //--------------------------------------------------------------------------------------------- - int ParserTester::TestInterface() - { - int iStat = 0; - mu::console() << _T("testing member functions..."); - - // Test RemoveVar - value_type afVal[3] = {1,2,3}; - Parser p; - - try - { - p.DefineVar( _T("a"), &afVal[0]); - p.DefineVar( _T("b"), &afVal[1]); - p.DefineVar( _T("c"), &afVal[2]); - p.SetExpr( _T("a+b+c") ); - p.Eval(); - } - catch(...) - { - iStat += 1; // this is not supposed to happen - } - - try - { - p.RemoveVar( _T("c") ); - p.Eval(); - iStat += 1; // not supposed to reach this, nonexisting variable "c" deleted... - } - catch(...) - { - // failure is expected... - } - - if (iStat==0) - mu::console() << _T("passed") << endl; - else - mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; - - return iStat; - } - - //--------------------------------------------------------------------------------------------- - int ParserTester::TestStrArg() - { - int iStat = 0; - mu::console() << _T("testing string arguments..."); - - iStat += EqnTest(_T("valueof(\"\")"), 123, true); // empty string arguments caused a crash - iStat += EqnTest(_T("valueof(\"aaa\")+valueof(\"bbb\") "), 246, true); - iStat += EqnTest(_T("2*(valueof(\"aaa\")-23)+valueof(\"bbb\")"), 323, true); - // use in expressions with variables - iStat += EqnTest(_T("a*(atof(\"10\")-b)"), 8, true); - iStat += EqnTest(_T("a-(atof(\"10\")*b)"), -19, true); - // string + numeric arguments - iStat += EqnTest(_T("strfun1(\"100\")"), 100, true); - iStat += EqnTest(_T("strfun2(\"100\",1)"), 101, true); - iStat += EqnTest(_T("strfun3(\"99\",1,2)"), 102, true); - // string constants - iStat += EqnTest(_T("atof(str1)+atof(str2)"), 3.33, true); - - if (iStat==0) - mu::console() << _T("passed") << endl; - else - mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; - - return iStat; - } - - //--------------------------------------------------------------------------------------------- - int ParserTester::TestBulkMode() - { - int iStat = 0; - mu::console() << _T("testing bulkmode..."); - -#define EQN_TEST_BULK(EXPR, R1, R2, R3, R4, PASS) \ - { \ - double res[] = { R1, R2, R3, R4 }; \ - iStat += EqnTestBulk(_T(EXPR), res, (PASS)); \ - } - - // Bulk Variables for the test: - // a: 1,2,3,4 - // b: 2,2,2,2 - // c: 3,3,3,3 - // d: 5,4,3,2 - EQN_TEST_BULK("a", 1, 1, 1, 1, false) - EQN_TEST_BULK("a", 1, 2, 3, 4, true) - EQN_TEST_BULK("b=a", 1, 2, 3, 4, true) - EQN_TEST_BULK("b=a, b*10", 10, 20, 30, 40, true) - EQN_TEST_BULK("b=a, b*10, a", 1, 2, 3, 4, true) - EQN_TEST_BULK("a+b", 3, 4, 5, 6, true) - EQN_TEST_BULK("c*(a+b)", 9, 12, 15, 18, true) -#undef EQN_TEST_BULK - - if (iStat == 0) - mu::console() << _T("passed") << endl; - else - mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; - - return iStat; - } - - //--------------------------------------------------------------------------------------------- - int ParserTester::TestBinOprt() - { - int iStat = 0; - mu::console() << _T("testing binary operators..."); - - // built in operators - // xor operator - - iStat += EqnTest(_T("a++b"), 3, true); - iStat += EqnTest(_T("a ++ b"), 3, true); - iStat += EqnTest(_T("1++2"), 3, true); - iStat += EqnTest(_T("1 ++ 2"), 3, true); - iStat += EqnTest(_T("a add b"), 3, true); - iStat += EqnTest(_T("1 add 2"), 3, true); - iStat += EqnTest(_T("aa"), 1, true); - iStat += EqnTest(_T("a>a"), 0, true); - iStat += EqnTest(_T("aa"), 0, true); - iStat += EqnTest(_T("a<=a"), 1, true); - iStat += EqnTest(_T("a<=b"), 1, true); - iStat += EqnTest(_T("b<=a"), 0, true); - iStat += EqnTest(_T("a>=a"), 1, true); - iStat += EqnTest(_T("b>=a"), 1, true); - iStat += EqnTest(_T("a>=b"), 0, true); - - // Test logical operators, especially if user defined "&" and the internal "&&" collide - iStat += EqnTest(_T("1 && 1"), 1, true); - iStat += EqnTest(_T("1 && 0"), 0, true); - iStat += EqnTest(_T("(aa)"), 1, true); - iStat += EqnTest(_T("(ab)"), 0, true); - //iStat += EqnTest(_T("12 and 255"), 12, true); - //iStat += EqnTest(_T("12 and 0"), 0, true); - iStat += EqnTest(_T("12 & 255"), 12, true); - iStat += EqnTest(_T("12 & 0"), 0, true); - iStat += EqnTest(_T("12&255"), 12, true); - iStat += EqnTest(_T("12&0"), 0, true); - - // Assignment operator - iStat += EqnTest(_T("a = b"), 2, true); - iStat += EqnTest(_T("a = sin(b)"), 0.909297, true); - iStat += EqnTest(_T("a = 1+sin(b)"), 1.909297, true); - iStat += EqnTest(_T("(a=b)*2"), 4, true); - iStat += EqnTest(_T("2*(a=b)"), 4, true); - iStat += EqnTest(_T("2*(a=b+1)"), 6, true); - iStat += EqnTest(_T("(a=b+1)*2"), 6, true); - iStat += EqnTest(_T("a=c, a*10"), 30, true); - - iStat += EqnTest(_T("2^2^3"), 256, true); - iStat += EqnTest(_T("1/2/3"), 1.0/6.0, true); - - // reference: http://www.wolframalpha.com/input/?i=3%2B4*2%2F%281-5%29^2^3 - iStat += EqnTest(_T("3+4*2/(1-5)^2^3"), 3.0001220703125, true); - - // Test user defined binary operators - iStat += EqnTestInt(_T("1 | 2"), 3, true); - iStat += EqnTestInt(_T("1 || 2"), 1, true); - iStat += EqnTestInt(_T("123 & 456"), 72, true); - iStat += EqnTestInt(_T("(123 & 456) % 10"), 2, true); - iStat += EqnTestInt(_T("1 && 0"), 0, true); - iStat += EqnTestInt(_T("123 && 456"), 1, true); - iStat += EqnTestInt(_T("1 << 3"), 8, true); - iStat += EqnTestInt(_T("8 >> 3"), 1, true); - iStat += EqnTestInt(_T("9 / 4"), 2, true); - iStat += EqnTestInt(_T("9 % 4"), 1, true); - iStat += EqnTestInt(_T("if(5%2,1,0)"), 1, true); - iStat += EqnTestInt(_T("if(4%2,1,0)"), 0, true); - iStat += EqnTestInt(_T("-10+1"), -9, true); - iStat += EqnTestInt(_T("1+2*3"), 7, true); - iStat += EqnTestInt(_T("const1 != const2"), 1, true); - iStat += EqnTestInt(_T("const1 != const2"), 0, false); - iStat += EqnTestInt(_T("const1 == const2"), 0, true); - iStat += EqnTestInt(_T("const1 == 1"), 1, true); - iStat += EqnTestInt(_T("10*(const1 == 1)"), 10, true); - iStat += EqnTestInt(_T("2*(const1 | const2)"), 6, true); - iStat += EqnTestInt(_T("2*(const1 | const2)"), 7, false); - iStat += EqnTestInt(_T("const1 < const2"), 1, true); - iStat += EqnTestInt(_T("const2 > const1"), 1, true); - iStat += EqnTestInt(_T("const1 <= 1"), 1, true); - iStat += EqnTestInt(_T("const2 >= 2"), 1, true); - iStat += EqnTestInt(_T("2*(const1 + const2)"), 6, true); - iStat += EqnTestInt(_T("2*(const1 - const2)"), -2, true); - iStat += EqnTestInt(_T("a != b"), 1, true); - iStat += EqnTestInt(_T("a != b"), 0, false); - iStat += EqnTestInt(_T("a == b"), 0, true); - iStat += EqnTestInt(_T("a == 1"), 1, true); - iStat += EqnTestInt(_T("10*(a == 1)"), 10, true); - iStat += EqnTestInt(_T("2*(a | b)"), 6, true); - iStat += EqnTestInt(_T("2*(a | b)"), 7, false); - iStat += EqnTestInt(_T("a < b"), 1, true); - iStat += EqnTestInt(_T("b > a"), 1, true); - iStat += EqnTestInt(_T("a <= 1"), 1, true); - iStat += EqnTestInt(_T("b >= 2"), 1, true); - iStat += EqnTestInt(_T("2*(a + b)"), 6, true); - iStat += EqnTestInt(_T("2*(a - b)"), -2, true); - iStat += EqnTestInt(_T("a + (a << b)"), 5, true); - iStat += EqnTestInt(_T("-2^2"), -4, true); - iStat += EqnTestInt(_T("3--a"), 4, true); - iStat += EqnTestInt(_T("3+-3^2"), -6, true); - - // Test reading of hex values: - iStat += EqnTestInt(_T("0xff"), 255, true); - iStat += EqnTestInt(_T("10+0xff"), 265, true); - iStat += EqnTestInt(_T("0xff+10"), 265, true); - iStat += EqnTestInt(_T("10*0xff"), 2550, true); - iStat += EqnTestInt(_T("0xff*10"), 2550, true); - iStat += EqnTestInt(_T("10+0xff+1"), 266, true); - iStat += EqnTestInt(_T("1+0xff+10"), 266, true); - -// incorrect: '^' is yor here, not power -// iStat += EqnTestInt("-(1+2)^2", -9, true); -// iStat += EqnTestInt("-1^3", -1, true); - - // Test precedence - // a=1, b=2, c=3 - iStat += EqnTestInt(_T("a + b * c"), 7, true); - iStat += EqnTestInt(_T("a * b + c"), 5, true); - iStat += EqnTestInt(_T("a10"), 0, true); - iStat += EqnTestInt(_T("a"), f1of1) - PARSER_THROWCHECK(PostfixOprt, true, _T("?<"), f1of1) - PARSER_THROWCHECK(PostfixOprt, true, _T("**"), f1of1) - PARSER_THROWCHECK(PostfixOprt, true, _T("xor"), f1of1) - PARSER_THROWCHECK(PostfixOprt, true, _T("and"), f1of1) - PARSER_THROWCHECK(PostfixOprt, true, _T("or"), f1of1) - PARSER_THROWCHECK(PostfixOprt, true, _T("not"), f1of1) - PARSER_THROWCHECK(PostfixOprt, true, _T("!"), f1of1) - // Binary operator - // The following must fail with builtin operators activated - // p.EnableBuiltInOp(true); -> this is the default - p.ClearPostfixOprt(); - PARSER_THROWCHECK(Oprt, false, _T("+"), f1of2) - PARSER_THROWCHECK(Oprt, false, _T("-"), f1of2) - PARSER_THROWCHECK(Oprt, false, _T("*"), f1of2) - PARSER_THROWCHECK(Oprt, false, _T("/"), f1of2) - PARSER_THROWCHECK(Oprt, false, _T("^"), f1of2) - PARSER_THROWCHECK(Oprt, false, _T("&&"), f1of2) - PARSER_THROWCHECK(Oprt, false, _T("||"), f1of2) - // without activated built in operators it should work - p.EnableBuiltInOprt(false); - PARSER_THROWCHECK(Oprt, true, _T("+"), f1of2) - PARSER_THROWCHECK(Oprt, true, _T("-"), f1of2) - PARSER_THROWCHECK(Oprt, true, _T("*"), f1of2) - PARSER_THROWCHECK(Oprt, true, _T("/"), f1of2) - PARSER_THROWCHECK(Oprt, true, _T("^"), f1of2) - PARSER_THROWCHECK(Oprt, true, _T("&&"), f1of2) - PARSER_THROWCHECK(Oprt, true, _T("||"), f1of2) - #undef PARSER_THROWCHECK - - if (iStat==0) - mu::console() << _T("passed") << endl; - else - mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; - - return iStat; - } - - //--------------------------------------------------------------------------- - int ParserTester::TestSyntax() - { - int iStat = 0; - mu::console() << _T("testing syntax engine..."); - - iStat += ThrowTest(_T("1,"), ecUNEXPECTED_EOF); // incomplete hex definition - iStat += ThrowTest(_T("a,"), ecUNEXPECTED_EOF); // incomplete hex definition - iStat += ThrowTest(_T("sin(8),"), ecUNEXPECTED_EOF); // incomplete hex definition - iStat += ThrowTest(_T("(sin(8)),"), ecUNEXPECTED_EOF); // incomplete hex definition - iStat += ThrowTest(_T("a{m},"), ecUNEXPECTED_EOF); // incomplete hex definition - - iStat += EqnTest(_T("(1+ 2*a)"), 3, true); // Spaces within formula - iStat += EqnTest(_T("sqrt((4))"), 2, true); // Multiple brackets - iStat += EqnTest(_T("sqrt((2)+2)"), 2, true);// Multiple brackets - iStat += EqnTest(_T("sqrt(2+(2))"), 2, true);// Multiple brackets - iStat += EqnTest(_T("sqrt(a+(3))"), 2, true);// Multiple brackets - iStat += EqnTest(_T("sqrt((3)+a)"), 2, true);// Multiple brackets - iStat += EqnTest(_T("order(1,2)"), 1, true); // May not cause name collision with operator "or" - iStat += EqnTest(_T("(2+"), 0, false); // missing closing bracket - iStat += EqnTest(_T("2++4"), 0, false); // unexpected operator - iStat += EqnTest(_T("2+-4"), 0, false); // unexpected operator - iStat += EqnTest(_T("(2+)"), 0, false); // unexpected closing bracket - iStat += EqnTest(_T("--2"), 0, false); // double sign - iStat += EqnTest(_T("ksdfj"), 0, false); // unknown token - iStat += EqnTest(_T("()"), 0, false); // empty bracket without a function - iStat += EqnTest(_T("5+()"), 0, false); // empty bracket without a function - iStat += EqnTest(_T("sin(cos)"), 0, false); // unexpected function - iStat += EqnTest(_T("5t6"), 0, false); // unknown token - iStat += EqnTest(_T("5 t 6"), 0, false); // unknown token - iStat += EqnTest(_T("8*"), 0, false); // unexpected end of formula - iStat += EqnTest(_T(",3"), 0, false); // unexpected comma - iStat += EqnTest(_T("3,5"), 0, false); // unexpected comma - iStat += EqnTest(_T("sin(8,8)"), 0, false); // too many function args - iStat += EqnTest(_T("(7,8)"), 0, false); // too many function args - iStat += EqnTest(_T("sin)"), 0, false); // unexpected closing bracket - iStat += EqnTest(_T("a)"), 0, false); // unexpected closing bracket - iStat += EqnTest(_T("pi)"), 0, false); // unexpected closing bracket - iStat += EqnTest(_T("sin(())"), 0, false); // unexpected closing bracket - iStat += EqnTest(_T("sin()"), 0, false); // unexpected closing bracket - - if (iStat==0) - mu::console() << _T("passed") << endl; - else - mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; - - return iStat; - } - - //--------------------------------------------------------------------------- - int ParserTester::TestVarConst() - { - int iStat = 0; - mu::console() << _T("testing variable/constant detection..."); - - // Test if the result changes when a variable changes - iStat += EqnTestWithVarChange( _T("a"), 1, 1, 2, 2 ); - iStat += EqnTestWithVarChange( _T("2*a"), 2, 4, 3, 6 ); - - // distinguish constants with same basename - iStat += EqnTest( _T("const"), 1, true); - iStat += EqnTest( _T("const1"), 2, true); - iStat += EqnTest( _T("const2"), 3, true); - iStat += EqnTest( _T("2*const"), 2, true); - iStat += EqnTest( _T("2*const1"), 4, true); - iStat += EqnTest( _T("2*const2"), 6, true); - iStat += EqnTest( _T("2*const+1"), 3, true); - iStat += EqnTest( _T("2*const1+1"), 5, true); - iStat += EqnTest( _T("2*const2+1"), 7, true); - iStat += EqnTest( _T("const"), 0, false); - iStat += EqnTest( _T("const1"), 0, false); - iStat += EqnTest( _T("const2"), 0, false); - - // distinguish variables with same basename - iStat += EqnTest( _T("a"), 1, true); - iStat += EqnTest( _T("aa"), 2, true); - iStat += EqnTest( _T("2*a"), 2, true); - iStat += EqnTest( _T("2*aa"), 4, true); - iStat += EqnTest( _T("2*a-1"), 1, true); - iStat += EqnTest( _T("2*aa-1"), 3, true); - - // custom value recognition - iStat += EqnTest( _T("0xff"), 255, true); - iStat += EqnTest( _T("0x97 + 0xff"), 406, true); - - // Finally test querying of used variables - try - { - int idx; - mu::Parser p; - mu::value_type vVarVal[] = { 1, 2, 3, 4, 5}; - p.DefineVar( _T("a"), &vVarVal[0]); - p.DefineVar( _T("b"), &vVarVal[1]); - p.DefineVar( _T("c"), &vVarVal[2]); - p.DefineVar( _T("d"), &vVarVal[3]); - p.DefineVar( _T("e"), &vVarVal[4]); - - // Test lookup of defined variables - // 4 used variables - p.SetExpr( _T("a+b+c+d") ); - mu::varmap_type UsedVar = p.GetUsedVar(); - int iCount = (int)UsedVar.size(); - if (iCount!=4) - throw false; - - // the next check will fail if the parser - // erroneously creates new variables internally - if (p.GetVar().size()!=5) - throw false; - - mu::varmap_type::const_iterator item = UsedVar.begin(); - for (idx=0; item!=UsedVar.end(); ++item) - { - if (&vVarVal[idx++]!=item->second) - throw false; - } - - // Test lookup of undefined variables - p.SetExpr( _T("undef1+undef2+undef3") ); - UsedVar = p.GetUsedVar(); - iCount = (int)UsedVar.size(); - if (iCount!=3) - throw false; - - // the next check will fail if the parser - // erroneously creates new variables internally - if (p.GetVar().size()!=5) - throw false; - - for (item = UsedVar.begin(); item!=UsedVar.end(); ++item) - { - if (item->second!=0) - throw false; // all pointers to undefined variables must be null - } - - // 1 used variables - p.SetExpr( _T("a+b") ); - UsedVar = p.GetUsedVar(); - iCount = (int)UsedVar.size(); - if (iCount!=2) throw false; - item = UsedVar.begin(); - for (idx=0; item!=UsedVar.end(); ++item) - if (&vVarVal[idx++]!=item->second) throw false; - - } - catch(...) - { - iStat += 1; - } - - if (iStat==0) - mu::console() << _T("passed") << endl; - else - mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; - - return iStat; - } - - //--------------------------------------------------------------------------- - int ParserTester::TestMultiArg() - { - int iStat = 0; - mu::console() << _T("testing multiarg functions..."); - - // Compound expressions - iStat += EqnTest( _T("1,2,3"), 3, true); - iStat += EqnTest( _T("a,b,c"), 3, true); - iStat += EqnTest( _T("a=10,b=20,c=a*b"), 200, true); - iStat += EqnTest( _T("1,\n2,\n3"), 3, true); - iStat += EqnTest( _T("a,\nb,\nc"), 3, true); - iStat += EqnTest( _T("a=10,\nb=20,\nc=a*b"), 200, true); - iStat += EqnTest( _T("1,\r\n2,\r\n3"), 3, true); - iStat += EqnTest( _T("a,\r\nb,\r\nc"), 3, true); - iStat += EqnTest( _T("a=10,\r\nb=20,\r\nc=a*b"), 200, true); - - // picking the right argument - iStat += EqnTest( _T("f1of1(1)"), 1, true); - iStat += EqnTest( _T("f1of2(1, 2)"), 1, true); - iStat += EqnTest( _T("f2of2(1, 2)"), 2, true); - iStat += EqnTest( _T("f1of3(1, 2, 3)"), 1, true); - iStat += EqnTest( _T("f2of3(1, 2, 3)"), 2, true); - iStat += EqnTest( _T("f3of3(1, 2, 3)"), 3, true); - iStat += EqnTest( _T("f1of4(1, 2, 3, 4)"), 1, true); - iStat += EqnTest( _T("f2of4(1, 2, 3, 4)"), 2, true); - iStat += EqnTest( _T("f3of4(1, 2, 3, 4)"), 3, true); - iStat += EqnTest( _T("f4of4(1, 2, 3, 4)"), 4, true); - iStat += EqnTest( _T("f1of5(1, 2, 3, 4, 5)"), 1, true); - iStat += EqnTest( _T("f2of5(1, 2, 3, 4, 5)"), 2, true); - iStat += EqnTest( _T("f3of5(1, 2, 3, 4, 5)"), 3, true); - iStat += EqnTest( _T("f4of5(1, 2, 3, 4, 5)"), 4, true); - iStat += EqnTest( _T("f5of5(1, 2, 3, 4, 5)"), 5, true); - // Too few arguments / Too many arguments - iStat += EqnTest( _T("1+ping()"), 11, true); - iStat += EqnTest( _T("ping()+1"), 11, true); - iStat += EqnTest( _T("2*ping()"), 20, true); - iStat += EqnTest( _T("ping()*2"), 20, true); - iStat += EqnTest( _T("ping(1,2)"), 0, false); - iStat += EqnTest( _T("1+ping(1,2)"), 0, false); - iStat += EqnTest( _T("f1of1(1,2)"), 0, false); - iStat += EqnTest( _T("f1of1()"), 0, false); - iStat += EqnTest( _T("f1of2(1, 2, 3)"), 0, false); - iStat += EqnTest( _T("f1of2(1)"), 0, false); - iStat += EqnTest( _T("f1of3(1, 2, 3, 4)"), 0, false); - iStat += EqnTest( _T("f1of3(1)"), 0, false); - iStat += EqnTest( _T("f1of4(1, 2, 3, 4, 5)"), 0, false); - iStat += EqnTest( _T("f1of4(1)"), 0, false); - iStat += EqnTest( _T("(1,2,3)"), 0, false); - iStat += EqnTest( _T("1,2,3"), 0, false); - iStat += EqnTest( _T("(1*a,2,3)"), 0, false); - iStat += EqnTest( _T("1,2*a,3"), 0, false); - - // correct calculation of arguments - iStat += EqnTest( _T("min(a, 1)"), 1, true); - iStat += EqnTest( _T("min(3*2, 1)"), 1, true); - iStat += EqnTest( _T("min(3*2, 1)"), 6, false); - iStat += EqnTest( _T("firstArg(2,3,4)"), 2, true); - iStat += EqnTest( _T("lastArg(2,3,4)"), 4, true); - iStat += EqnTest( _T("min(3*a+1, 1)"), 1, true); - iStat += EqnTest( _T("max(3*a+1, 1)"), 4, true); - iStat += EqnTest( _T("max(3*a+1, 1)*2"), 8, true); - iStat += EqnTest( _T("2*max(3*a+1, 1)+2"), 10, true); - - // functions with Variable argument count - iStat += EqnTest( _T("sum(a)"), 1, true); - iStat += EqnTest( _T("sum(1,2,3)"), 6, true); - iStat += EqnTest( _T("sum(a,b,c)"), 6, true); - iStat += EqnTest( _T("sum(1,-max(1,2),3)*2"), 4, true); - iStat += EqnTest( _T("2*sum(1,2,3)"), 12, true); - iStat += EqnTest( _T("2*sum(1,2,3)+2"), 14, true); - iStat += EqnTest( _T("2*sum(-1,2,3)+2"), 10, true); - iStat += EqnTest( _T("2*sum(-1,2,-(-a))+2"), 6, true); - iStat += EqnTest( _T("2*sum(-1,10,-a)+2"), 18, true); - iStat += EqnTest( _T("2*sum(1,2,3)*2"), 24, true); - iStat += EqnTest( _T("sum(1,-max(1,2),3)*2"), 4, true); - iStat += EqnTest( _T("sum(1*3, 4, a+2)"), 10, true); - iStat += EqnTest( _T("sum(1*3, 2*sum(1,2,2), a+2)"), 16, true); - iStat += EqnTest( _T("sum(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2)"), 24, true); - - // some failures - iStat += EqnTest( _T("sum()"), 0, false); - iStat += EqnTest( _T("sum(,)"), 0, false); - iStat += EqnTest( _T("sum(1,2,)"), 0, false); - iStat += EqnTest( _T("sum(,1,2)"), 0, false); - - if (iStat==0) - mu::console() << _T("passed") << endl; - else - mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; - - return iStat; - } - - - //--------------------------------------------------------------------------- - int ParserTester::TestInfixOprt() - { - int iStat(0); - mu::console() << "testing infix operators..."; - - iStat += EqnTest( _T("+1"), +1, true); - iStat += EqnTest( _T("-(+1)"), -1, true); - iStat += EqnTest( _T("-(+1)*2"), -2, true); - iStat += EqnTest( _T("-(+2)*sqrt(4)"), -4, true); - iStat += EqnTest( _T("3-+a"), 2, true); - iStat += EqnTest( _T("+1*3"), 3, true); - - iStat += EqnTest( _T("-1"), -1, true); - iStat += EqnTest( _T("-(-1)"), 1, true); - iStat += EqnTest( _T("-(-1)*2"), 2, true); - iStat += EqnTest( _T("-(-2)*sqrt(4)"), 4, true); - iStat += EqnTest( _T("-_pi"), -PARSER_CONST_PI, true); - iStat += EqnTest( _T("-a"), -1, true); - iStat += EqnTest( _T("-(a)"), -1, true); - iStat += EqnTest( _T("-(-a)"), 1, true); - iStat += EqnTest( _T("-(-a)*2"), 2, true); - iStat += EqnTest( _T("-(8)"), -8, true); - iStat += EqnTest( _T("-8"), -8, true); - iStat += EqnTest( _T("-(2+1)"), -3, true); - iStat += EqnTest( _T("-(f1of1(1+2*3)+1*2)"), -9, true); - iStat += EqnTest( _T("-(-f1of1(1+2*3)+1*2)"), 5, true); - iStat += EqnTest( _T("-sin(8)"), -0.989358, true); - iStat += EqnTest( _T("3-(-a)"), 4, true); - iStat += EqnTest( _T("3--a"), 4, true); - iStat += EqnTest( _T("-1*3"), -3, true); - - // Postfix / infix priorities - iStat += EqnTest( _T("~2#"), 8, true); - iStat += EqnTest( _T("~f1of1(2)#"), 8, true); - iStat += EqnTest( _T("~(b)#"), 8, true); - iStat += EqnTest( _T("(~b)#"), 12, true); - iStat += EqnTest( _T("~(2#)"), 8, true); - iStat += EqnTest( _T("~(f1of1(2)#)"), 8, true); - // - iStat += EqnTest( _T("-2^2"),-4, true); - iStat += EqnTest( _T("-(a+b)^2"),-9, true); - iStat += EqnTest( _T("(-3)^2"),9, true); - iStat += EqnTest( _T("-(-2^2)"),4, true); - iStat += EqnTest( _T("3+-3^2"),-6, true); - // The following assumes use of sqr as postfix operator ("§") together - // with a sign operator of low priority: - iStat += EqnTest( _T("-2'"), -4, true); - iStat += EqnTest( _T("-(1+1)'"),-4, true); - iStat += EqnTest( _T("2+-(1+1)'"),-2, true); - iStat += EqnTest( _T("2+-2'"), -2, true); - // This is the classic behaviour of the infix sign operator (here: "$") which is - // now deprecated: - iStat += EqnTest( _T("$2^2"),4, true); - iStat += EqnTest( _T("$(a+b)^2"),9, true); - iStat += EqnTest( _T("($3)^2"),9, true); - iStat += EqnTest( _T("$($2^2)"),-4, true); - iStat += EqnTest( _T("3+$3^2"),12, true); - - // infix operators sharing the first few characters - iStat += EqnTest( _T("~ 123"), 123+2, true); - iStat += EqnTest( _T("~~ 123"), 123+2, true); - - if (iStat==0) - mu::console() << _T("passed") << endl; - else - mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; - - return iStat; - } - - - //--------------------------------------------------------------------------- - int ParserTester::TestPostFix() - { - int iStat = 0; - mu::console() << _T("testing postfix operators..."); - - // application - iStat += EqnTest( _T("3{m}+5"), 5.003, true); - iStat += EqnTest( _T("1000{m}"), 1, true); - iStat += EqnTest( _T("1000 {m}"), 1, true); - iStat += EqnTest( _T("(a){m}"), 1e-3, true); - iStat += EqnTest( _T("a{m}"), 1e-3, true); - iStat += EqnTest( _T("a {m}"), 1e-3, true); - iStat += EqnTest( _T("-(a){m}"), -1e-3, true); - iStat += EqnTest( _T("-2{m}"), -2e-3, true); - iStat += EqnTest( _T("-2 {m}"), -2e-3, true); - iStat += EqnTest( _T("f1of1(1000){m}"), 1, true); - iStat += EqnTest( _T("-f1of1(1000){m}"), -1, true); - iStat += EqnTest( _T("-f1of1(-1000){m}"), 1, true); - iStat += EqnTest( _T("f4of4(0,0,0,1000){m}"), 1, true); - iStat += EqnTest( _T("2+(a*1000){m}"), 3, true); - - // can postfix operators "m" und "meg" be told apart properly? - iStat += EqnTest( _T("2*3000meg+2"), 2*3e9+2, true); - - // some incorrect results - iStat += EqnTest( _T("1000{m}"), 0.1, false); - iStat += EqnTest( _T("(a){m}"), 2, false); - // failure due to syntax checking - iStat += ThrowTest(_T("0x"), ecUNASSIGNABLE_TOKEN); // incomplete hex definition - iStat += ThrowTest(_T("3+"), ecUNEXPECTED_EOF); - iStat += ThrowTest( _T("4 + {m}"), ecUNASSIGNABLE_TOKEN); - iStat += ThrowTest( _T("{m}4"), ecUNASSIGNABLE_TOKEN); - iStat += ThrowTest( _T("sin({m})"), ecUNASSIGNABLE_TOKEN); - iStat += ThrowTest( _T("{m} {m}"), ecUNASSIGNABLE_TOKEN); - iStat += ThrowTest( _T("{m}(8)"), ecUNASSIGNABLE_TOKEN); - iStat += ThrowTest( _T("4,{m}"), ecUNASSIGNABLE_TOKEN); - iStat += ThrowTest( _T("-{m}"), ecUNASSIGNABLE_TOKEN); - iStat += ThrowTest( _T("2(-{m})"), ecUNEXPECTED_PARENS); - iStat += ThrowTest( _T("2({m})"), ecUNEXPECTED_PARENS); - - iStat += ThrowTest( _T("multi*1.0"), ecUNASSIGNABLE_TOKEN); - - if (iStat==0) - mu::console() << _T("passed") << endl; - else - mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; - - return iStat; - } - - //--------------------------------------------------------------------------- - int ParserTester::TestExpression() - { - int iStat = 0; - mu::console() << _T("testing expression samples..."); - - value_type b = 2; - - // Optimization - iStat += EqnTest( _T("2*b*5"), 20, true); - iStat += EqnTest( _T("2*b*5 + 4*b"), 28, true); - iStat += EqnTest( _T("2*a/3"), 2.0/3.0, true); - - // Addition auf cmVARMUL - iStat += EqnTest( _T("3+b"), b+3, true); - iStat += EqnTest( _T("b+3"), b+3, true); - iStat += EqnTest( _T("b*3+2"), b*3+2, true); - iStat += EqnTest( _T("3*b+2"), b*3+2, true); - iStat += EqnTest( _T("2+b*3"), b*3+2, true); - iStat += EqnTest( _T("2+3*b"), b*3+2, true); - iStat += EqnTest( _T("b+3*b"), b+3*b, true); - iStat += EqnTest( _T("3*b+b"), b+3*b, true); - - iStat += EqnTest( _T("2+b*3+b"), 2+b*3+b, true); - iStat += EqnTest( _T("b+2+b*3"), b+2+b*3, true); - - iStat += EqnTest( _T("(2*b+1)*4"), (2*b+1)*4, true); - iStat += EqnTest( _T("4*(2*b+1)"), (2*b+1)*4, true); - - // operator precedences - iStat += EqnTest( _T("1+2-3*4/5^6"), 2.99923, true); - iStat += EqnTest( _T("1^2/3*4-5+6"), 2.33333333, true); - iStat += EqnTest( _T("1+2*3"), 7, true); - iStat += EqnTest( _T("1+2*3"), 7, true); - iStat += EqnTest( _T("(1+2)*3"), 9, true); - iStat += EqnTest( _T("(1+2)*(-3)"), -9, true); - iStat += EqnTest( _T("2/4"), 0.5, true); - - iStat += EqnTest( _T("exp(ln(7))"), 7, true); - iStat += EqnTest( _T("e^ln(7)"), 7, true); - iStat += EqnTest( _T("e^(ln(7))"), 7, true); - iStat += EqnTest( _T("(e^(ln(7)))"), 7, true); - iStat += EqnTest( _T("1-(e^(ln(7)))"), -6, true); - iStat += EqnTest( _T("2*(e^(ln(7)))"), 14, true); - iStat += EqnTest( _T("10^log(5)"), pow(10.0, log(5.0)), true); - iStat += EqnTest( _T("10^log10(5)"), 5, true); - iStat += EqnTest( _T("2^log2(4)"), 4, true); - iStat += EqnTest( _T("-(sin(0)+1)"), -1, true); - iStat += EqnTest( _T("-(2^1.1)"), -2.14354692, true); - - iStat += EqnTest( _T("(cos(2.41)/b)"), -0.372056, true); - iStat += EqnTest( _T("(1*(2*(3*(4*(5*(6*(a+b)))))))"), 2160, true); - iStat += EqnTest( _T("(1*(2*(3*(4*(5*(6*(7*(a+b))))))))"), 15120, true); - iStat += EqnTest( _T("(a/((((b+(((e*(((((pi*((((3.45*((pi+a)+pi))+b)+b)*a))+0.68)+e)+a)/a))+a)+b))+b)*a)-pi))"), 0.00377999, true); - - // long formula (Reference: Matlab) - iStat += EqnTest( - _T("(((-9))-e/(((((((pi-(((-7)+(-3)/4/e))))/(((-5))-2)-((pi+(-0))*(sqrt((e+e))*(-8))*(((-pi)+(-pi)-(-9)*(6*5))") - _T("/(-e)-e))/2)/((((sqrt(2/(-e)+6)-(4-2))+((5/(-2))/(1*(-pi)+3))/8)*pi*((pi/((-2)/(-6)*1*(-1))*(-6)+(-e)))))/") - _T("((e+(-2)+(-e)*((((-3)*9+(-e)))+(-9)))))))-((((e-7+(((5/pi-(3/1+pi)))))/e)/(-5))/(sqrt((((((1+(-7))))+((((-") - _T("e)*(-e)))-8))*(-5)/((-e)))*(-6)-((((((-2)-(-9)-(-e)-1)/3))))/(sqrt((8+(e-((-6))+(9*(-9))))*(((3+2-8))*(7+6") - _T("+(-5))+((0/(-e)*(-pi))+7)))+(((((-e)/e/e)+((-6)*5)*e+(3+(-5)/pi))))+pi))/sqrt((((9))+((((pi))-8+2))+pi))/e") - _T("*4)*((-5)/(((-pi))*(sqrt(e)))))-(((((((-e)*(e)-pi))/4+(pi)*(-9)))))))+(-pi)"), -12.23016549, true); - - // long formula (Reference: Matlab) - iStat += EqnTest( - _T("(atan(sin((((((((((((((((pi/cos((a/((((0.53-b)-pi)*e)/b))))+2.51)+a)-0.54)/0.98)+b)*b)+e)/a)+b)+a)+b)+pi)/e") - _T(")+a)))*2.77)"), -2.16995656, true); - - // long formula (Reference: Matlab) - iStat += EqnTest( _T("1+2-3*4/5^6*(2*(1-5+(3*7^9)*(4+6*7-3)))+12"), -7995810.09926, true); - - if (iStat==0) - mu::console() << _T("passed") << endl; - else - mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; - - return iStat; - } - - - - //--------------------------------------------------------------------------- - int ParserTester::TestIfThenElse() - { - int iStat = 0; - mu::console() << _T("testing if-then-else operator..."); - - // Test error detection - iStat += ThrowTest(_T(":3"), ecUNEXPECTED_CONDITIONAL); - iStat += ThrowTest(_T("? 1 : 2"), ecUNEXPECTED_CONDITIONAL); - iStat += ThrowTest(_T("(ab) ? 10 : 11"), 11, true); - iStat += EqnTest(_T("(ab) ? c : d"), -2, true); - - iStat += EqnTest(_T("(a>b) ? 1 : 0"), 0, true); - iStat += EqnTest(_T("((a>b) ? 1 : 0) ? 1 : 2"), 2, true); - iStat += EqnTest(_T("((a>b) ? 1 : 0) ? 1 : sum((a>b) ? 1 : 2)"), 2, true); - iStat += EqnTest(_T("((a>b) ? 0 : 1) ? 1 : sum((a>b) ? 1 : 2)"), 1, true); - - iStat += EqnTest(_T("sum((a>b) ? 1 : 2)"), 2, true); - iStat += EqnTest(_T("sum((1) ? 1 : 2)"), 1, true); - iStat += EqnTest(_T("sum((a>b) ? 1 : 2, 100)"), 102, true); - iStat += EqnTest(_T("sum((1) ? 1 : 2, 100)"), 101, true); - iStat += EqnTest(_T("sum(3, (a>b) ? 3 : 10)"), 13, true); - iStat += EqnTest(_T("sum(3, (ab) ? 3 : 10)"), 130, true); - iStat += EqnTest(_T("10*sum(3, (ab) ? 3 : 10)*10"), 130, true); - iStat += EqnTest(_T("sum(3, (ab) ? sum(3, (ab) ? sum(3, (ab) ? sum(3, (ab)&&(a2)&&(1<2) ? 128 : 255"), 255, true); - iStat += EqnTest(_T("((1<2)&&(1<2)) ? 128 : 255"), 128, true); - iStat += EqnTest(_T("((1>2)&&(1<2)) ? 128 : 255"), 255, true); - iStat += EqnTest(_T("((ab)&&(a0 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 64"), 255, true); - iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 :(1>0 ? 32 : 64)"), 255, true); - iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 : 1>2 ? 32 : 64"), 128, true); - iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 :(1>2 ? 32 : 64)"), 128, true); - iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 64"), 32, true); - iStat += EqnTest(_T("1>2 ? 1>0 ? 128 : 255 : 1>2 ? 32 : 64"), 64, true); - iStat += EqnTest(_T("1>0 ? 50 : 1>0 ? 128 : 255"), 50, true); - iStat += EqnTest(_T("1>0 ? 50 : (1>0 ? 128 : 255)"), 50, true); - iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 : 50"), 128, true); - iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 1>2 ? 64 : 16"), 32, true); - iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 :(1>2 ? 64 : 16)"), 32, true); - iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : 1>0 ? 32 :1>2 ? 64 : 16"), 255, true); - iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : (1>0 ? 32 :1>2 ? 64 : 16)"), 255, true); - iStat += EqnTest(_T("1 ? 0 ? 128 : 255 : 1 ? 32 : 64"), 255, true); - - // assignment operators - iStat += EqnTest(_T("a= 0 ? 128 : 255, a"), 255, true); - iStat += EqnTest(_T("a=((a>b)&&(a - // this is now legal, for reference see: - // https://sourceforge.net/forum/message.php?msg_id=7411373 - // iStat += ThrowTest( _T("sin=9"), ecUNEXPECTED_OPERATOR); - //
- - iStat += ThrowTest( _T("(8)=5"), ecUNEXPECTED_OPERATOR); - iStat += ThrowTest( _T("(a)=5"), ecUNEXPECTED_OPERATOR); - iStat += ThrowTest( _T("a=\"tttt\""), ecOPRT_TYPE_CONFLICT); - - if (iStat==0) - mu::console() << _T("passed") << endl; - else - mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; - - return iStat; - } - - - //--------------------------------------------------------------------------- - void ParserTester::AddTest(testfun_type a_pFun) - { - m_vTestFun.push_back(a_pFun); - } - - //--------------------------------------------------------------------------- - void ParserTester::Run() - { - int iStat = 0; - try - { - for (int i=0; i<(int)m_vTestFun.size(); ++i) - iStat += (this->*m_vTestFun[i])(); - } - catch(Parser::exception_type &e) - { - mu::console() << "\n" << e.GetMsg() << endl; - mu::console() << e.GetToken() << endl; - Abort(); - } - catch(std::exception &e) - { - mu::console() << e.what() << endl; - Abort(); - } - catch(...) - { - mu::console() << "Internal error"; - Abort(); - } - - if (iStat==0) - { - mu::console() << "Test passed (" << ParserTester::c_iCount << " expressions)" << endl; - } - else - { - mu::console() << "Test failed with " << iStat - << " errors (" << ParserTester::c_iCount - << " expressions)" << endl; - } - ParserTester::c_iCount = 0; - } - - - //--------------------------------------------------------------------------- - int ParserTester::ThrowTest(const string_type &a_str, int a_iErrc, bool a_bFail) - { - ParserTester::c_iCount++; - - try - { - value_type fVal[] = {1,1,1}; - Parser p; - - p.DefineVar( _T("a"), &fVal[0]); - p.DefineVar( _T("b"), &fVal[1]); - p.DefineVar( _T("c"), &fVal[2]); - p.DefinePostfixOprt( _T("{m}"), Milli); - p.DefinePostfixOprt( _T("m"), Milli); - p.DefineFun( _T("ping"), Ping); - p.DefineFun( _T("valueof"), ValueOf); - p.DefineFun( _T("strfun1"), StrFun1); - p.DefineFun( _T("strfun2"), StrFun2); - p.DefineFun( _T("strfun3"), StrFun3); - p.SetExpr(a_str); - p.Eval(); - } - catch(ParserError &e) - { - // output the formula in case of an failed test - if (a_bFail==false || (a_bFail==true && a_iErrc!=e.GetCode()) ) - { - mu::console() << _T("\n ") - << _T("Expression: ") << a_str - << _T(" Code:") << e.GetCode() << _T("(") << e.GetMsg() << _T(")") - << _T(" Expected:") << a_iErrc; - } - - return (a_iErrc==e.GetCode()) ? 0 : 1; - } - - // if a_bFail==false no exception is expected - bool bRet((a_bFail==false) ? 0 : 1); - if (bRet==1) - { - mu::console() << _T("\n ") - << _T("Expression: ") << a_str - << _T(" did evaluate; Expected error:") << a_iErrc; - } - - return bRet; - } - - //--------------------------------------------------------------------------- - /** \brief Evaluate a tet expression. - - \return 1 in case of a failure, 0 otherwise. - */ - int ParserTester::EqnTestWithVarChange(const string_type &a_str, - double a_fVar1, - double a_fRes1, - double a_fVar2, - double a_fRes2) - { - ParserTester::c_iCount++; - - try - { - value_type fVal[2] = {-999, -999 }; // should be equal - - Parser p; - value_type var = 0; - - // variable - p.DefineVar( _T("a"), &var); - p.SetExpr(a_str); - - var = a_fVar1; - fVal[0] = p.Eval(); - - var = a_fVar2; - fVal[1] = p.Eval(); - - if ( fabs(a_fRes1-fVal[0]) > 0.0000000001) - throw std::runtime_error("incorrect result (first pass)"); - - if ( fabs(a_fRes2-fVal[1]) > 0.0000000001) - throw std::runtime_error("incorrect result (second pass)"); - } - catch(Parser::exception_type &e) - { - mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.GetMsg() << _T(")"); - return 1; - } - catch(std::exception &e) - { - mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.what() << _T(")"); - return 1; // always return a failure since this exception is not expected - } - catch(...) - { - mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)"); - return 1; // exceptions other than ParserException are not allowed - } - - return 0; - } - - //--------------------------------------------------------------------------- - /** \brief Evaluate a tet expression. - - \return 1 in case of a failure, 0 otherwise. - */ - int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass) - { - ParserTester::c_iCount++; - int iRet(0); - value_type fVal[5] = {-999, -998, -997, -996, -995}; // initially should be different - - try - { - std::unique_ptr p1; - Parser p2, p3; // three parser objects - // they will be used for testing copy and assignment operators - // p1 is a pointer since i'm going to delete it in order to test if - // parsers after copy construction still refer to members of it. - // !! If this is the case this function will crash !! - - p1.reset(new mu::Parser()); - // Add constants - p1->DefineConst( _T("pi"), (value_type)PARSER_CONST_PI); - p1->DefineConst( _T("e"), (value_type)PARSER_CONST_E); - p1->DefineConst( _T("const"), 1); - p1->DefineConst( _T("const1"), 2); - p1->DefineConst( _T("const2"), 3); - // string constants - p1->DefineStrConst( _T("str1"), _T("1.11")); - p1->DefineStrConst( _T("str2"), _T("2.22")); - // variables - value_type vVarVal[] = { 1, 2, 3, -2}; - p1->DefineVar( _T("a"), &vVarVal[0]); - p1->DefineVar( _T("aa"), &vVarVal[1]); - p1->DefineVar( _T("b"), &vVarVal[1]); - p1->DefineVar( _T("c"), &vVarVal[2]); - p1->DefineVar( _T("d"), &vVarVal[3]); - - // custom value ident functions - p1->AddValIdent(&ParserTester::IsHexVal); - - // functions - p1->DefineFun( _T("ping"), Ping); - p1->DefineFun( _T("f1of1"), f1of1); // one parameter - p1->DefineFun( _T("f1of2"), f1of2); // two parameter - p1->DefineFun( _T("f2of2"), f2of2); - p1->DefineFun( _T("f1of3"), f1of3); // three parameter - p1->DefineFun( _T("f2of3"), f2of3); - p1->DefineFun( _T("f3of3"), f3of3); - p1->DefineFun( _T("f1of4"), f1of4); // four parameter - p1->DefineFun( _T("f2of4"), f2of4); - p1->DefineFun( _T("f3of4"), f3of4); - p1->DefineFun( _T("f4of4"), f4of4); - p1->DefineFun( _T("f1of5"), f1of5); // five parameter - p1->DefineFun( _T("f2of5"), f2of5); - p1->DefineFun( _T("f3of5"), f3of5); - p1->DefineFun( _T("f4of5"), f4of5); - p1->DefineFun( _T("f5of5"), f5of5); - - // binary operators - p1->DefineOprt( _T("add"), add, 0); - p1->DefineOprt( _T("++"), add, 0); - p1->DefineOprt( _T("&"), land, prLAND); - - // sample functions - p1->DefineFun( _T("min"), Min); - p1->DefineFun( _T("max"), Max); - p1->DefineFun( _T("sum"), Sum); - p1->DefineFun( _T("valueof"), ValueOf); - p1->DefineFun( _T("atof"), StrToFloat); - p1->DefineFun( _T("strfun1"), StrFun1); - p1->DefineFun( _T("strfun2"), StrFun2); - p1->DefineFun( _T("strfun3"), StrFun3); - p1->DefineFun( _T("lastArg"), LastArg); - p1->DefineFun( _T("firstArg"), FirstArg); - p1->DefineFun( _T("order"), FirstArg); - - // infix / postfix operator - // Note: Identifiers used here do not have any meaning - // they are mere placeholders to test certain features. - p1->DefineInfixOprt( _T("$"), sign, prPOW+1); // sign with high priority - p1->DefineInfixOprt( _T("~"), plus2); // high priority - p1->DefineInfixOprt( _T("~~"), plus2); - p1->DefinePostfixOprt( _T("{m}"), Milli); - p1->DefinePostfixOprt( _T("{M}"), Mega); - p1->DefinePostfixOprt( _T("m"), Milli); - p1->DefinePostfixOprt( _T("meg"), Mega); - p1->DefinePostfixOprt( _T("#"), times3); - p1->DefinePostfixOprt( _T("'"), sqr); - p1->SetExpr(a_str); - - // Test bytecode integrity - // String parsing and bytecode parsing must yield the same result - fVal[0] = p1->Eval(); // result from stringparsing - fVal[1] = p1->Eval(); // result from bytecode - if (fVal[0]!=fVal[1]) - throw Parser::exception_type( _T("Bytecode / string parsing mismatch.") ); - - // Test copy and assignment operators - try - { - // Test copy constructor - std::vector vParser; - vParser.push_back(*(p1.get())); - mu::Parser p2 = vParser[0]; // take parser from vector - - // destroy the originals from p2 - vParser.clear(); // delete the vector - p1.reset(0); - - fVal[2] = p2.Eval(); - - // Test assignment operator - // additionally disable Optimizer this time - mu::Parser p3; - p3 = p2; - p3.EnableOptimizer(false); - fVal[3] = p3.Eval(); - - // Test Eval function for multiple return values - // use p2 since it has the optimizer enabled! - int nNum; - value_type *v = p2.Eval(nNum); - fVal[4] = v[nNum-1]; - } - catch(std::exception &e) - { - mu::console() << _T("\n ") << e.what() << _T("\n"); - } - - // limited floating point accuracy requires the following test - bool bCloseEnough(true); - for (unsigned i=0; i::has_infinity) -#pragma warning(pop) - { - bCloseEnough &= (fabs(fVal[i]) != numeric_limits::infinity()); - } - } - - iRet = ((bCloseEnough && a_fPass) || (!bCloseEnough && !a_fPass)) ? 0 : 1; - - - if (iRet==1) - { - mu::console() << _T("\n fail: ") << a_str.c_str() - << _T(" (incorrect result; expected: ") << a_fRes - << _T(" ;calculated: ") << fVal[0] << _T(",") - << fVal[1] << _T(",") - << fVal[2] << _T(",") - << fVal[3] << _T(",") - << fVal[4] << _T(")."); - } - } - catch(Parser::exception_type &e) - { - if (a_fPass) - { - if (fVal[0]!=fVal[2] && fVal[0]!=-999 && fVal[1]!=-998) - mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (copy construction)"); - else - mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.GetMsg() << _T(")"); - return 1; - } - } - catch(std::exception &e) - { - mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.what() << _T(")"); - return 1; // always return a failure since this exception is not expected - } - catch(...) - { - mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)"); - return 1; // exceptions other than ParserException are not allowed - } - - return iRet; - } - - //--------------------------------------------------------------------------- - int ParserTester::EqnTestInt(const string_type &a_str, double a_fRes, bool a_fPass) - { - ParserTester::c_iCount++; - - value_type vVarVal[] = {1, 2, 3}; // variable values - int iRet(0); - - try - { - value_type fVal[2] = {-99, -999}; // results: initially should be different - ParserInt p; - p.DefineConst( _T("const1"), 1); - p.DefineConst( _T("const2"), 2); - p.DefineVar( _T("a"), &vVarVal[0]); - p.DefineVar( _T("b"), &vVarVal[1]); - p.DefineVar( _T("c"), &vVarVal[2]); - - p.SetExpr(a_str); - fVal[0] = p.Eval(); // result from stringparsing - fVal[1] = p.Eval(); // result from bytecode - - if (fVal[0]!=fVal[1]) - throw Parser::exception_type( _T("Bytecode corrupt.") ); - - iRet = ( (a_fRes==fVal[0] && a_fPass) || - (a_fRes!=fVal[0] && !a_fPass) ) ? 0 : 1; - if (iRet==1) - { - mu::console() << _T("\n fail: ") << a_str.c_str() - << _T(" (incorrect result; expected: ") << a_fRes - << _T(" ;calculated: ") << fVal[0]<< _T(")."); - } - } - catch(Parser::exception_type &e) - { - if (a_fPass) - { - mu::console() << _T("\n fail: ") << e.GetExpr() << _T(" : ") << e.GetMsg(); - iRet = 1; - } - } - catch(...) - { - mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)"); - iRet = 1; // exceptions other than ParserException are not allowed - } - - return iRet; - } - - //--------------------------------------------------------------------------- - /** \brief Test an expression in Bulk Mode. */ - int ParserTester::EqnTestBulk(const string_type &a_str, double a_fRes[4], bool a_fPass) - { - ParserTester::c_iCount++; - - // Define Bulk Variables - int nBulkSize = 4; - value_type vVariableA[] = { 1, 2, 3, 4 }; // variable values - value_type vVariableB[] = { 2, 2, 2, 2 }; // variable values - value_type vVariableC[] = { 3, 3, 3, 3 }; // variable values - value_type vResults[] = { 0, 0, 0, 0 }; // variable values - int iRet(0); - - try - { - Parser p; - p.DefineConst(_T("const1"), 1); - p.DefineConst(_T("const2"), 2); - p.DefineVar(_T("a"), vVariableA); - p.DefineVar(_T("b"), vVariableB); - p.DefineVar(_T("c"), vVariableC); - - p.SetExpr(a_str); - p.Eval(vResults, nBulkSize); - - bool bCloseEnough(true); - for (int i = 0; i < nBulkSize; ++i) - { - bCloseEnough &= (fabs(a_fRes[i] - vResults[i]) <= fabs(a_fRes[i] * 0.00001)); - } - - iRet = ((bCloseEnough && a_fPass) || (!bCloseEnough && !a_fPass)) ? 0 : 1; - if (iRet == 1) - { - mu::console() << _T("\n fail: ") << a_str.c_str() - << _T(" (incorrect result; expected: {") << a_fRes[0] << _T(",") << a_fRes[1] << _T(",") << a_fRes[2] << _T(",") << a_fRes[3] << _T("}") - << _T(" ;calculated: ") << vResults[0] << _T(",") << vResults[1] << _T(",") << vResults[2] << _T(",") << vResults[3] << _T("}"); - } - } - catch (Parser::exception_type &e) - { - if (a_fPass) - { - mu::console() << _T("\n fail: ") << e.GetExpr() << _T(" : ") << e.GetMsg(); - iRet = 1; - } - } - catch (...) - { - mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)"); - iRet = 1; // exceptions other than ParserException are not allowed - } - - return iRet; - } - - //--------------------------------------------------------------------------- - /** \brief Internal error in test class Test is going to be aborted. */ - void ParserTester::Abort() const - { - mu::console() << _T("Test failed (internal error in test class)") << endl; - while (!getchar()); - exit(-1); - } - } // namespace test -} // namespace mu diff --git a/external/muparser/src/muParserTokenReader.cpp b/external/muparser/src/muParserTokenReader.cpp deleted file mode 100644 index 576c8510..00000000 --- a/external/muparser/src/muParserTokenReader.cpp +++ /dev/null @@ -1,968 +0,0 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2013 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -#include -#include -#include -#include -#include -#include - -#include "muParserTokenReader.h" -#include "muParserBase.h" - -/** \file - \brief This file contains the parser token reader implementation. -*/ - - -namespace mu -{ - - // Forward declaration - class ParserBase; - - //--------------------------------------------------------------------------- - /** \brief Copy constructor. - - \sa Assign - \throw nothrow - */ - ParserTokenReader::ParserTokenReader(const ParserTokenReader &a_Reader) - { - Assign(a_Reader); - } - - //--------------------------------------------------------------------------- - /** \brief Assignment operator. - - Self assignment will be suppressed otherwise #Assign is called. - - \param a_Reader Object to copy to this token reader. - \throw nothrow - */ - ParserTokenReader& ParserTokenReader::operator=(const ParserTokenReader &a_Reader) - { - if (&a_Reader!=this) - Assign(a_Reader); - - return *this; - } - - //--------------------------------------------------------------------------- - /** \brief Assign state of a token reader to this token reader. - - \param a_Reader Object from which the state should be copied. - \throw nothrow - */ - void ParserTokenReader::Assign(const ParserTokenReader &a_Reader) - { - m_pParser = a_Reader.m_pParser; - m_strFormula = a_Reader.m_strFormula; - m_iPos = a_Reader.m_iPos; - m_iSynFlags = a_Reader.m_iSynFlags; - - m_UsedVar = a_Reader.m_UsedVar; - m_pFunDef = a_Reader.m_pFunDef; - m_pConstDef = a_Reader.m_pConstDef; - m_pVarDef = a_Reader.m_pVarDef; - m_pStrVarDef = a_Reader.m_pStrVarDef; - m_pPostOprtDef = a_Reader.m_pPostOprtDef; - m_pInfixOprtDef = a_Reader.m_pInfixOprtDef; - m_pOprtDef = a_Reader.m_pOprtDef; - m_bIgnoreUndefVar = a_Reader.m_bIgnoreUndefVar; - m_vIdentFun = a_Reader.m_vIdentFun; - m_pFactory = a_Reader.m_pFactory; - m_pFactoryData = a_Reader.m_pFactoryData; - m_iBrackets = a_Reader.m_iBrackets; - m_cArgSep = a_Reader.m_cArgSep; - m_fZero = a_Reader.m_fZero; - m_lastTok = a_Reader.m_lastTok; - } - - //--------------------------------------------------------------------------- - /** \brief Constructor. - - Create a Token reader and bind it to a parser object. - - \pre [assert] a_pParser may not be NULL - \post #m_pParser==a_pParser - \param a_pParent Parent parser object of the token reader. - */ - ParserTokenReader::ParserTokenReader(ParserBase *a_pParent) - :m_pParser(a_pParent) - ,m_strFormula() - ,m_iPos(0) - ,m_iSynFlags(0) - ,m_bIgnoreUndefVar(false) - ,m_pFunDef(NULL) - ,m_pPostOprtDef(NULL) - ,m_pInfixOprtDef(NULL) - ,m_pOprtDef(NULL) - ,m_pConstDef(NULL) - ,m_pStrVarDef(NULL) - ,m_pVarDef(NULL) - ,m_pFactory(NULL) - ,m_pFactoryData(NULL) - ,m_vIdentFun() - ,m_UsedVar() - ,m_fZero(0) - ,m_iBrackets(0) - ,m_lastTok() - ,m_cArgSep(',') - { - assert(m_pParser); - SetParent(m_pParser); - } - - //--------------------------------------------------------------------------- - /** \brief Create instance of a ParserTokenReader identical with this - and return its pointer. - - This is a factory method the calling function must take care of the object destruction. - - \return A new ParserTokenReader object. - \throw nothrow - */ - ParserTokenReader* ParserTokenReader::Clone(ParserBase *a_pParent) const - { -#if ENABLE_CPP11 - std::unique_ptr ptr(new ParserTokenReader(*this)); - ptr->SetParent(a_pParent); - return ptr.release(); -#else - ParserTokenReader* ptr = new ParserTokenReader(*this); - ptr->SetParent( a_pParent ); - return ptr; - // Upi Bhalla 13 June 2016: I think the original two lines below are wrong - // delete ptr; - // return NULL; -#endif - - } - - //--------------------------------------------------------------------------- - ParserTokenReader::token_type& ParserTokenReader::SaveBeforeReturn(const token_type &tok) - { - m_lastTok = tok; - return m_lastTok; - } - - //--------------------------------------------------------------------------- - void ParserTokenReader::AddValIdent(identfun_type a_pCallback) - { - // Use push_front is used to give user defined callbacks a higher priority than - // the built in ones. Otherwise reading hex numbers would not work - // since the "0" in "0xff" would always be read first making parsing of - // the rest impossible. - // reference: - // http://sourceforge.net/projects/muparser/forums/forum/462843/topic/4824956 - m_vIdentFun.push_front(a_pCallback); - } - - //--------------------------------------------------------------------------- - void ParserTokenReader::SetVarCreator(facfun_type a_pFactory, void *pUserData) - { - m_pFactory = a_pFactory; - m_pFactoryData = pUserData; - } - - //--------------------------------------------------------------------------- - /** \brief Return the current position of the token reader in the formula string. - - \return #m_iPos - \throw nothrow - */ - int ParserTokenReader::GetPos() const - { - return m_iPos; - } - - //--------------------------------------------------------------------------- - /** \brief Return a reference to the formula. - - \return #m_strFormula - \throw nothrow - */ - const string_type& ParserTokenReader::GetExpr() const - { - return m_strFormula; - } - - //--------------------------------------------------------------------------- - /** \brief Return a map containing the used variables only. */ - varmap_type& ParserTokenReader::GetUsedVar() - { - return m_UsedVar; - } - - //--------------------------------------------------------------------------- - /** \brief Initialize the token Reader. - - Sets the formula position index to zero and set Syntax flags to default for initial formula parsing. - \pre [assert] triggered if a_szFormula==0 - */ - void ParserTokenReader::SetFormula(const string_type &a_strFormula) - { - m_strFormula = a_strFormula; - ReInit(); - } - - //--------------------------------------------------------------------------- - /** \brief Set Flag that controls behaviour in case of undefined variables being found. - - If true, the parser does not throw an exception if an undefined variable is found. - otherwise it does. This variable is used internally only! - It suppresses a "undefined variable" exception in GetUsedVar(). - Those function should return a complete list of variables including - those the are not defined by the time of it's call. - */ - void ParserTokenReader::IgnoreUndefVar(bool bIgnore) - { - m_bIgnoreUndefVar = bIgnore; - } - - //--------------------------------------------------------------------------- - /** \brief Reset the token reader to the start of the formula. - - The syntax flags will be reset to a value appropriate for the - start of a formula. - \post #m_iPos==0, #m_iSynFlags = noOPT | noBC | noPOSTOP | noSTR - \throw nothrow - \sa ESynCodes - */ - void ParserTokenReader::ReInit() - { - m_iPos = 0; - m_iSynFlags = sfSTART_OF_LINE; - m_iBrackets = 0; - m_UsedVar.clear(); - m_lastTok = token_type(); - } - - //--------------------------------------------------------------------------- - /** \brief Read the next token from the string. */ - ParserTokenReader::token_type ParserTokenReader::ReadNextToken() - { - assert(m_pParser); - - const char_type *szFormula = m_strFormula.c_str(); - token_type tok; - - // Ignore all non printable characters when reading the expression - while (szFormula[m_iPos]>0 && szFormula[m_iPos]<=0x20) - ++m_iPos; - - if ( IsEOF(tok) ) return SaveBeforeReturn(tok); // Check for end of formula - if ( IsOprt(tok) ) return SaveBeforeReturn(tok); // Check for user defined binary operator - if ( IsFunTok(tok) ) return SaveBeforeReturn(tok); // Check for function token - if ( IsBuiltIn(tok) ) return SaveBeforeReturn(tok); // Check built in operators / tokens - if ( IsArgSep(tok) ) return SaveBeforeReturn(tok); // Check for function argument separators - if ( IsValTok(tok) ) return SaveBeforeReturn(tok); // Check for values / constant tokens - if ( IsVarTok(tok) ) return SaveBeforeReturn(tok); // Check for variable tokens - if ( IsStrVarTok(tok) ) return SaveBeforeReturn(tok); // Check for string variables - if ( IsString(tok) ) return SaveBeforeReturn(tok); // Check for String tokens - if ( IsInfixOpTok(tok) ) return SaveBeforeReturn(tok); // Check for unary operators - if ( IsPostOpTok(tok) ) return SaveBeforeReturn(tok); // Check for unary operators - - // Check String for undefined variable token. Done only if a - // flag is set indicating to ignore undefined variables. - // This is a way to conditionally avoid an error if - // undefined variables occur. - // (The GetUsedVar function must suppress the error for - // undefined variables in order to collect all variable - // names including the undefined ones.) - if ( (m_bIgnoreUndefVar || m_pFactory) && IsUndefVarTok(tok) ) - return SaveBeforeReturn(tok); - - // Check for unknown token - // - // !!! From this point on there is no exit without an exception possible... - // - string_type strTok; - int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos); - if (iEnd!=m_iPos) - Error(ecUNASSIGNABLE_TOKEN, m_iPos, strTok); - - Error(ecUNASSIGNABLE_TOKEN, m_iPos, m_strFormula.substr(m_iPos)); - return token_type(); // never reached - } - - //--------------------------------------------------------------------------- - void ParserTokenReader::SetParent(ParserBase *a_pParent) - { - m_pParser = a_pParent; - m_pFunDef = &a_pParent->m_FunDef; - m_pOprtDef = &a_pParent->m_OprtDef; - m_pInfixOprtDef = &a_pParent->m_InfixOprtDef; - m_pPostOprtDef = &a_pParent->m_PostOprtDef; - m_pVarDef = &a_pParent->m_VarDef; - m_pStrVarDef = &a_pParent->m_StrVarDef; - m_pConstDef = &a_pParent->m_ConstDef; - } - - //--------------------------------------------------------------------------- - /** \brief Extract all characters that belong to a certain charset. - - \param a_szCharSet [in] Const char array of the characters allowed in the token. - \param a_strTok [out] The string that consists entirely of characters listed in a_szCharSet. - \param a_iPos [in] Position in the string from where to start reading. - \return The Position of the first character not listed in a_szCharSet. - \throw nothrow - */ - int ParserTokenReader::ExtractToken(const char_type *a_szCharSet, - string_type &a_sTok, - int a_iPos) const - { - int iEnd = (int)m_strFormula.find_first_not_of(a_szCharSet, a_iPos); - - if (iEnd==(int)string_type::npos) - iEnd = (int)m_strFormula.length(); - - // Assign token string if there was something found - if (a_iPos!=iEnd) - a_sTok = string_type( m_strFormula.begin()+a_iPos, m_strFormula.begin()+iEnd); - - return iEnd; - } - - //--------------------------------------------------------------------------- - /** \brief Check Expression for the presence of a binary operator token. - - Userdefined binary operator "++" gives inconsistent parsing result for - the equations "a++b" and "a ++ b" if alphabetic characters are allowed - in operator tokens. To avoid this this function checks specifically - for operator tokens. - */ - int ParserTokenReader::ExtractOperatorToken(string_type &a_sTok, - int a_iPos) const - { - // Changed as per Issue 6: https://code.google.com/p/muparser/issues/detail?id=6 - int iEnd = (int)m_strFormula.find_first_not_of(m_pParser->ValidOprtChars(), a_iPos); - if (iEnd==(int)string_type::npos) - iEnd = (int)m_strFormula.length(); - - // Assign token string if there was something found - if (a_iPos!=iEnd) - { - a_sTok = string_type( m_strFormula.begin() + a_iPos, m_strFormula.begin() + iEnd); - return iEnd; - } - else - { - // There is still the chance of having to deal with an operator consisting exclusively - // of alphabetic characters. - return ExtractToken(MUP_CHARS, a_sTok, a_iPos); - } - } - - //--------------------------------------------------------------------------- - /** \brief Check if a built in operator or other token can be found - \param a_Tok [out] Operator token if one is found. This can either be a binary operator or an infix operator token. - \return true if an operator token has been found. - */ - bool ParserTokenReader::IsBuiltIn(token_type &a_Tok) - { - const char_type **const pOprtDef = m_pParser->GetOprtDef(), - *const szFormula = m_strFormula.c_str(); - - // Compare token with function and operator strings - // check string for operator/function - for (int i=0; pOprtDef[i]; i++) - { - std::size_t len( std::char_traits::length(pOprtDef[i]) ); - if ( string_type(pOprtDef[i]) == string_type(szFormula + m_iPos, szFormula + m_iPos + len) ) - { - switch(i) - { - //case cmAND: - //case cmOR: - //case cmXOR: - case cmLAND: - case cmLOR: - case cmLT: - case cmGT: - case cmLE: - case cmGE: - case cmNEQ: - case cmEQ: - case cmADD: - case cmSUB: - case cmMUL: - case cmDIV: - case cmPOW: - case cmASSIGN: - //if (len!=sTok.length()) - // continue; - - // The assignment operator need special treatment - if (i==cmASSIGN && m_iSynFlags & noASSIGN) - Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]); - - if (!m_pParser->HasBuiltInOprt()) continue; - if (m_iSynFlags & noOPT) - { - // Maybe its an infix operator not an operator - // Both operator types can share characters in - // their identifiers - if ( IsInfixOpTok(a_Tok) ) - return true; - - Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]); - } - - m_iSynFlags = noBC | noOPT | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE | noEND; - break; - - case cmBO: - if (m_iSynFlags & noBO) - Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); - - if (m_lastTok.GetCode()==cmFUNC) - m_iSynFlags = noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE; - else - m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN| noIF | noELSE; - - ++m_iBrackets; - break; - - case cmBC: - if (m_iSynFlags & noBC) - Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); - - m_iSynFlags = noBO | noVAR | noVAL | noFUN | noINFIXOP | noSTR | noASSIGN; - - if (--m_iBrackets<0) - Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); - break; - - case cmELSE: - if (m_iSynFlags & noELSE) - Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]); - - m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE; - break; - - case cmIF: - if (m_iSynFlags & noIF) - Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]); - - m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE; - break; - - default: // The operator is listed in c_DefaultOprt, but not here. This is a bad thing... - Error(ecINTERNAL_ERROR); - } // switch operator id - - m_iPos += (int)len; - a_Tok.Set( (ECmdCode)i, pOprtDef[i] ); - return true; - } // if operator string found - } // end of for all operator strings - - return false; - } - - //--------------------------------------------------------------------------- - bool ParserTokenReader::IsArgSep(token_type &a_Tok) - { - const char_type* szFormula = m_strFormula.c_str(); - - if (szFormula[m_iPos]==m_cArgSep) - { - // copy the separator into null terminated string - char_type szSep[2]; - szSep[0] = m_cArgSep; - szSep[1] = 0; - - if (m_iSynFlags & noARG_SEP) - Error(ecUNEXPECTED_ARG_SEP, m_iPos, szSep); - - m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN; - m_iPos++; - a_Tok.Set(cmARG_SEP, szSep); - return true; - } - - return false; - } - - //--------------------------------------------------------------------------- - /** \brief Check for End of Formula. - - \return true if an end of formula is found false otherwise. - \param a_Tok [out] If an eof is found the corresponding token will be stored there. - \throw nothrow - \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsString, IsInfixOpTok, IsPostOpTok - */ - bool ParserTokenReader::IsEOF(token_type &a_Tok) - { - const char_type* szFormula = m_strFormula.c_str(); - - // check for EOF - if ( !szFormula[m_iPos] /*|| szFormula[m_iPos] == '\n'*/) - { - if ( m_iSynFlags & noEND ) - Error(ecUNEXPECTED_EOF, m_iPos); - - if (m_iBrackets>0) - Error(ecMISSING_PARENS, m_iPos, _T(")")); - - m_iSynFlags = 0; - a_Tok.Set(cmEND); - return true; - } - - return false; - } - - //--------------------------------------------------------------------------- - /** \brief Check if a string position contains a unary infix operator. - \return true if a function token has been found false otherwise. - */ - bool ParserTokenReader::IsInfixOpTok(token_type &a_Tok) - { - string_type sTok; - int iEnd = ExtractToken(m_pParser->ValidInfixOprtChars(), sTok, m_iPos); - if (iEnd==m_iPos) - return false; - - // iterate over all postfix operator strings - funmap_type::const_reverse_iterator it = m_pInfixOprtDef->rbegin(); - for ( ; it!=m_pInfixOprtDef->rend(); ++it) - { - if (sTok.find(it->first)!=0) - continue; - - a_Tok.Set(it->second, it->first); - m_iPos += (int)it->first.length(); - - if (m_iSynFlags & noINFIXOP) - Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); - - m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN; - return true; - } - - return false; - -/* - a_Tok.Set(item->second, sTok); - m_iPos = (int)iEnd; - - if (m_iSynFlags & noINFIXOP) - Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); - - m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN; - return true; -*/ - } - - //--------------------------------------------------------------------------- - /** \brief Check whether the token at a given position is a function token. - \param a_Tok [out] If a value token is found it will be placed here. - \throw ParserException if Syntaxflags do not allow a function at a_iPos - \return true if a function token has been found false otherwise. - \pre [assert] m_pParser!=0 - */ - bool ParserTokenReader::IsFunTok(token_type &a_Tok) - { - string_type strTok; - int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos); - if (iEnd==m_iPos) - return false; - - funmap_type::const_iterator item = m_pFunDef->find(strTok); - if (item==m_pFunDef->end()) - return false; - - // Check if the next sign is an opening bracket - const char_type *szFormula = m_strFormula.c_str(); - if (szFormula[iEnd]!='(') - return false; - - a_Tok.Set(item->second, strTok); - - m_iPos = (int)iEnd; - if (m_iSynFlags & noFUN) - Error(ecUNEXPECTED_FUN, m_iPos-(int)a_Tok.GetAsString().length(), a_Tok.GetAsString()); - - m_iSynFlags = noANY ^ noBO; - return true; - } - - //--------------------------------------------------------------------------- - /** \brief Check if a string position contains a binary operator. - \param a_Tok [out] Operator token if one is found. This can either be a binary operator or an infix operator token. - \return true if an operator token has been found. - */ - bool ParserTokenReader::IsOprt(token_type &a_Tok) - { - const char_type *const szExpr = m_strFormula.c_str(); - string_type strTok; - - int iEnd = ExtractOperatorToken(strTok, m_iPos); - if (iEnd==m_iPos) - return false; - - // Check if the operator is a built in operator, if so ignore it here - const char_type **const pOprtDef = m_pParser->GetOprtDef(); - for (int i=0; m_pParser->HasBuiltInOprt() && pOprtDef[i]; ++i) - { - if (string_type(pOprtDef[i])==strTok) - return false; - } - - // Note: - // All tokens in oprt_bin_maptype are have been sorted by their length - // Long operators must come first! Otherwise short names (like: "add") that - // are part of long token names (like: "add123") will be found instead - // of the long ones. - // Length sorting is done with ascending length so we use a reverse iterator here. - funmap_type::const_reverse_iterator it = m_pOprtDef->rbegin(); - for ( ; it!=m_pOprtDef->rend(); ++it) - { - const string_type &sID = it->first; - if ( sID == string_type(szExpr + m_iPos, szExpr + m_iPos + sID.length()) ) - { - a_Tok.Set(it->second, strTok); - - // operator was found - if (m_iSynFlags & noOPT) - { - // An operator was found but is not expected to occur at - // this position of the formula, maybe it is an infix - // operator, not a binary operator. Both operator types - // can share characters in their identifiers. - if ( IsInfixOpTok(a_Tok) ) - return true; - else - { - // nope, no infix operator - return false; - //Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); - } - - } - - m_iPos += (int)sID.length(); - m_iSynFlags = noBC | noOPT | noARG_SEP | noPOSTOP | noEND | noASSIGN; - return true; - } - } - - return false; - } - - //--------------------------------------------------------------------------- - /** \brief Check if a string position contains a unary post value operator. */ - bool ParserTokenReader::IsPostOpTok(token_type &a_Tok) - { - // Do not check for postfix operators if they are not allowed at - // the current expression index. - // - // This will fix the bug reported here: - // - // http://sourceforge.net/tracker/index.php?func=detail&aid=3343891&group_id=137191&atid=737979 - // - if (m_iSynFlags & noPOSTOP) - return false; - // - - // Tricky problem with equations like "3m+5": - // m is a postfix operator, + is a valid sign for postfix operators and - // for binary operators parser detects "m+" as operator string and - // finds no matching postfix operator. - // - // This is a special case so this routine slightly differs from the other - // token readers. - - // Test if there could be a postfix operator - string_type sTok; - int iEnd = ExtractToken(m_pParser->ValidOprtChars(), sTok, m_iPos); - if (iEnd==m_iPos) - return false; - - // iterate over all postfix operator strings - funmap_type::const_reverse_iterator it = m_pPostOprtDef->rbegin(); - for ( ; it!=m_pPostOprtDef->rend(); ++it) - { - if (sTok.find(it->first)!=0) - continue; - - a_Tok.Set(it->second, sTok); - m_iPos += (int)it->first.length(); - - m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noSTR | noASSIGN; - return true; - } - - return false; - } - - //--------------------------------------------------------------------------- - /** \brief Check whether the token at a given position is a value token. - - Value tokens are either values or constants. - - \param a_Tok [out] If a value token is found it will be placed here. - \return true if a value token has been found. - */ - bool ParserTokenReader::IsValTok(token_type &a_Tok) - { - assert(m_pConstDef); - assert(m_pParser); - - string_type strTok; - value_type fVal(0); - int iEnd(0); - - // 2.) Check for user defined constant - // Read everything that could be a constant name - iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos); - if (iEnd!=m_iPos) - { - valmap_type::const_iterator item = m_pConstDef->find(strTok); - if (item!=m_pConstDef->end()) - { - m_iPos = iEnd; - a_Tok.SetVal(item->second, strTok); - - if (m_iSynFlags & noVAL) - Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok); - - m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; - return true; - } - } - - // 3.call the value recognition functions provided by the user - // Call user defined value recognition functions - std::list::const_iterator item = m_vIdentFun.begin(); - for (item = m_vIdentFun.begin(); item!=m_vIdentFun.end(); ++item) - { - int iStart = m_iPos; - if ( (*item)(m_strFormula.c_str() + m_iPos, &m_iPos, &fVal)==1 ) - { - // 2013-11-27 Issue 2: https://code.google.com/p/muparser/issues/detail?id=2 - strTok.assign(m_strFormula.c_str(), iStart, m_iPos-iStart); - - if (m_iSynFlags & noVAL) - Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok); - - a_Tok.SetVal(fVal, strTok); - m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; - return true; - } - } - - return false; - } - - //--------------------------------------------------------------------------- - /** \brief Check wheter a token at a given position is a variable token. - \param a_Tok [out] If a variable token has been found it will be placed here. - \return true if a variable token has been found. - */ - bool ParserTokenReader::IsVarTok(token_type &a_Tok) - { - if (m_pVarDef->empty()) - return false; - - string_type strTok; - int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos); - if (iEnd==m_iPos) - return false; - - varmap_type::const_iterator item = m_pVarDef->find(strTok); - if (item==m_pVarDef->end()) - return false; - - if (m_iSynFlags & noVAR) - Error(ecUNEXPECTED_VAR, m_iPos, strTok); - - m_pParser->OnDetectVar(&m_strFormula, m_iPos, iEnd); - - m_iPos = iEnd; - a_Tok.SetVar(item->second, strTok); - m_UsedVar[item->first] = item->second; // Add variable to used-var-list - - m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR; - -// Zur Info hier die SynFlags von IsVal(): -// m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; - return true; - } - - //--------------------------------------------------------------------------- - bool ParserTokenReader::IsStrVarTok(token_type &a_Tok) - { - if (!m_pStrVarDef || m_pStrVarDef->empty()) - return false; - - string_type strTok; - int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos); - if (iEnd==m_iPos) - return false; - - strmap_type::const_iterator item = m_pStrVarDef->find(strTok); - if (item==m_pStrVarDef->end()) - return false; - - if (m_iSynFlags & noSTR) - Error(ecUNEXPECTED_VAR, m_iPos, strTok); - - m_iPos = iEnd; - if (!m_pParser->m_vStringVarBuf.size()) - Error(ecINTERNAL_ERROR); - - a_Tok.SetString(m_pParser->m_vStringVarBuf[item->second], m_pParser->m_vStringVarBuf.size() ); - - m_iSynFlags = noANY ^ ( noBC | noOPT | noEND | noARG_SEP); - return true; - } - - - //--------------------------------------------------------------------------- - /** \brief Check wheter a token at a given position is an undefined variable. - - \param a_Tok [out] If a variable tom_pParser->m_vStringBufken has been found it will be placed here. - \return true if a variable token has been found. - \throw nothrow - */ - bool ParserTokenReader::IsUndefVarTok(token_type &a_Tok) - { - string_type strTok; - int iEnd( ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos) ); - if ( iEnd==m_iPos ) - return false; - - if (m_iSynFlags & noVAR) - { - // 20061021 added token string strTok instead of a_Tok.GetAsString() as the - // token identifier. - // related bug report: - // http://sourceforge.net/tracker/index.php?func=detail&aid=1578779&group_id=137191&atid=737979 - Error(ecUNEXPECTED_VAR, m_iPos - (int)a_Tok.GetAsString().length(), strTok); - } - - // If a factory is available implicitely create new variables - if (m_pFactory) - { - value_type *fVar = m_pFactory(strTok.c_str(), m_pFactoryData); - a_Tok.SetVar(fVar, strTok ); - - // Do not use m_pParser->DefineVar( strTok, fVar ); - // in order to define the new variable, it will clear the - // m_UsedVar array which will kill previously defined variables - // from the list - // This is safe because the new variable can never override an existing one - // because they are checked first! - (*m_pVarDef)[strTok] = fVar; - m_UsedVar[strTok] = fVar; // Add variable to used-var-list - } - else - { - a_Tok.SetVar((value_type*)&m_fZero, strTok); - m_UsedVar[strTok] = 0; // Add variable to used-var-list - } - - m_iPos = iEnd; - - // Call the variable factory in order to let it define a new parser variable - m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noINFIXOP | noSTR; - return true; - } - - - //--------------------------------------------------------------------------- - /** \brief Check wheter a token at a given position is a string. - \param a_Tok [out] If a variable token has been found it will be placed here. - \return true if a string token has been found. - \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsEOF, IsInfixOpTok, IsPostOpTok - \throw nothrow - */ - bool ParserTokenReader::IsString(token_type &a_Tok) - { - if (m_strFormula[m_iPos]!='"') - return false; - - string_type strBuf(&m_strFormula[m_iPos+1]); - std::size_t iEnd(0), iSkip(0); - - // parser over escaped '\"' end replace them with '"' - for(iEnd=(int)strBuf.find( _T("\"") ); iEnd!=0 && iEnd!=string_type::npos; iEnd=(int)strBuf.find( _T("\""), iEnd)) - { - if (strBuf[iEnd-1]!='\\') break; - strBuf.replace(iEnd-1, 2, _T("\"") ); - iSkip++; - } - - if (iEnd==string_type::npos) - Error(ecUNTERMINATED_STRING, m_iPos, _T("\"") ); - - string_type strTok(strBuf.begin(), strBuf.begin()+iEnd); - - if (m_iSynFlags & noSTR) - Error(ecUNEXPECTED_STR, m_iPos, strTok); - - m_pParser->m_vStringBuf.push_back(strTok); // Store string in internal buffer - a_Tok.SetString(strTok, m_pParser->m_vStringBuf.size()); - - m_iPos += (int)strTok.length() + 2 + (int)iSkip; // +2 wg Anführungszeichen; +iSkip für entfernte escape zeichen - m_iSynFlags = noANY ^ ( noARG_SEP | noBC | noOPT | noEND ); - - return true; - } - - //--------------------------------------------------------------------------- - /** \brief Create an error containing the parse error position. - - This function will create an Parser Exception object containing the error text and its position. - - \param a_iErrc [in] The error code of type #EErrorCodes. - \param a_iPos [in] The position where the error was detected. - \param a_strTok [in] The token string representation associated with the error. - \throw ParserException always throws thats the only purpose of this function. - */ - void ParserTokenReader::Error( EErrorCodes a_iErrc, - int a_iPos, - const string_type &a_sTok) const - { - m_pParser->Error(a_iErrc, a_iPos, a_sTok); - } - - //--------------------------------------------------------------------------- - void ParserTokenReader::SetArgSep(char_type cArgSep) - { - m_cArgSep = cArgSep; - } - - //--------------------------------------------------------------------------- - char_type ParserTokenReader::GetArgSep() const - { - return m_cArgSep; - } -} // namespace mu - diff --git a/external/tinyexpr/.travis.yml b/external/tinyexpr/.travis.yml new file mode 100644 index 00000000..d275c1a7 --- /dev/null +++ b/external/tinyexpr/.travis.yml @@ -0,0 +1,7 @@ +language: c + +compiler: + - clang + - gcc + +script: make diff --git a/external/tinyexpr/CMakeLists.txt b/external/tinyexpr/CMakeLists.txt new file mode 100644 index 00000000..e7ffe667 --- /dev/null +++ b/external/tinyexpr/CMakeLists.txt @@ -0,0 +1,64 @@ +cmake_minimum_required(VERSION 2.8.4) + +project(tinyexpr) + +option(TE_POW_FROM_RIGHT "Evaluate exponents from right to left." OFF) +option(TE_NAT_LOG "Define the log function as natural logarithm." OFF) +option(ENABLE_TESTS "Enabled tests" ON) +option(ENABLE_EXAMPALES "Enabled examples" ON) +option(ENABLE_BENCHMAKRS "Enabled benchamarks" ON) + +find_library(MATH_LIB m) + +set(SOURCE_FILES tinyexpr.c) +add_library(tinyexpr STATIC ${SOURCE_FILES}) + +if (TE_POW_FROM_RIGHT) + target_compile_definitions(tinyexpr PRIVATE TE_POW_FROM_RIGHT) +endif() +if (TE_NAT_LOG) + target_compile_definitions(tinyexpr PRIVATE TE_NAT_LOG) +endif() +target_link_libraries(tinyexpr ${MATH_LIB}) + +install(TARGETS tinyexpr ARCHIVE DESTINATION lib) +install(FILES tinyexpr.h DESTINATION include COMPONENT Devel) + +# Now tests. + +if (ENABLE_TESTS) + add_executable(tinyexpr_test test.c ) + target_link_libraries(tinyexpr_test tinyexpr) + + add_executable(tinyexpr_test_pr test.c) + target_compile_definitions(tinyexpr_test_pr PRIVATE TE_POW_FROM_RIGHT TE_NAT_LOG) + target_link_libraries(tinyexpr_test_pr tinyexpr ${MATH_LIB}) +endif() + +if (ENABLE_BENCHMAKRS) + add_executable(tinyexpr_benchmark benchmark.c) + target_link_libraries(tinyexpr_benchmark tinyexpr ${MATH_LIB}) +endif() + +if (ENABLE_EXAMPALES) + add_custom_target(examples) + file(GLOB _example_src "example*.c") + foreach( _ex_src ${_example_src}) + message(STATUS "Adding ${_ex_src} to examples" ) + get_filename_component(TGT_NAME ${_ex_src} NAME_WE) + set(TGT_EXAMPLE_NAME tinyexpr_${TGT_NAME}) + add_executable(${TGT_EXAMPLE_NAME} ${_ex_src} ) + target_link_libraries(${TGT_EXAMPLE_NAME} tinyexpr) + add_dependencies(examples ${TGT_EXAMPLE_NAME}) + endforeach() +endif() + +enable_testing() +add_test( NAME test1 + COMMAND $ + WORKING_DIRECTORY $CMAKE_CURRENT_BINARY_DIR} + ) +add_test( NAME test2 + COMMAND $ + WORKING_DIRECTORY $CMAKE_CURRENT_BINARY_DIR} + ) diff --git a/external/tinyexpr/CONTRIBUTING b/external/tinyexpr/CONTRIBUTING new file mode 100644 index 00000000..f27fc96f --- /dev/null +++ b/external/tinyexpr/CONTRIBUTING @@ -0,0 +1,10 @@ +A core strength of TinyExpr is that it is small and simple. This makes it easy +to add new features. However, if we keep adding new features, it'll no longer +be small or simple. In other words, each new feature corrodes away at the core +strength of TinyExpr. + +If you want to add a new feature, and you expect me to merge it, please discuss +it with me before you go to that work. Open an issue at +https://github.com/codeplea/tinyexpr and let us know what you're proposing. + +Bug fixes are always welcome and appreciated, of course. diff --git a/external/tinyexpr/LICENSE b/external/tinyexpr/LICENSE new file mode 100644 index 00000000..3a1bc572 --- /dev/null +++ b/external/tinyexpr/LICENSE @@ -0,0 +1,20 @@ +zlib License + +Copyright (C) 2015, 2016 Lewis Van Winkle + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgement in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + diff --git a/external/tinyexpr/README.md b/external/tinyexpr/README.md new file mode 100644 index 00000000..ad9f45a4 --- /dev/null +++ b/external/tinyexpr/README.md @@ -0,0 +1,319 @@ +[![Build Status](https://travis-ci.org/codeplea/tinyexpr.svg?branch=master)](https://travis-ci.org/codeplea/tinyexpr) + + +TinyExpr logo + +# TinyExpr + +TinyExpr is a very small recursive descent parser and evaluation engine for +math expressions. It's handy when you want to add the ability to evaluation +math expressions at runtime without adding a bunch of cruft to you project. + +In addition to the standard math operators and precedence, TinyExpr also supports +the standard C math functions and runtime binding of variables. + +## Features + +- **ANSI C with no dependencies**. +- Single source file and header file. +- Simple and fast. +- Implements standard operators precedence. +- Exposes standard C math functions (sin, sqrt, ln, etc.). +- Can add custom functions and variables easily. +- Can bind variables at eval-time. +- Released under the zlib license - free for nearly any use. +- Easy to use and integrate with your code +- Thread-safe, provided that your *malloc* is. + +## Building + +TinyExpr is self-contained in two files: `tinyexpr.c` and `tinyexpr.h`. To use +TinyExpr, simply add those two files to your project. + +## Short Example + +Here is a minimal example to evaluate an expression at runtime. + +```C + #include "tinyexpr.h" + printf("%f\n", te_interp("5*5", 0)); /* Prints 25. */ +``` + + +## Usage + +TinyExpr defines only four functions: + +```C + double te_interp(const char *expression, int *error); + te_expr *te_compile(const char *expression, const te_variable *variables, int var_count, int *error); + double te_eval(const te_expr *expr); + void te_free(te_expr *expr); +``` + +## te_interp +```C + double te_interp(const char *expression, int *error); +``` + +`te_interp()` takes an expression and immediately returns the result of it. If there +is a parse error, `te_interp()` returns NaN. + +If the `error` pointer argument is not 0, then `te_interp()` will set `*error` to the position +of the parse error on failure, and set `*error` to 0 on success. + +**example usage:** + +```C + int error; + + double a = te_interp("(5+5)", 0); /* Returns 10. */ + double b = te_interp("(5+5)", &error); /* Returns 10, error is set to 0. */ + double c = te_interp("(5+5", &error); /* Returns NaN, error is set to 4. */ +``` + +## te_compile, te_eval, te_free +```C + te_expr *te_compile(const char *expression, const te_variable *lookup, int lookup_len, int *error); + double te_eval(const te_expr *n); + void te_free(te_expr *n); +``` + +Give `te_compile()` an expression with unbound variables and a list of +variable names and pointers. `te_compile()` will return a `te_expr*` which can +be evaluated later using `te_eval()`. On failure, `te_compile()` will return 0 +and optionally set the passed in `*error` to the location of the parse error. + +You may also compile expressions without variables by passing `te_compile()`'s second +and thrid arguments as 0. + +Give `te_eval()` a `te_expr*` from `te_compile()`. `te_eval()` will evaluate the expression +using the current variable values. + +After you're finished, make sure to call `te_free()`. + +**example usage:** + +```C + double x, y; + /* Store variable names and pointers. */ + te_variable vars[] = {{"x", &x}, {"y", &y}}; + + int err; + /* Compile the expression with variables. */ + te_expr *expr = te_compile("sqrt(x^2+y^2)", vars, 2, &err); + + if (expr) { + x = 3; y = 4; + const double h1 = te_eval(expr); /* Returns 5. */ + + x = 5; y = 12; + const double h2 = te_eval(expr); /* Returns 13. */ + + te_free(expr); + } else { + printf("Parse error at %d\n", err); + } + +``` + +## Longer Example + +Here is a complete example that will evaluate an expression passed in from the command +line. It also does error checking and binds the variables `x` and `y` to *3* and *4*, respectively. + +```C + #include "tinyexpr.h" + #include + + int main(int argc, char *argv[]) + { + if (argc < 2) { + printf("Usage: example2 \"expression\"\n"); + return 0; + } + + const char *expression = argv[1]; + printf("Evaluating:\n\t%s\n", expression); + + /* This shows an example where the variables + * x and y are bound at eval-time. */ + double x, y; + te_variable vars[] = {{"x", &x}, {"y", &y}}; + + /* This will compile the expression and check for errors. */ + int err; + te_expr *n = te_compile(expression, vars, 2, &err); + + if (n) { + /* The variables can be changed here, and eval can be called as many + * times as you like. This is fairly efficient because the parsing has + * already been done. */ + x = 3; y = 4; + const double r = te_eval(n); printf("Result:\n\t%f\n", r); + te_free(n); + } else { + /* Show the user where the error is at. */ + printf("\t%*s^\nError near here", err-1, ""); + } + + return 0; + } +``` + + +This produces the output: + + $ example2 "sqrt(x^2+y2)" + Evaluating: + sqrt(x^2+y2) + ^ + Error near here + + + $ example2 "sqrt(x^2+y^2)" + Evaluating: + sqrt(x^2+y^2) + Result: + 5.000000 + + +## Binding to Custom Functions + +TinyExpr can also call to custom functions implemented in C. Here is a short example: + +```C +double my_sum(double a, double b) { + /* Example C function that adds two numbers together. */ + return a + b; +} + +te_variable vars[] = { + {"mysum", my_sum, TE_FUNCTION2} /* TE_FUNCTION2 used because my_sum takes two arguments. */ +}; + +te_expr *n = te_compile("mysum(5, 6)", vars, 1, 0); + +``` + + +## How it works + +`te_compile()` uses a simple recursive descent parser to compile your +expression into a syntax tree. For example, the expression `"sin x + 1/4"` +parses as: + +![example syntax tree](doc/e1.png?raw=true) + +`te_compile()` also automatically prunes constant branches. In this example, +the compiled expression returned by `te_compile()` would become: + +![example syntax tree](doc/e2.png?raw=true) + +`te_eval()` will automatically load in any variables by their pointer, and then evaluate +and return the result of the expression. + +`te_free()` should always be called when you're done with the compiled expression. + + +## Speed + + +TinyExpr is pretty fast compared to C when the expression is short, when the +expression does hard calculations (e.g. exponentiation), and when some of the +work can be simplified by `te_compile()`. TinyExpr is slow compared to C when the +expression is long and involves only basic arithmetic. + +Here is some example performance numbers taken from the included +**benchmark.c** program: + +| Expression | te_eval time | native C time | slowdown | +| :------------- |-------------:| -----:|----:| +| sqrt(a^1.5+a^2.5) | 15,641 ms | 14,478 ms | 8% slower | +| a+5 | 765 ms | 563 ms | 36% slower | +| a+(5*2) | 765 ms | 563 ms | 36% slower | +| (a+5)*2 | 1422 ms | 563 ms | 153% slower | +| (1/(a+1)+2/(a+2)+3/(a+3)) | 5,516 ms | 1,266 ms | 336% slower | + + + +## Grammar + +TinyExpr parses the following grammar: + + = {"," } + = {("+" | "-") } + = {("*" | "/" | "%") } + = {"^" } + = {("-" | "+")} + = + | + | {"(" ")"} + | + | "(" {"," } ")" + | "(" ")" + +In addition, whitespace between tokens is ignored. + +Valid variable names consist of a lower case letter followed by any combination +of: lower case letters *a* through *z*, the digits *0* through *9*, and +underscore. Constants can be integers, decimal numbers, or in scientific +notation (e.g. *1e3* for *1000*). A leading zero is not required (e.g. *.5* +for *0.5*) + + +## Functions supported + +TinyExpr supports addition (+), subtraction/negation (-), multiplication (\*), +division (/), exponentiation (^) and modulus (%) with the normal operator +precedence (the one exception being that exponentiation is evaluated +left-to-right, but this can be changed - see below). + +The following C math functions are also supported: + +- abs (calls to *fabs*), acos, asin, atan, atan2, ceil, cos, cosh, exp, floor, ln (calls to *log*), log (calls to *log10* by default, see below), log10, pow, sin, sinh, sqrt, tan, tanh + +The following functions are also built-in and provided by TinyExpr: + +- fac (factorials e.g. `fac 5` == 120) +- ncr (combinations e.g. `ncr(6,2)` == 15) +- npr (permutations e.g. `npr(6,2)` == 30) + +Also, the following constants are available: + +- `pi`, `e` + + +## Compile-time options + + +By default, TinyExpr does exponentiation from left to right. For example: + +`a^b^c == (a^b)^c` and `-a^b == (-a)^b` + +This is by design. It's the way that spreadsheets do it (e.g. Excel, Google Sheets). + + +If you would rather have exponentiation work from right to left, you need to +define `TE_POW_FROM_RIGHT` when compiling `tinyexpr.c`. There is a +commented-out define near the top of that file. With this option enabled, the +behaviour is: + +`a^b^c == a^(b^c)` and `-a^b == -(a^b)` + +That will match how many scripting languages do it (e.g. Python, Ruby). + +Also, if you'd like `log` to default to the natural log instead of `log10`, +then you can define `TE_NAT_LOG`. + +## Hints + +- All functions/types start with the letters *te*. + +- To allow constant optimization, surround constant expressions in parentheses. + For example "x+(1+5)" will evaluate the "(1+5)" expression at compile time and + compile the entire expression as "x+6", saving a runtime calculation. The + parentheses are important, because TinyExpr will not change the order of + evaluation. If you instead compiled "x+1+5" TinyExpr will insist that "1" is + added to "x" first, and "5" is added the result second. + diff --git a/external/tinyexpr/benchmark.c b/external/tinyexpr/benchmark.c new file mode 100644 index 00000000..31d18faf --- /dev/null +++ b/external/tinyexpr/benchmark.c @@ -0,0 +1,125 @@ +/* + * TINYEXPR - Tiny recursive descent parser and evaluation engine in C + * + * Copyright (c) 2015, 2016 Lewis Van Winkle + * + * http://CodePlea.com + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgement in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ + +#include +#include +#include +#include "tinyexpr.h" + + + +#define loops 10000 + + + +typedef double (*function1)(double); + +void bench(const char *expr, function1 func) { + int i, j; + volatile double d; + double tmp; + clock_t start; + + te_variable lk = {"a", &tmp}; + + printf("Expression: %s\n", expr); + + printf("native "); + start = clock(); + d = 0; + for (j = 0; j < loops; ++j) + for (i = 0; i < loops; ++i) { + tmp = i; + d += func(tmp); + } + const int nelapsed = (clock() - start) * 1000 / CLOCKS_PER_SEC; + + /*Million floats per second input.*/ + printf(" %.5g", d); + if (nelapsed) + printf("\t%5dms\t%5dmfps\n", nelapsed, loops * loops / nelapsed / 1000); + else + printf("\tinf\n"); + + + + + printf("interp "); + te_expr *n = te_compile(expr, &lk, 1, 0); + start = clock(); + d = 0; + for (j = 0; j < loops; ++j) + for (i = 0; i < loops; ++i) { + tmp = i; + d += te_eval(n); + } + const int eelapsed = (clock() - start) * 1000 / CLOCKS_PER_SEC; + te_free(n); + + /*Million floats per second input.*/ + printf(" %.5g", d); + if (eelapsed) + printf("\t%5dms\t%5dmfps\n", eelapsed, loops * loops / eelapsed / 1000); + else + printf("\tinf\n"); + + + printf("%.2f%% longer\n", (((double)eelapsed / nelapsed) - 1.0) * 100.0); + + + printf("\n"); +} + + +double a5(double a) { + return a+5; +} + +double a52(double a) { + return (a+5)*2; +} + +double a10(double a) { + return a+(5*2); +} + +double as(double a) { + return sqrt(pow(a, 1.5) + pow(a, 2.5)); +} + +double al(double a) { + return (1/(a+1)+2/(a+2)+3/(a+3)); +} + +int main(int argc, char *argv[]) +{ + + bench("sqrt(a^1.5+a^2.5)", as); + bench("a+5", a5); + bench("a+(5*2)", a10); + bench("(a+5)*2", a52); + bench("(1/(a+1)+2/(a+2)+3/(a+3))", al); + + return 0; +} diff --git a/external/tinyexpr/doc/e1.dot b/external/tinyexpr/doc/e1.dot new file mode 100644 index 00000000..6a631aba --- /dev/null +++ b/external/tinyexpr/doc/e1.dot @@ -0,0 +1,8 @@ +digraph G { + "+" -> "sin"; + "+" -> div; + "sin" -> "x"; + div -> "1"; + div -> "4"; + div [label="÷"] +} diff --git a/external/tinyexpr/doc/e1.png b/external/tinyexpr/doc/e1.png new file mode 100644 index 0000000000000000000000000000000000000000..7f7a4500b173697057d247a96834cb88a0341fb1 GIT binary patch literal 11883 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 b36$TOm=n1+D}>?pI70QNx?-`sng9O){!(!~ literal 0 HcmV?d00001 diff --git a/external/tinyexpr/doc/e2.dot b/external/tinyexpr/doc/e2.dot new file mode 100644 index 00000000..d6067228 --- /dev/null +++ b/external/tinyexpr/doc/e2.dot @@ -0,0 +1,5 @@ +digraph G { + "+" -> "sin"; + "+" -> "0.25"; + "sin" -> "x"; +} diff --git a/external/tinyexpr/doc/e2.png b/external/tinyexpr/doc/e2.png new file mode 100644 index 0000000000000000000000000000000000000000..cebb1dbc4fb3b0679fc4753c29a4509d54e805c6 GIT binary patch literal 10032 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 PIE1XEqD1*4gMj}7`r*d= literal 0 HcmV?d00001 diff --git a/external/tinyexpr/example.c b/external/tinyexpr/example.c new file mode 100644 index 00000000..040093fd --- /dev/null +++ b/external/tinyexpr/example.c @@ -0,0 +1,10 @@ +#include "tinyexpr.h" +#include + +int main(int argc, char *argv[]) +{ + const char *c = "sqrt(5^2+7^2+11^2+(8-2)^2)"; + double r = te_interp(c, 0); + printf("The expression:\n\t%s\nevaluates to:\n\t%f\n", c, r); + return 0; +} diff --git a/external/tinyexpr/example2.c b/external/tinyexpr/example2.c new file mode 100644 index 00000000..9c2274d8 --- /dev/null +++ b/external/tinyexpr/example2.c @@ -0,0 +1,42 @@ +#include "tinyexpr.h" +#include +#include + +double H( double a) +{ + return pow(a, 3.0); +} + +int main(int argc, char *argv[]) +{ + const char* expr = "p + g + l + len + dia + h(1-l)"; + printf("Evaluating:\n\t%s\n", expr); + + /* This shows an example where the variables + * x and y are bound at eval-time. */ + double p, g, L, len, dia; + te_variable vars[] = {{"p", &p}, {"g", &g}, {"l", &L}, {"len", &len}, {"dia", &dia} + , { "h", H, TE_FUNCTION1} + }; + + + /* This will compile the expression and check for errors. */ + int err; + te_expr *n = te_compile(expr, vars, 6, &err); + + if (n) { + /* The variables can be changed here, and eval can be called as many + * times as you like. This is fairly efficient because the parsing has + * already been done. */ + p = 1; g = 0.1; L = 10; len = 2; dia = 0.2; + const double r = te_eval(n); printf("Result:\n\t%f\n", r); + + te_free(n); + } else { + /* Show the user where the error is at. */ + printf("\t%*s^\nError near here", err-1, ""); + } + + + return 0; +} diff --git a/external/tinyexpr/example3.c b/external/tinyexpr/example3.c new file mode 100644 index 00000000..80fe9da4 --- /dev/null +++ b/external/tinyexpr/example3.c @@ -0,0 +1,35 @@ +#include "tinyexpr.h" +#include + + +/* An example of calling a C function. */ +double my_sum(double a, double b) { + printf("Called C function with %f and %f.\n", a, b); + return a + b; +} + + +int main(int argc, char *argv[]) +{ + te_variable vars[] = { + {"mysum", my_sum, TE_FUNCTION2} + }; + + const char *expression = "mysum(5, 6)"; + printf("Evaluating:\n\t%s\n", expression); + + int err; + te_expr *n = te_compile(expression, vars, 1, &err); + + if (n) { + const double r = te_eval(n); + printf("Result:\n\t%f\n", r); + te_free(n); + } else { + /* Show the user where the error is at. */ + printf("\t%*s^\nError near here", err-1, ""); + } + + + return 0; +} diff --git a/external/tinyexpr/minctest.h b/external/tinyexpr/minctest.h new file mode 100644 index 00000000..6180de84 --- /dev/null +++ b/external/tinyexpr/minctest.h @@ -0,0 +1,128 @@ +/* + * + * MINCTEST - Minimal C Test Library - 0.1 + * + * Copyright (c) 2014, 2015 Lewis Van Winkle + * + * http://CodePlea.com + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgement in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + * + */ + + + +/* + * MINCTEST - Minimal testing library for C + * + * + * Example: + * + * void test1() { + * lok('a' == 'a'); + * } + * + * void test2() { + * lequal(5, 6); + * lfequal(5.5, 5.6); + * } + * + * int main() { + * lrun("test1", test1); + * lrun("test2", test2); + * lresults(); + * return lfails != 0; + * } + * + * + * + * Hints: + * All functions/variables start with the letter 'l'. + * + */ + + +#ifndef __MINCTEST_H__ +#define __MINCTEST_H__ + +#include +#include +#include + + +/* How far apart can floats be before we consider them unequal. */ +#define LTEST_FLOAT_TOLERANCE 0.001 + + +/* Track the number of passes, fails. */ +/* NB this is made for all tests to be in one file. */ +static int ltests = 0; +static int lfails = 0; + + +/* Display the test results. */ +#define lresults() do {\ + if (lfails == 0) {\ + printf("ALL TESTS PASSED (%d/%d)\n", ltests, ltests);\ + } else {\ + printf("SOME TESTS FAILED (%d/%d)\n", ltests-lfails, ltests);\ + }\ +} while (0) + + +/* Run a test. Name can be any string to print out, test is the function name to call. */ +#define lrun(name, test) do {\ + const int ts = ltests;\ + const int fs = lfails;\ + const clock_t start = clock();\ + printf("\t%-14s", name);\ + test();\ + printf("pass:%2d fail:%2d %4dms\n",\ + (ltests-ts)-(lfails-fs), lfails-fs,\ + (int)((clock() - start) * 1000 / CLOCKS_PER_SEC));\ +} while (0) + + +/* Assert a true statement. */ +#define lok(test) do {\ + ++ltests;\ + if (!(test)) {\ + ++lfails;\ + printf("%s:%d error \n", __FILE__, __LINE__);\ + }} while (0) + + +/* Assert two integers are equal. */ +#define lequal(a, b) do {\ + ++ltests;\ + if ((a) != (b)) {\ + ++lfails;\ + printf("%s:%d (%d != %d)\n", __FILE__, __LINE__, (a), (b));\ + }} while (0) + + +/* Assert two floats are equal (Within LTEST_FLOAT_TOLERANCE). */ +#define lfequal(a, b) do {\ + ++ltests;\ + const double __LF_COMPARE = fabs((double)(a)-(double)(b));\ + if (__LF_COMPARE > LTEST_FLOAT_TOLERANCE || (__LF_COMPARE != __LF_COMPARE)) {\ + ++lfails;\ + printf("%s:%d (%f != %f)\n", __FILE__, __LINE__, (double)(a), (double)(b));\ + }} while (0) + + +#endif /*__MINCTEST_H__*/ diff --git a/external/tinyexpr/test.c b/external/tinyexpr/test.c new file mode 100644 index 00000000..b6b8f7da --- /dev/null +++ b/external/tinyexpr/test.c @@ -0,0 +1,825 @@ +/* + * TINYEXPR - Tiny recursive descent parser and evaluation engine in C + * + * Copyright (c) 2015, 2016 Lewis Van Winkle + * + * http://CodePlea.com + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgement in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ + +#include "tinyexpr.h" +#include +#include "minctest.h" + + +typedef struct { + const char *expr; + double answer; +} test_case; + +typedef struct { + const char *expr1; + const char *expr2; +} test_equ; + + + +void test_results() { + test_case cases[] = { + {"1", 1}, + {"1 ", 1}, + {"(1)", 1}, + + {"1e-1", 0.1}, + {"1e1", 10}, + + {"pi", 3.14159}, + {"atan(1)*4 - pi", 0}, + {"e", 2.71828}, + + {"2+1", 2+1}, + {"(((2+(1))))", 2+1}, + {"3+2", 3+2}, + + {"3+2+4", 3+2+4}, + {"(3+2)+4", 3+2+4}, + {"3+(2+4)", 3+2+4}, + {"(3+2+4)", 3+2+4}, + + {"3*2*4", 3*2*4}, + {"(3*2)*4", 3*2*4}, + {"3*(2*4)", 3*2*4}, + {"(3*2*4)", 3*2*4}, + + {"3-2-4", 3-2-4}, + {"(3-2)-4", (3-2)-4}, + {"3-(2-4)", 3-(2-4)}, + {"(3-2-4)", 3-2-4}, + + {"3/2/4", 3.0/2.0/4.0}, + {"(3/2)/4", (3.0/2.0)/4.0}, + {"3/(2/4)", 3.0/(2.0/4.0)}, + {"(3/2/4)", 3.0/2.0/4.0}, + + {"(3*2/4)", 3.0*2.0/4.0}, + {"(3/2*4)", 3.0/2.0*4.0}, + {"3*(2/4)", 3.0*(2.0/4.0)}, + + {"asin sin .5", 0.5}, + {"sin asin .5", 0.5}, + {"ln exp .5", 0.5}, + {"exp ln .5", 0.5}, + + {"asin sin-.5", -0.5}, + {"asin sin-0.5", -0.5}, + {"asin sin -0.5", -0.5}, + {"asin (sin -0.5)", -0.5}, + {"asin (sin (-0.5))", -0.5}, + {"asin sin (-0.5)", -0.5}, + {"(asin sin (-0.5))", -0.5}, + + {"log10 1000", 3}, + {"log10 1e3", 3}, + {"log10 1000", 3}, + {"log10 1e3", 3}, + {"log10(1000)", 3}, + {"log10(1e3)", 3}, + {"log10 1.0e3", 3}, + {"10^5*5e-5", 5}, + +#ifdef TE_NAT_LOG + {"log 1000", 6.9078}, + {"log e", 1}, + {"log (e^10)", 10}, +#else + {"log 1000", 3}, +#endif + + {"ln (e^10)", 10}, + {"100^.5+1", 11}, + {"100 ^.5+1", 11}, + {"100^+.5+1", 11}, + {"100^--.5+1", 11}, + {"100^---+-++---++-+-+-.5+1", 11}, + + {"100^-.5+1", 1.1}, + {"100^---.5+1", 1.1}, + {"100^+---.5+1", 1.1}, + {"1e2^+---.5e0+1e0", 1.1}, + {"--(1e2^(+(-(-(-.5e0))))+1e0)", 1.1}, + + {"sqrt 100 + 7", 17}, + {"sqrt 100 * 7", 70}, + {"sqrt (100 * 100)", 100}, + + {"1,2", 2}, + {"1,2+1", 3}, + {"1+1,2+2,2+1", 3}, + {"1,2,3", 3}, + {"(1,2),3", 3}, + {"1,(2,3)", 3}, + {"-(1,(2,3))", -3}, + + {"2^2", 4}, + {"pow(2,2)", 4}, + + {"atan2(1,1)", 0.7854}, + {"atan2(1,2)", 0.4636}, + {"atan2(2,1)", 1.1071}, + {"atan2(3,4)", 0.6435}, + {"atan2(3+3,4*2)", 0.6435}, + {"atan2(3+3,(4*2))", 0.6435}, + {"atan2((3+3),4*2)", 0.6435}, + {"atan2((3+3),(4*2))", 0.6435}, + + }; + + + int i; + for (i = 0; i < sizeof(cases) / sizeof(test_case); ++i) { + const char *expr = cases[i].expr; + const double answer = cases[i].answer; + + int err; + const double ev = te_interp(expr, &err); + lok(!err); + lfequal(ev, answer); + + if (err) { + printf("FAILED: %s (%d)\n", expr, err); + } + } +} + + +void test_syntax() { + test_case errors[] = { + {"", 1}, + {"1+", 2}, + {"1)", 2}, + {"(1", 2}, + {"1**1", 3}, + {"1*2(+4", 4}, + {"1*2(1+4", 4}, + {"a+5", 1}, + /** {"A+5", 1}, */ + /** {"Aa+5", 1}, */ // No longer an error. + {"1^^5", 3}, + {"1**5", 3}, + {"sin(cos5", 8}, + }; + + + int i; + for (i = 0; i < sizeof(errors) / sizeof(test_case); ++i) { + const char *expr = errors[i].expr; + const int e = errors[i].answer; + + int err; + const double r = te_interp(expr, &err); + lequal(err, e); + lok(r != r); + + te_expr *n = te_compile(expr, 0, 0, &err); + lequal(err, e); + lok(!n); + + if (err != e) { + printf("FAILED: %s\n", expr); + } + + const double k = te_interp(expr, 0); + lok(k != k); + } +} + + +void test_nans() { + + const char *nans[] = { + "0/0", + "1%0", + "1%(1%0)", + "(1%0)%1", + "fac(-1)", + "ncr(2, 4)", + "ncr(-2, 4)", + "ncr(2, -4)", + "npr(2, 4)", + "npr(-2, 4)", + "npr(2, -4)", + }; + + int i; + for (i = 0; i < sizeof(nans) / sizeof(const char *); ++i) { + const char *expr = nans[i]; + + int err; + const double r = te_interp(expr, &err); + lequal(err, 0); + lok(r != r); + + te_expr *n = te_compile(expr, 0, 0, &err); + lok(n); + lequal(err, 0); + const double c = te_eval(n); + lok(c != c); + te_free(n); + } +} + + +void test_infs() { + + const char *infs[] = { + "1/0", + "log(0)", + "pow(2,10000000)", + "fac(300)", + "ncr(300,100)", + "ncr(300000,100)", + "ncr(300000,100)*8", + "npr(3,2)*ncr(300000,100)", + "npr(100,90)", + "npr(30,25)", + }; + + int i; + for (i = 0; i < sizeof(infs) / sizeof(const char *); ++i) { + const char *expr = infs[i]; + + int err; + const double r = te_interp(expr, &err); + lequal(err, 0); + lok(r == r + 1); + + te_expr *n = te_compile(expr, 0, 0, &err); + lok(n); + lequal(err, 0); + const double c = te_eval(n); + lok(c == c + 1); + te_free(n); + } +} + + +void test_variables() { + + double x, y, test; + te_variable lookup[] = {{"x", &x}, {"y", &y}, {"te_st", &test}}; + + int err; + + te_expr *expr1 = te_compile("cos x + sin y", lookup, 2, &err); + lok(expr1); + lok(!err); + + te_expr *expr2 = te_compile("x+x+x-y", lookup, 2, &err); + lok(expr2); + lok(!err); + + te_expr *expr3 = te_compile("x*y^3", lookup, 2, &err); + lok(expr3); + lok(!err); + + te_expr *expr4 = te_compile("te_st+5", lookup, 3, &err); + lok(expr4); + lok(!err); + + for (y = 2; y < 3; ++y) { + for (x = 0; x < 5; ++x) { + double ev; + + ev = te_eval(expr1); + lfequal(ev, cos(x) + sin(y)); + + ev = te_eval(expr2); + lfequal(ev, x+x+x-y); + + ev = te_eval(expr3); + lfequal(ev, x*y*y*y); + + test = x; + ev = te_eval(expr4); + lfequal(ev, x+5); + } + } + + te_free(expr1); + te_free(expr2); + te_free(expr3); + te_free(expr4); + + + + te_expr *expr5 = te_compile("xx*y^3", lookup, 2, &err); + lok(!expr5); + lok(err); + + te_expr *expr6 = te_compile("tes", lookup, 3, &err); + lok(!expr6); + lok(err); + + te_expr *expr7 = te_compile("sinn x", lookup, 2, &err); + lok(!expr7); + lok(err); + + te_expr *expr8 = te_compile("si x", lookup, 2, &err); + lok(!expr8); + lok(err); +} + + + +#define cross_check(a, b) do {\ + if ((b)!=(b)) break;\ + expr = te_compile((a), lookup, 2, &err);\ + lfequal(te_eval(expr), (b));\ + lok(!err);\ + te_free(expr);\ +}while(0) + +void test_functions() { + + double x, y; + te_variable lookup[] = {{"x", &x}, {"y", &y}}; + + int err; + te_expr *expr; + + for (x = -5; x < 5; x += .2) { + cross_check("abs x", fabs(x)); + cross_check("acos x", acos(x)); + cross_check("asin x", asin(x)); + cross_check("atan x", atan(x)); + cross_check("ceil x", ceil(x)); + cross_check("cos x", cos(x)); + cross_check("cosh x", cosh(x)); + cross_check("exp x", exp(x)); + cross_check("floor x", floor(x)); + cross_check("ln x", log(x)); + cross_check("log10 x", log10(x)); + cross_check("sin x", sin(x)); + cross_check("sinh x", sinh(x)); + cross_check("sqrt x", sqrt(x)); + cross_check("tan x", tan(x)); + cross_check("tanh x", tanh(x)); + + for (y = -2; y < 2; y += .2) { + if (fabs(x) < 0.01) break; + cross_check("atan2(x,y)", atan2(x, y)); + cross_check("pow(x,y)", pow(x, y)); + } + } +} + + +double sum0() { + return 6; +} +double sum1(double a) { + return a * 2; +} +double sum2(double a, double b) { + return a + b; +} +double sum3(double a, double b, double c) { + return a + b + c; +} +double sum4(double a, double b, double c, double d) { + return a + b + c + d; +} +double sum5(double a, double b, double c, double d, double e) { + return a + b + c + d + e; +} +double sum6(double a, double b, double c, double d, double e, double f) { + return a + b + c + d + e + f; +} +double sum7(double a, double b, double c, double d, double e, double f, double g) { + return a + b + c + d + e + f + g; +} + + +void test_dynamic() { + + double x, f; + te_variable lookup[] = { + {"x", &x}, + {"f", &f}, + {"sum0", sum0, TE_FUNCTION0}, + {"sum1", sum1, TE_FUNCTION1}, + {"sum2", sum2, TE_FUNCTION2}, + {"sum3", sum3, TE_FUNCTION3}, + {"sum4", sum4, TE_FUNCTION4}, + {"sum5", sum5, TE_FUNCTION5}, + {"sum6", sum6, TE_FUNCTION6}, + {"sum7", sum7, TE_FUNCTION7}, + }; + + test_case cases[] = { + {"x", 2}, + {"f+x", 7}, + {"x+x", 4}, + {"x+f", 7}, + {"f+f", 10}, + {"f+sum0", 11}, + {"sum0+sum0", 12}, + {"sum0()+sum0", 12}, + {"sum0+sum0()", 12}, + {"sum0()+(0)+sum0()", 12}, + {"sum1 sum0", 12}, + {"sum1(sum0)", 12}, + {"sum1 f", 10}, + {"sum1 x", 4}, + {"sum2 (sum0, x)", 8}, + {"sum3 (sum0, x, 2)", 10}, + {"sum2(2,3)", 5}, + {"sum3(2,3,4)", 9}, + {"sum4(2,3,4,5)", 14}, + {"sum5(2,3,4,5,6)", 20}, + {"sum6(2,3,4,5,6,7)", 27}, + {"sum7(2,3,4,5,6,7,8)", 35}, + }; + + x = 2; + f = 5; + + int i; + for (i = 0; i < sizeof(cases) / sizeof(test_case); ++i) { + const char *expr = cases[i].expr; + const double answer = cases[i].answer; + + int err; + te_expr *ex = te_compile(expr, lookup, sizeof(lookup)/sizeof(te_variable), &err); + lok(ex); + lfequal(te_eval(ex), answer); + te_free(ex); + } +} + + +double clo0(void *context) { + if (context) return *((double*)context) + 6; + return 6; +} +double clo1(void *context, double a) { + if (context) return *((double*)context) + a * 2; + return a * 2; +} +double clo2(void *context, double a, double b) { + if (context) return *((double*)context) + a + b; + return a + b; +} + +double cell(void *context, double a) { + double *c = context; + return c[(int)a]; +} + +void test_closure() { + + double extra; + double c[] = {5,6,7,8,9}; + + te_variable lookup[] = { + {"c0", clo0, TE_CLOSURE0, &extra}, + {"c1", clo1, TE_CLOSURE1, &extra}, + {"c2", clo2, TE_CLOSURE2, &extra}, + {"cell", cell, TE_CLOSURE1, c}, + }; + + test_case cases[] = { + {"c0", 6}, + {"c1 4", 8}, + {"c2 (10, 20)", 30}, + }; + + int i; + for (i = 0; i < sizeof(cases) / sizeof(test_case); ++i) { + const char *expr = cases[i].expr; + const double answer = cases[i].answer; + + int err; + te_expr *ex = te_compile(expr, lookup, sizeof(lookup)/sizeof(te_variable), &err); + lok(ex); + + extra = 0; + lfequal(te_eval(ex), answer + extra); + + extra = 10; + lfequal(te_eval(ex), answer + extra); + + te_free(ex); + } + + + test_case cases2[] = { + {"cell 0", 5}, + {"cell 1", 6}, + {"cell 0 + cell 1", 11}, + {"cell 1 * cell 3 + cell 4", 57}, + }; + + for (i = 0; i < sizeof(cases2) / sizeof(test_case); ++i) { + const char *expr = cases2[i].expr; + const double answer = cases2[i].answer; + + int err; + te_expr *ex = te_compile(expr, lookup, sizeof(lookup)/sizeof(te_variable), &err); + lok(ex); + lfequal(te_eval(ex), answer); + te_free(ex); + } +} + +void test_optimize() { + + test_case cases[] = { + {"5+5", 10}, + {"pow(2,2)", 4}, + {"sqrt 100", 10}, + {"pi * 2", 6.2832}, + }; + + int i; + for (i = 0; i < sizeof(cases) / sizeof(test_case); ++i) { + const char *expr = cases[i].expr; + const double answer = cases[i].answer; + + int err; + te_expr *ex = te_compile(expr, 0, 0, &err); + lok(ex); + + /* The answer should be know without + * even running eval. */ + lfequal(ex->value, answer); + lfequal(te_eval(ex), answer); + + te_free(ex); + } +} + +void test_pow() { +#ifdef TE_POW_FROM_RIGHT + test_equ cases[] = { + {"2^3^4", "2^(3^4)"}, + {"-2^2", "-(2^2)"}, + {"--2^2", "(2^2)"}, + {"---2^2", "-(2^2)"}, + {"-(2)^2", "-(2^2)"}, + {"-(2*1)^2", "-(2^2)"}, + {"-2^2", "-4"}, + {"2^1.1^1.2^1.3", "2^(1.1^(1.2^1.3))"}, + {"-a^b", "-(a^b)"}, + {"-a^-b", "-(a^-b)"} + }; +#else + test_equ cases[] = { + {"2^3^4", "(2^3)^4"}, + {"-2^2", "(-2)^2"}, + {"--2^2", "2^2"}, + {"---2^2", "(-2)^2"}, + {"-2^2", "4"}, + {"2^1.1^1.2^1.3", "((2^1.1)^1.2)^1.3"}, + {"-a^b", "(-a)^b"}, + {"-a^-b", "(-a)^(-b)"} + }; +#endif + + double a = 2, b = 3; + + te_variable lookup[] = { + {"a", &a}, + {"b", &b} + }; + + int i; + for (i = 0; i < sizeof(cases) / sizeof(test_equ); ++i) { + const char *expr1 = cases[i].expr1; + const char *expr2 = cases[i].expr2; + + te_expr *ex1 = te_compile(expr1, lookup, sizeof(lookup)/sizeof(te_variable), 0); + te_expr *ex2 = te_compile(expr2, lookup, sizeof(lookup)/sizeof(te_variable), 0); + + lok(ex1); + lok(ex2); + + double r1 = te_eval(ex1); + double r2 = te_eval(ex2); + + fflush(stdout); + lfequal(r1, r2); + + te_free(ex1); + te_free(ex2); + } + +} + +void test_combinatorics() { + test_case cases[] = { + {"fac(0)", 1}, + {"fac(0.2)", 1}, + {"fac(1)", 1}, + {"fac(2)", 2}, + {"fac(3)", 6}, + {"fac(4.8)", 24}, + {"fac(10)", 3628800}, + + {"ncr(0,0)", 1}, + {"ncr(10,1)", 10}, + {"ncr(10,0)", 1}, + {"ncr(10,10)", 1}, + {"ncr(16,7)", 11440}, + {"ncr(16,9)", 11440}, + {"ncr(100,95)", 75287520}, + + {"npr(0,0)", 1}, + {"npr(10,1)", 10}, + {"npr(10,0)", 1}, + {"npr(10,10)", 3628800}, + {"npr(20,5)", 1860480}, + {"npr(100,4)", 94109400}, + }; + + + int i; + for (i = 0; i < sizeof(cases) / sizeof(test_case); ++i) { + const char *expr = cases[i].expr; + const double answer = cases[i].answer; + + int err; + const double ev = te_interp(expr, &err); + lok(!err); + lfequal(ev, answer); + + if (err) { + printf("FAILED: %s (%d)\n", expr, err); + } + } +} + + +void test_logic() { + test_case cases[] = { + {"1 && 1", 1}, + {"1 && 0", 0}, + {"0 && 1", 0}, + {"0 && 0", 0}, + {"1 || 1", 1}, + {"1 || 0", 1}, + {"0 || 1", 1}, + {"0 || 0", 0}, + {"!0", 1}, + {"!1", 0}, + {"!2", 0}, + + {"!-2", 0}, + {"-!2", 0}, + {"!!0", 0}, + {"!!1", 1}, + {"!!2", 1}, + {"!!-2", 1}, + {"!-!2", 1}, + {"-!!2", -1}, + {"--!!2", 1}, + + {"1 < 2", 1}, + {"2 < 2", 0}, + {"2 <= 2", 1}, + {"2 > 1", 1}, + {"2 > 2", 0}, + {"2 >= 2", 1}, + {"2 > -2", 1}, + {"-2 < 2", 1}, + + {"0 == 0", 1}, + {"0 != 0", 0}, + {"2 == 2", 1}, + {"2 != 2", 0}, + {"2 == 3", 0}, + {"2 != 3", 1}, + {"2 == 2.0001", 0}, + {"2 != 2.0001", 1}, + + {"1 < 2 && 2 < 3", 1}, + {"1 < 2 && 3 < 2", 0}, + {"2 < 1 && 2 < 3", 0}, + {"2 < 1 && 3 < 2", 0}, + {"1 < 2 || 2 < 3", 1}, + {"1 < 2 || 3 < 2", 1}, + {"2 < 1 || 2 < 3", 1}, + {"2 < 1 || 3 < 2", 0}, + + {"1 < 1+1", 1}, + {"1 < 1*2", 1}, + {"1 < 2/2", 0}, + {"1 < 2^2", 1}, + + {"5+5 < 4+10", 1}, + {"5+(5 < 4)+10", 15}, + {"5+(5 < 4+10)", 6}, + {"(5+5 < 4)+10", 10}, + {"5+!(5 < 4)+10", 16}, + {"5+!(5 < 4+10)", 5}, + {"!(5+5 < 4)+10", 11}, + +#ifdef TE_POW_FROM_RIGHT + {"!0^2", 1}, + {"!0^-1", 0}, + {"-!0^2", -1}, +#else + {"!0^2", 1}, + {"!0^-1", 1}, + {"-!0^2", 1}, +#endif + + }; + + + int i; + for (i = 0; i < sizeof(cases) / sizeof(test_case); ++i) { + const char *expr = cases[i].expr; + const double answer = cases[i].answer; + + int err; + const double ev = te_interp(expr, &err); + lok(!err); + lfequal(ev, answer); + + if (err) { + printf("FAILED: %s (%d)\n", expr, err); + } + } +} + +// Uppercase test +double H( double a ) +{ + return 1 + pow(a, 3.0); +} + +void test_uppercase( ) { + const char* expr = "p + g + L + len + dia + H(1-L)"; + + /* This shows an example where the variables + * x and y are bound at eval-time. */ + double p, g, L, len, dia; + te_variable vars[] = {{"p", &p}, {"g", &g}, {"L", &L}, {"len", &len}, {"dia", &dia} + , { "H", H, TE_FUNCTION1} + }; + + + /* This will compile the expression and check for errors. */ + int err; + te_expr *n = te_compile(expr, vars, 6, &err); + + if (n) { + /* The variables can be changed here, and eval can be called as many + * times as you like. This is fairly efficient because the parsing has + * already been done. */ + p = 1; g = 0.1; L = 10; len = 2; dia = 0.2; + const double r = te_eval(n); + lequal(-714.7, r); + te_free(n); + } else { + printf("FAILED: %s (%d)\n", expr, err); + } +} + + + +int main(int argc, char *argv[]) +{ + lrun("Results", test_results); + lrun("Syntax", test_syntax); + lrun("NaNs", test_nans); + lrun("INFs", test_infs); + lrun("Variables", test_variables); + lrun("Functions", test_functions); + lrun("Dynamic", test_dynamic); + lrun("Closure", test_closure); + lrun("Optimize", test_optimize); + lrun("Pow", test_pow); + lrun("Combinatorics", test_combinatorics); + lrun("Logic", test_logic); + lrun("Uppercase", test_uppercase); + lresults(); + + return lfails != 0; +} diff --git a/external/tinyexpr/tinyexpr.c b/external/tinyexpr/tinyexpr.c new file mode 100644 index 00000000..9ce324b6 --- /dev/null +++ b/external/tinyexpr/tinyexpr.c @@ -0,0 +1,1108 @@ +/* + * TINYEXPR - Tiny recursive descent parser and evaluation engine in C + * + * Copyright (c) 2015-2018 Lewis Van Winkle + * + * http://CodePlea.com + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgement in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ + +/* COMPILE TIME OPTIONS */ + +/* Exponentiation associativity: +For a^b^c = (a^b)^c and -a^b = (-a)^b do nothing. +For a^b^c = a^(b^c) and -a^b = -(a^b) uncomment the next line.*/ +/* #define TE_POW_FROM_RIGHT */ + +/* Logarithms +For log = base 10 log do nothing +For log = natural log uncomment the next line. */ +/* #define TE_NAT_LOG */ + +#include "tinyexpr.h" +#include +#include +#include +#include +#include + +#ifndef NAN +#define NAN (0.0/0.0) +#endif + +#ifndef INFINITY +#define INFINITY (1.0/0.0) +#endif + + +typedef double (*te_fun2)(double, double); + +enum +{ + TOK_NULL = TE_CLOSURE7+1, TOK_ERROR, TOK_END, TOK_SEP, + TOK_OPEN, TOK_CLOSE, TOK_NUMBER, TOK_VARIABLE, TOK_INFIX +}; + + +enum {TE_CONSTANT = 1}; + + +typedef struct state +{ + const char *start; + const char *next; + int type; + union + { + double value; + const double *bound; + const void *function; + }; + void *context; + + const te_variable *lookup; + int lookup_len; +} state; + + +#define TYPE_MASK(TYPE) ((TYPE)&0x0000001F) + +#define IS_PURE(TYPE) (((TYPE) & TE_FLAG_PURE) != 0) +#define IS_FUNCTION(TYPE) (((TYPE) & TE_FUNCTION0) != 0) +#define IS_CLOSURE(TYPE) (((TYPE) & TE_CLOSURE0) != 0) +#define ARITY(TYPE) ( ((TYPE) & (TE_FUNCTION0 | TE_CLOSURE0)) ? ((TYPE) & 0x00000007) : 0 ) +#define NEW_EXPR(type, ...) new_expr((type), (const te_expr*[]){__VA_ARGS__}) + +static te_expr *new_expr(const int type, const te_expr *parameters[]) +{ + const int arity = ARITY(type); + const int psize = sizeof(void*) * arity; + const int size = (sizeof(te_expr) - sizeof(void*)) + psize + (IS_CLOSURE(type) ? sizeof(void*) : 0); + te_expr *ret = malloc(size); + memset(ret, 0, size); + if (arity && parameters) + { + memcpy(ret->parameters, parameters, psize); + } + ret->type = type; + ret->bound = 0; + return ret; +} + + +void te_free_parameters(te_expr *n) +{ + if (!n) return; + switch (TYPE_MASK(n->type)) + { + case TE_FUNCTION7: + case TE_CLOSURE7: + te_free(n->parameters[6]); /* Falls through. */ + case TE_FUNCTION6: + case TE_CLOSURE6: + te_free(n->parameters[5]); /* Falls through. */ + case TE_FUNCTION5: + case TE_CLOSURE5: + te_free(n->parameters[4]); /* Falls through. */ + case TE_FUNCTION4: + case TE_CLOSURE4: + te_free(n->parameters[3]); /* Falls through. */ + case TE_FUNCTION3: + case TE_CLOSURE3: + te_free(n->parameters[2]); /* Falls through. */ + case TE_FUNCTION2: + case TE_CLOSURE2: + te_free(n->parameters[1]); /* Falls through. */ + case TE_FUNCTION1: + case TE_CLOSURE1: + te_free(n->parameters[0]); + } +} + + +void te_free(te_expr *n) +{ + if (!n) return; + te_free_parameters(n); + free(n); +} + + +static double pi(void) +{ + return 3.14159265358979323846; +} +static double e(void) +{ + return 2.71828182845904523536; +} +static double fac(double a) /* simplest version of fac */ +{ + if (a < 0.0) + return NAN; + if (a > UINT_MAX) + return INFINITY; + unsigned int ua = (unsigned int)(a); + unsigned long int result = 1, i; + for (i = 1; i <= ua; i++) + { + if (i > ULONG_MAX / result) + return INFINITY; + result *= i; + } + return (double)result; +} +static double ncr(double n, double r) +{ + if (n < 0.0 || r < 0.0 || n < r) return NAN; + if (n > UINT_MAX || r > UINT_MAX) return INFINITY; + unsigned long int un = (unsigned int)(n), ur = (unsigned int)(r), i; + unsigned long int result = 1; + if (ur > un / 2) ur = un - ur; + for (i = 1; i <= ur; i++) + { + if (result > ULONG_MAX / (un - ur + i)) + return INFINITY; + result *= un - ur + i; + result /= i; + } + return result; +} +static double npr(double n, double r) +{ + return ncr(n, r) * fac(r); +} + +static const te_variable functions[] = +{ + /* must be in alphabetical order */ + {"abs", fabs, TE_FUNCTION1 | TE_FLAG_PURE, 0}, + {"acos", acos, TE_FUNCTION1 | TE_FLAG_PURE, 0}, + {"asin", asin, TE_FUNCTION1 | TE_FLAG_PURE, 0}, + {"atan", atan, TE_FUNCTION1 | TE_FLAG_PURE, 0}, + {"atan2", atan2, TE_FUNCTION2 | TE_FLAG_PURE, 0}, + {"ceil", ceil, TE_FUNCTION1 | TE_FLAG_PURE, 0}, + {"cos", cos, TE_FUNCTION1 | TE_FLAG_PURE, 0}, + {"cosh", cosh, TE_FUNCTION1 | TE_FLAG_PURE, 0}, + {"e", e, TE_FUNCTION0 | TE_FLAG_PURE, 0}, + {"exp", exp, TE_FUNCTION1 | TE_FLAG_PURE, 0}, + {"fac", fac, TE_FUNCTION1 | TE_FLAG_PURE, 0}, + {"floor", floor, TE_FUNCTION1 | TE_FLAG_PURE, 0}, + {"ln", log, TE_FUNCTION1 | TE_FLAG_PURE, 0}, +#ifdef TE_NAT_LOG + {"log", log, TE_FUNCTION1 | TE_FLAG_PURE, 0}, +#else + {"log", log10, TE_FUNCTION1 | TE_FLAG_PURE, 0}, +#endif + {"log10", log10, TE_FUNCTION1 | TE_FLAG_PURE, 0}, + {"ncr", ncr, TE_FUNCTION2 | TE_FLAG_PURE, 0}, + {"npr", npr, TE_FUNCTION2 | TE_FLAG_PURE, 0}, + {"pi", pi, TE_FUNCTION0 | TE_FLAG_PURE, 0}, + {"pow", pow, TE_FUNCTION2 | TE_FLAG_PURE, 0}, + {"sin", sin, TE_FUNCTION1 | TE_FLAG_PURE, 0}, + {"sinh", sinh, TE_FUNCTION1 | TE_FLAG_PURE, 0}, + {"sqrt", sqrt, TE_FUNCTION1 | TE_FLAG_PURE, 0}, + {"tan", tan, TE_FUNCTION1 | TE_FLAG_PURE, 0}, + {"tanh", tanh, TE_FUNCTION1 | TE_FLAG_PURE, 0}, + {0, 0, 0, 0} +}; + +static const te_variable *find_builtin(const char *name, int len) +{ + int imin = 0; + int imax = sizeof(functions) / sizeof(te_variable) - 2; + + /*Binary search.*/ + while (imax >= imin) + { + const int i = (imin + ((imax-imin)/2)); + int c = strncmp(name, functions[i].name, len); + if (!c) c = '\0' - functions[i].name[len]; + if (c == 0) + { + return functions + i; + } + else if (c > 0) + { + imin = i + 1; + } + else + { + imax = i - 1; + } + } + + return 0; +} + +static const te_variable *find_lookup(const state *s, const char *name, int len) +{ + int iters; + const te_variable *var; + if (!s->lookup) return 0; + + for (var = s->lookup, iters = s->lookup_len; iters; ++var, --iters) + { + if (strncmp(name, var->name, len) == 0 && var->name[len] == '\0') + { + return var; + } + } + return 0; +} + + + +static double add(double a, double b) +{ + return a + b; +} +static double sub(double a, double b) +{ + return a - b; +} +static double mul(double a, double b) +{ + return a * b; +} +static double divide(double a, double b) +{ + return a / b; +} +static double negate(double a) +{ + return -a; +} +static double comma(double a, double b) +{ + (void)a; + return b; +} + +static double greater(double a, double b) +{ + return a > b; +} +static double greater_eq(double a, double b) +{ + return a >= b; +} +static double lower(double a, double b) +{ + return a < b; +} +static double lower_eq(double a, double b) +{ + return a <= b; +} +static double equal(double a, double b) +{ + return a == b; +} +static double not_equal(double a, double b) +{ + return a != b; +} +static double logical_and(double a, double b) +{ + return a != 0.0 && b != 0.0; +} +static double logical_or(double a, double b) +{ + return a != 0.0 || b != 0.0; +} +static double logical_not(double a) +{ + return a == 0.0; +} +static double logical_notnot(double a) +{ + return a != 0.0; +} +static double negate_logical_not(double a) +{ + return -(a == 0.0); +} +static double negate_logical_notnot(double a) +{ + return -(a != 0.0); +} + + +void next_token(state *s) +{ + s->type = TOK_NULL; + + do + { + + if (!*s->next) + { + s->type = TOK_END; + return; + } + + /* Try reading a number. */ + if ((s->next[0] >= '0' && s->next[0] <= '9') || s->next[0] == '.') + { + s->value = strtod(s->next, (char**)&s->next); + s->type = TOK_NUMBER; + } + else + { + /* Look for a variable or builtin function call. */ + if ( (s->next[0] >= 'a' && s->next[0] <= 'z') || (s->next[0] >= 'A' && s->next[0] <= 'Z')) { + const char *start; + start = s->next; + while ((s->next[0] >= 'a' && s->next[0] <= 'z') + || (s->next[0] >= 'A' && s->next[0] <= 'Z') + || (s->next[0] >= '0' && s->next[0] <= '9') + || (s->next[0] == '_')) s->next++; + + const te_variable *var = find_lookup(s, start, s->next - start); + if (!var) var = find_builtin(start, s->next - start); + if (!var) + { + s->type = TOK_ERROR; + } + else + { + switch(TYPE_MASK(var->type)) + { + case TE_VARIABLE: + s->type = TOK_VARIABLE; + s->bound = var->address; + break; + + case TE_CLOSURE0: + case TE_CLOSURE1: + case TE_CLOSURE2: + case TE_CLOSURE3: /* Falls through. */ + case TE_CLOSURE4: + case TE_CLOSURE5: + case TE_CLOSURE6: + case TE_CLOSURE7: /* Falls through. */ + s->context = var->context; /* Falls through. */ + + case TE_FUNCTION0: + case TE_FUNCTION1: + case TE_FUNCTION2: + case TE_FUNCTION3: /* Falls through. */ + case TE_FUNCTION4: + case TE_FUNCTION5: + case TE_FUNCTION6: + case TE_FUNCTION7: /* Falls through. */ + s->type = var->type; + s->function = var->address; + break; + } + } + + } + else + { + /* Look for an operator or special character. */ + switch (s->next++[0]) + { + case '+': + s->type = TOK_INFIX; + s->function = add; + break; + case '-': + s->type = TOK_INFIX; + s->function = sub; + break; + case '*': + s->type = TOK_INFIX; + s->function = mul; + break; + case '/': + s->type = TOK_INFIX; + s->function = divide; + break; + case '^': + s->type = TOK_INFIX; + s->function = pow; + break; + case '%': + s->type = TOK_INFIX; + s->function = fmod; + break; + case '!': + if (s->next++[0] == '=') + { + s->type = TOK_INFIX; + s->function = not_equal; + } + else + { + s->next--; + s->type = TOK_INFIX; + s->function = logical_not; + } + break; + case '=': + if (s->next++[0] == '=') + { + s->type = TOK_INFIX; + s->function = equal; + } + else + { + s->type = TOK_ERROR; + } + break; + case '<': + if (s->next++[0] == '=') + { + s->type = TOK_INFIX; + s->function = lower_eq; + } + else + { + s->next--; + s->type = TOK_INFIX; + s->function = lower; + } + break; + case '>': + if (s->next++[0] == '=') + { + s->type = TOK_INFIX; + s->function = greater_eq; + } + else + { + s->next--; + s->type = TOK_INFIX; + s->function = greater; + } + break; + case '&': + if (s->next++[0] == '&') + { + s->type = TOK_INFIX; + s->function = logical_and; + } + else + { + s->type = TOK_ERROR; + } + break; + case '|': + if (s->next++[0] == '|') + { + s->type = TOK_INFIX; + s->function = logical_or; + } + else + { + s->type = TOK_ERROR; + } + break; + case '(': + s->type = TOK_OPEN; + break; + case ')': + s->type = TOK_CLOSE; + break; + case ',': + s->type = TOK_SEP; + break; + case ' ': + case '\t': + case '\n': + case '\r': + break; + default: + s->type = TOK_ERROR; + break; + } + } + } + } + while (s->type == TOK_NULL); +} + + +static te_expr *list(state *s); +static te_expr *expr(state *s); +static te_expr *power(state *s); + +static te_expr *base(state *s) +{ + /* = | | {"(" ")"} | | "(" {"," } ")" | "(" ")" */ + te_expr *ret; + int arity; + + switch (TYPE_MASK(s->type)) + { + case TOK_NUMBER: + ret = new_expr(TE_CONSTANT, 0); + ret->value = s->value; + next_token(s); + break; + + case TOK_VARIABLE: + ret = new_expr(TE_VARIABLE, 0); + ret->bound = s->bound; + next_token(s); + break; + + case TE_FUNCTION0: + case TE_CLOSURE0: + ret = new_expr(s->type, 0); + ret->function = s->function; + if (IS_CLOSURE(s->type)) ret->parameters[0] = s->context; + next_token(s); + if (s->type == TOK_OPEN) + { + next_token(s); + if (s->type != TOK_CLOSE) + { + s->type = TOK_ERROR; + } + else + { + next_token(s); + } + } + break; + + case TE_FUNCTION1: + case TE_CLOSURE1: + ret = new_expr(s->type, 0); + ret->function = s->function; + if (IS_CLOSURE(s->type)) ret->parameters[1] = s->context; + next_token(s); + ret->parameters[0] = power(s); + break; + + case TE_FUNCTION2: + case TE_FUNCTION3: + case TE_FUNCTION4: + case TE_FUNCTION5: + case TE_FUNCTION6: + case TE_FUNCTION7: + case TE_CLOSURE2: + case TE_CLOSURE3: + case TE_CLOSURE4: + case TE_CLOSURE5: + case TE_CLOSURE6: + case TE_CLOSURE7: + arity = ARITY(s->type); + + ret = new_expr(s->type, 0); + ret->function = s->function; + if (IS_CLOSURE(s->type)) ret->parameters[arity] = s->context; + next_token(s); + + if (s->type != TOK_OPEN) + { + s->type = TOK_ERROR; + } + else + { + int i; + for(i = 0; i < arity; i++) + { + next_token(s); + ret->parameters[i] = expr(s); + if(s->type != TOK_SEP) + { + break; + } + } + if(s->type != TOK_CLOSE || i != arity - 1) + { + s->type = TOK_ERROR; + } + else + { + next_token(s); + } + } + + break; + + case TOK_OPEN: + next_token(s); + ret = list(s); + if (s->type != TOK_CLOSE) + { + s->type = TOK_ERROR; + } + else + { + next_token(s); + } + break; + + default: + ret = new_expr(0, 0); + s->type = TOK_ERROR; + ret->value = NAN; + break; + } + + return ret; +} + + +static te_expr *power(state *s) +{ + /* = {("-" | "+" | "!")} */ + int sign = 1; + while (s->type == TOK_INFIX && (s->function == add || s->function == sub)) + { + if (s->function == sub) sign = -sign; + next_token(s); + } + + int logical = 0; + while (s->type == TOK_INFIX && (s->function == add || s->function == sub || s->function == logical_not)) + { + if (s->function == logical_not) + { + if (logical == 0) + { + logical = -1; + } + else + { + logical = -logical; + } + } + next_token(s); + } + + te_expr *ret; + + if (sign == 1) + { + if (logical == 0) + { + ret = base(s); + } + else if (logical == -1) + { + ret = NEW_EXPR(TE_FUNCTION1 | TE_FLAG_PURE, base(s)); + ret->function = logical_not; + } + else + { + ret = NEW_EXPR(TE_FUNCTION1 | TE_FLAG_PURE, base(s)); + ret->function = logical_notnot; + } + } + else + { + if (logical == 0) + { + ret = NEW_EXPR(TE_FUNCTION1 | TE_FLAG_PURE, base(s)); + ret->function = negate; + } + else if (logical == -1) + { + ret = NEW_EXPR(TE_FUNCTION1 | TE_FLAG_PURE, base(s)); + ret->function = negate_logical_not; + } + else + { + ret = NEW_EXPR(TE_FUNCTION1 | TE_FLAG_PURE, base(s)); + ret->function = negate_logical_notnot; + } + } + + return ret; +} + +#ifdef TE_POW_FROM_RIGHT +static te_expr *factor(state *s) +{ + /* = {"^" } */ + te_expr *ret = power(s); + + const void *left_function = NULL; + te_expr *insertion = 0; + + if (ret->type == (TE_FUNCTION1 | TE_FLAG_PURE) && + (ret->function == negate || ret->function == logical_not || ret->function == logical_notnot || + ret->function == negate_logical_not || ret->function == negate_logical_notnot)) + { + left_function = ret->function; + te_expr *se = ret->parameters[0]; + free(ret); + ret = se; + } + + while (s->type == TOK_INFIX && (s->function == pow)) + { + te_fun2 t = s->function; + next_token(s); + + if (insertion) + { + /* Make exponentiation go right-to-left. */ + te_expr *insert = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, insertion->parameters[1], power(s)); + insert->function = t; + insertion->parameters[1] = insert; + insertion = insert; + } + else + { + ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, power(s)); + ret->function = t; + insertion = ret; + } + } + + if (left_function) + { + ret = NEW_EXPR(TE_FUNCTION1 | TE_FLAG_PURE, ret); + ret->function = left_function; + } + + return ret; +} +#else +static te_expr *factor(state *s) +{ + /* = {"^" } */ + te_expr *ret = power(s); + + while (s->type == TOK_INFIX && (s->function == pow)) + { + te_fun2 t = s->function; + next_token(s); + ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, power(s)); + ret->function = t; + } + + return ret; +} +#endif + + + +static te_expr *term(state *s) +{ + /* = {("*" | "/" | "%") } */ + te_expr *ret = factor(s); + + while (s->type == TOK_INFIX && (s->function == mul || s->function == divide || s->function == fmod)) + { + te_fun2 t = s->function; + next_token(s); + ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, factor(s)); + ret->function = t; + } + + return ret; +} + + +static te_expr *sum_expr(state *s) +{ + /* = {("+" | "-") } */ + te_expr *ret = term(s); + + while (s->type == TOK_INFIX && (s->function == add || s->function == sub)) + { + te_fun2 t = s->function; + next_token(s); + ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, term(s)); + ret->function = t; + } + + return ret; +} + + +static te_expr *test_expr(state *s) +{ + /* = {(">" | ">=" | "<" | "<=" | "==" | "!=") } */ + te_expr *ret = sum_expr(s); + + while (s->type == TOK_INFIX && (s->function == greater || s->function == greater_eq || + s->function == lower || s->function == lower_eq || s->function == equal || s->function == not_equal)) + { + te_fun2 t = s->function; + next_token(s); + ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, sum_expr(s)); + ret->function = t; + } + + return ret; +} + + +static te_expr *expr(state *s) +{ + /* = {("&&" | "||") } */ + te_expr *ret = test_expr(s); + + while (s->type == TOK_INFIX && (s->function == logical_and || s->function == logical_or)) + { + te_fun2 t = s->function; + next_token(s); + ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, test_expr(s)); + ret->function = t; + } + + return ret; +} + + +static te_expr *list(state *s) +{ + /* = {"," } */ + te_expr *ret = expr(s); + + while (s->type == TOK_SEP) + { + next_token(s); + ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, expr(s)); + ret->function = comma; + } + + return ret; +} + + +#define TE_FUN(...) ((double(*)(__VA_ARGS__))n->function) +#define M(e) te_eval(n->parameters[e]) + + +double te_eval(const te_expr *n) +{ + if (!n) return NAN; + + switch(TYPE_MASK(n->type)) + { + case TE_CONSTANT: + return n->value; + case TE_VARIABLE: + return *n->bound; + + case TE_FUNCTION0: + case TE_FUNCTION1: + case TE_FUNCTION2: + case TE_FUNCTION3: + case TE_FUNCTION4: + case TE_FUNCTION5: + case TE_FUNCTION6: + case TE_FUNCTION7: + switch(ARITY(n->type)) + { + case 0: + return TE_FUN(void)(); + case 1: + return TE_FUN(double)(M(0)); + case 2: + return TE_FUN(double, double)(M(0), M(1)); + case 3: + return TE_FUN(double, double, double)(M(0), M(1), M(2)); + case 4: + return TE_FUN(double, double, double, double)(M(0), M(1), M(2), M(3)); + case 5: + return TE_FUN(double, double, double, double, double)(M(0), M(1), M(2), M(3), M(4)); + case 6: + return TE_FUN(double, double, double, double, double, double)(M(0), M(1), M(2), M(3), M(4), M(5)); + case 7: + return TE_FUN(double, double, double, double, double, double, double)(M(0), M(1), M(2), M(3), M(4), M(5), M(6)); + default: + return NAN; + } + + case TE_CLOSURE0: + case TE_CLOSURE1: + case TE_CLOSURE2: + case TE_CLOSURE3: + case TE_CLOSURE4: + case TE_CLOSURE5: + case TE_CLOSURE6: + case TE_CLOSURE7: + switch(ARITY(n->type)) + { + case 0: + return TE_FUN(void*)(n->parameters[0]); + case 1: + return TE_FUN(void*, double)(n->parameters[1], M(0)); + case 2: + return TE_FUN(void*, double, double)(n->parameters[2], M(0), M(1)); + case 3: + return TE_FUN(void*, double, double, double)(n->parameters[3], M(0), M(1), M(2)); + case 4: + return TE_FUN(void*, double, double, double, double)(n->parameters[4], M(0), M(1), M(2), M(3)); + case 5: + return TE_FUN(void*, double, double, double, double, double)(n->parameters[5], M(0), M(1), M(2), M(3), M(4)); + case 6: + return TE_FUN(void*, double, double, double, double, double, double)(n->parameters[6], M(0), M(1), M(2), M(3), M(4), M(5)); + case 7: + return TE_FUN(void*, double, double, double, double, double, double, double)(n->parameters[7], M(0), M(1), M(2), M(3), M(4), M(5), M(6)); + default: + return NAN; + } + + default: + return NAN; + } + +} + +#undef TE_FUN +#undef M + +static void optimize(te_expr *n) +{ + /* Evaluates as much as possible. */ + if (n->type == TE_CONSTANT) return; + if (n->type == TE_VARIABLE) return; + + /* Only optimize out functions flagged as pure. */ + if (IS_PURE(n->type)) + { + const int arity = ARITY(n->type); + int known = 1; + int i; + for (i = 0; i < arity; ++i) + { + optimize(n->parameters[i]); + if (((te_expr*)(n->parameters[i]))->type != TE_CONSTANT) + { + known = 0; + } + } + if (known) + { + const double value = te_eval(n); + te_free_parameters(n); + n->type = TE_CONSTANT; + n->value = value; + } + } +} + + +te_expr *te_compile(const char *expression, const te_variable *variables, int var_count, int *error) +{ + state s; + s.start = s.next = expression; + s.lookup = variables; + s.lookup_len = var_count; + +#if 0 + // Got variables. + int i = 0; + for (i = 0; i < var_count; i++) + { + te_variable v = variables[i]; + if( v.address ) + printf( "%d %s ", i, v.name ); + } +#endif + + next_token(&s); + te_expr *root = list(&s); + + if (s.type != TOK_END) + { + te_free(root); + if (error) + { + *error = (s.next - s.start); + if (*error == 0) *error = 1; + } + return 0; + } + else + { + optimize(root); + if (error) *error = 0; + return root; + } +} + + +double te_interp(const char *expression, int *error) +{ + te_expr *n = te_compile(expression, 0, 0, error); + double ret; + if (n) + { + ret = te_eval(n); + te_free(n); + } + else + { + ret = NAN; + } + return ret; +} + +static void pn (const te_expr *n, int depth) +{ + int i, arity; + printf("%*s", depth, ""); + + switch(TYPE_MASK(n->type)) + { + case TE_CONSTANT: + printf("%f\n", n->value); + break; + case TE_VARIABLE: + printf("bound %p\n", n->bound); + break; + + case TE_FUNCTION0: + case TE_FUNCTION1: + case TE_FUNCTION2: + case TE_FUNCTION3: + case TE_FUNCTION4: + case TE_FUNCTION5: + case TE_FUNCTION6: + case TE_FUNCTION7: + case TE_CLOSURE0: + case TE_CLOSURE1: + case TE_CLOSURE2: + case TE_CLOSURE3: + case TE_CLOSURE4: + case TE_CLOSURE5: + case TE_CLOSURE6: + case TE_CLOSURE7: + arity = ARITY(n->type); + printf("f%d", arity); + for(i = 0; i < arity; i++) + { + printf(" %p", n->parameters[i]); + } + printf("\n"); + for(i = 0; i < arity; i++) + { + pn(n->parameters[i], depth + 1); + } + break; + } +} + + +void te_print(const te_expr *n) +{ + pn(n, 0); +} diff --git a/external/tinyexpr/tinyexpr.h b/external/tinyexpr/tinyexpr.h new file mode 100644 index 00000000..82786336 --- /dev/null +++ b/external/tinyexpr/tinyexpr.h @@ -0,0 +1,86 @@ +/* + * TINYEXPR - Tiny recursive descent parser and evaluation engine in C + * + * Copyright (c) 2015-2018 Lewis Van Winkle + * + * http://CodePlea.com + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgement in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ + +#ifndef __TINYEXPR_H__ +#define __TINYEXPR_H__ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +typedef struct te_expr { + int type; + union {double value; const double *bound; const void *function;}; + void *parameters[1]; +} te_expr; + + +enum { + TE_VARIABLE = 0, + + TE_FUNCTION0 = 8, TE_FUNCTION1, TE_FUNCTION2, TE_FUNCTION3, + TE_FUNCTION4, TE_FUNCTION5, TE_FUNCTION6, TE_FUNCTION7, + + TE_CLOSURE0 = 16, TE_CLOSURE1, TE_CLOSURE2, TE_CLOSURE3, + TE_CLOSURE4, TE_CLOSURE5, TE_CLOSURE6, TE_CLOSURE7, + + TE_FLAG_PURE = 32 +}; + +typedef struct te_variable { + const char *name; + const void *address; + int type; + void *context; +} te_variable; + + + +/* Parses the input expression, evaluates it, and frees it. */ +/* Returns NaN on error. */ +double te_interp(const char *expression, int *error); + +/* Parses the input expression and binds variables. */ +/* Returns NULL on error. */ +te_expr *te_compile(const char *expression, const te_variable *variables, int var_count, int *error); + +/* Evaluates the expression. */ +double te_eval(const te_expr *n); + +/* Prints debugging information on the syntax tree. */ +void te_print(const te_expr *n); + +/* Frees the expression. */ +/* This is safe to call on NULL pointers. */ +void te_free(te_expr *n); + + +#ifdef __cplusplus +} +#endif + +#endif /*__TINYEXPR_H__*/ diff --git a/hsolve/HSolveInterface.cpp b/hsolve/HSolveInterface.cpp index 455c8cb7..05cd95c2 100644 --- a/hsolve/HSolveInterface.cpp +++ b/hsolve/HSolveInterface.cpp @@ -89,8 +89,10 @@ void HSolve::setCm( Id id, double value ) { unsigned int index = localIndex( id ); assert( index < tree_.size() ); - // Also update data structures used for calculations. tree_[ index ].Cm = value; + // Also update data structures used for calculations. + assert( tree_.size() == compartment_.size() ); + compartment_[index].CmByDt = 2.0 * value / dt_; } double HSolve::getEm( Id id ) const @@ -104,8 +106,10 @@ void HSolve::setEm( Id id, double value ) { unsigned int index = localIndex( id ); assert( index < tree_.size() ); - // Also update data structures used for calculations. tree_[ index ].Em = value; + // Also update data structures used for calculations. + assert( tree_.size() == compartment_.size() ); + compartment_[index].EmByRm = value / tree_[index].Rm; } double HSolve::getRm( Id id ) const @@ -119,8 +123,10 @@ void HSolve::setRm( Id id, double value ) { unsigned int index = localIndex( id ); assert( index < tree_.size() ); - // Also update data structures used for calculations. tree_[ index ].Rm = value; + // Also update data structures used for calculations. + assert( tree_.size() == compartment_.size() ); + compartment_[index].EmByRm = tree_[index].Em / value; } double HSolve::getRa( Id id ) const diff --git a/kinetics/Pool.cpp b/kinetics/Pool.cpp index b6b448ba..9184c0fe 100644 --- a/kinetics/Pool.cpp +++ b/kinetics/Pool.cpp @@ -9,6 +9,7 @@ #include "../basecode/header.h" #include "../basecode/ElementValueFinfo.h" +#include "../utility/print_function.hpp" #include "lookupVolumeFromMesh.h" #include "PoolBase.h" #include "Pool.h" @@ -164,6 +165,7 @@ void Pool::vHandleMolWt( const Eref& e, double v ) void Pool::vSetN( const Eref& e, double v ) { + assert(! std::isnan(v)); n_ = v; } @@ -174,6 +176,7 @@ double Pool::vGetN( const Eref& e ) const void Pool::vSetNinit( const Eref& e, double v ) { + assert(! std::isnan(v)); nInit_ = v; } @@ -201,7 +204,10 @@ void Pool::vSetConcInit( const Eref& e, double c ) void Pool::vSetDiffConst( const Eref& e, double v ) { - diffConst_ = v; + if(! std::isnan(v)) + diffConst_ = v; + else + moose::showWarn("Trying to assign non-numeric value:" + to_string(v) + ". Ignored!"); } double Pool::vGetDiffConst( const Eref& e ) const diff --git a/kinetics/PoolBase.cpp b/kinetics/PoolBase.cpp index bff5f026..da8f20b9 100644 --- a/kinetics/PoolBase.cpp +++ b/kinetics/PoolBase.cpp @@ -225,8 +225,7 @@ const Cinfo* PoolBase::initCinfo() static const Cinfo* poolCinfo = PoolBase::initCinfo(); ////////////////////////////////////////////////////////////// -PoolBase::PoolBase() - : concInit_( 0.0 ) +PoolBase::PoolBase() : concInit_( 0.0 ) {;} PoolBase::~PoolBase() @@ -427,8 +426,7 @@ void PoolBase::vSetIsBuffered( const Eref& e, bool v ) // There should also be a subsequent call to resched for the entire tree. ////////////////////////////////////////////////////////////// // static func -void PoolBase::zombify( Element* orig, const Cinfo* zClass, - Id ksolve, Id dsolve ) +void PoolBase::zombify(Element* orig, const Cinfo* zClass, Id ksolve, Id dsolve) { if ( orig->cinfo() == zClass ) return; @@ -443,8 +441,7 @@ void PoolBase::zombify( Element* orig, const Cinfo* zClass, for ( unsigned int i = 0; i < num; ++i ) { Eref er( orig, i + start ); - const PoolBase* pb = - reinterpret_cast< const PoolBase* >( er.data() ); + const PoolBase* pb = reinterpret_cast< const PoolBase* >( er.data() ); species[ i ] = pb->getSpecies( er ); concInit[ i ] = pb->getConcInit( er ); diffConst[ i ] = pb->getDiffConst( er ); diff --git a/kinetics/PoolBase.h b/kinetics/PoolBase.h index 20ab0000..58794d18 100644 --- a/kinetics/PoolBase.h +++ b/kinetics/PoolBase.h @@ -153,6 +153,7 @@ class PoolBase ////////////////////////////////////////////////////////////////// static const Cinfo* initCinfo(); + private: double concInit_; /// Initial concentration. // We don't store the conc here as this is computed on the fly diff --git a/kinetics/ReadKkit.cpp b/kinetics/ReadKkit.cpp index a33986ac..209af9e0 100644 --- a/kinetics/ReadKkit.cpp +++ b/kinetics/ReadKkit.cpp @@ -12,7 +12,6 @@ #include #include #include "../basecode/header.h" -#include "../utility/utility.h" #include "PoolBase.h" #include "Pool.h" #include "BufPool.h" @@ -23,6 +22,8 @@ #include "../shell/Shell.h" #include "../shell/Wildcard.h" +#include "../utility/strutil.h" + #include "ReadKkit.h" const double ReadKkit::EPSILON = 1.0e-15; @@ -30,52 +31,53 @@ static const double KKIT_NA = 6.0e23; // Causes all sorts of conversion fun unsigned int chopLine( const string& line, vector< string >& ret ) { - ret.resize( 0 ); - stringstream ss( line ); - string arg; - while ( ss >> arg ) { - ret.push_back( moose::trim(arg, "\"") ); - } - return ret.size(); + ret.resize( 0 ); + stringstream ss( line ); + string arg; + while ( ss >> arg ) + { + ret.push_back( moose::trim(arg, "\"") ); + } + return ret.size(); } string lower( const string& input ) { - string ret = input; - for ( unsigned int i = 0; i < input.length(); ++i ) - ret[i] = tolower( ret[i] ); - return ret; + string ret = input; + for ( unsigned int i = 0; i < input.length(); ++i ) + ret[i] = tolower( ret[i] ); + return ret; } //////////////////////////////////////////////////////////////////////// ReadKkit::ReadKkit() - : - basePath_( "" ), - baseId_(), - fastdt_( 0.001 ), - simdt_( 0.01 ), - controldt_( 0.1 ), - plotdt_( 1 ), - maxtime_( 1.0 ), - transientTime_( 1.0 ), - useVariableDt_( 0 ), - defaultVol_( 1 ), - version_( 11 ), - initdumpVersion_( 3 ), - moveOntoCompartment_( true ), - numCompartments_( 0 ), - numPools_( 0 ), - numReacs_( 0 ), - numEnz_( 0 ), - numMMenz_( 0 ), - numPlot_( 0 ), - numStim_( 0 ), - numOthers_( 0 ), - lineNum_( 0 ), - shell_( reinterpret_cast< Shell* >( Id().eref().data() ) ) + : + basePath_( "" ), + baseId_(), + fastdt_( 0.001 ), + simdt_( 0.01 ), + controldt_( 0.1 ), + plotdt_( 1 ), + maxtime_( 1.0 ), + transientTime_( 1.0 ), + useVariableDt_( 0 ), + defaultVol_( 1 ), + version_( 11 ), + initdumpVersion_( 3 ), + moveOntoCompartment_( true ), + numCompartments_( 0 ), + numPools_( 0 ), + numReacs_( 0 ), + numEnz_( 0 ), + numMMenz_( 0 ), + numPlot_( 0 ), + numStim_( 0 ), + numOthers_( 0 ), + lineNum_( 0 ), + shell_( reinterpret_cast< Shell* >( Id().eref().data() ) ) { - ; + ; } ////////////////////////////////////////////////////////////////// @@ -84,37 +86,37 @@ ReadKkit::ReadKkit() double ReadKkit::getMaxTime() const { - return maxtime_; + return maxtime_; } double ReadKkit::getPlotDt() const { - return plotdt_; + return plotdt_; } double ReadKkit::getDefaultVol() const { - return defaultVol_; + return defaultVol_; } string ReadKkit::getBasePath() const { - return basePath_; + return basePath_; } unsigned int ReadKkit::getVersion() const { - return version_; + return version_; } bool ReadKkit::getMoveOntoCompartment() const { - return moveOntoCompartment_; + return moveOntoCompartment_; } void ReadKkit::setMoveOntoCompartment( bool v ) { - moveOntoCompartment_ = v; + moveOntoCompartment_ = v; } ////////////////////////////////////////////////////////////////// @@ -122,151 +124,154 @@ void ReadKkit::setMoveOntoCompartment( bool v ) ////////////////////////////////////////////////////////////////// Id makeStandardElements( Id pa, const string& modelname ) { - Shell* shell = reinterpret_cast< Shell* >( Id().eref().data() ); - string modelPath = pa.path() + "/" + modelname; - if ( pa == Id() ) - modelPath = "/" + modelname; - Id mgr( modelPath ); - if ( mgr == Id() ) - mgr = shell->doCreate( "Neutral", pa, modelname, 1, MooseGlobal ); - Id kinetics( modelPath + "/kinetics" ); - if ( kinetics == Id() ) { - kinetics = shell->doCreate( "CubeMesh", mgr, "kinetics", 1, MooseGlobal ); - SetGet2< double, unsigned int >::set( kinetics, "buildDefaultMesh", 1e-15, 1 ); - Id cInfo = shell->doCreate( "Annotator", kinetics, "info", 1 ); - assert( cInfo != Id() ); - } - assert( kinetics != Id() ); - - Id graphs = shell->doCreate( "Neutral", mgr, "graphs", 1, MooseGlobal); - assert( graphs != Id() ); - Id moregraphs = shell->doCreate( "Neutral", mgr, "moregraphs", 1, MooseGlobal ); - - Id geometry = shell->doCreate( "Neutral", mgr, "geometry", 1, MooseGlobal ); - assert( geometry != Id() ); - - Id groups = - shell->doCreate( "Neutral", mgr, "groups", 1, MooseGlobal ); - assert( groups != Id() ); - return mgr; + Shell* shell = reinterpret_cast< Shell* >( Id().eref().data() ); + string modelPath = pa.path() + "/" + modelname; + if ( pa == Id() ) + modelPath = "/" + modelname; + Id mgr( modelPath ); + if ( mgr == Id() ) + mgr = shell->doCreate( "Neutral", pa, modelname, 1, MooseGlobal ); + Id kinetics( modelPath + "/kinetics" ); + if ( kinetics == Id() ) + { + kinetics = shell->doCreate( "CubeMesh", mgr, "kinetics", 1, MooseGlobal ); + SetGet2< double, unsigned int >::set( kinetics, "buildDefaultMesh", 1e-15, 1 ); + Id cInfo = shell->doCreate( "Annotator", kinetics, "info", 1 ); + assert( cInfo != Id() ); + } + assert( kinetics != Id() ); + + Id graphs = shell->doCreate( "Neutral", mgr, "graphs", 1, MooseGlobal); + assert( graphs != Id() ); + Id moregraphs = shell->doCreate( "Neutral", mgr, "moregraphs", 1, MooseGlobal ); + + Id geometry = shell->doCreate( "Neutral", mgr, "geometry", 1, MooseGlobal ); + assert( geometry != Id() ); + + Id groups = shell->doCreate( "Neutral", mgr, "groups", 1, MooseGlobal ); + assert( groups != Id() ); + return mgr; } static void positionCompt( ObjId compt, double side, bool shiftUp ) { - double y0 = Field< double >::get( compt, "y0" ); - double y1 = Field< double >::get( compt, "y1" ); - if ( shiftUp ) { - Field< double >::set( compt, "y0", y0 + side ); - Field< double >::set( compt, "y1", y1 + side ); - } else { - Field< double >::set( compt, "y0", y0 - y1 ); - Field< double >::set( compt, "y1", 0 ); - } + double y0 = Field< double >::get( compt, "y0" ); + double y1 = Field< double >::get( compt, "y1" ); + if ( shiftUp ) + { + Field< double >::set( compt, "y0", y0 + side ); + Field< double >::set( compt, "y1", y1 + side ); + } + else + { + Field< double >::set( compt, "y0", y0 - y1 ); + Field< double >::set( compt, "y1", 0 ); + } } -void makeSolverOnCompt( Shell* s,const vector< ObjId >& compts, - bool isGsolve ) +void makeSolverOnCompt(Shell* s,const vector< ObjId >& compts, bool isGsolve) { - if ( compts.size() > 3 ) { - cout << "Warning: ReadKkit::makeSolverOnCompt: Cannot handle " << - compts.size() << " chemical compartments\n"; - return; - } - vector< Id > stoichVec; - /* - if ( compts.size() == 2 ) { - double side = Field< double >::get( compts[1], "dy" ); - positionCompt( compts[0], side, true ); - } - if ( compts.size() == 3 ) { - double side = Field< double >::get( compts[1], "dy" ); - positionCompt( compts[0], side, true ); - positionCompt( compts[2], side, false ); - } - */ - /* - for ( vector< ObjId >::const_iterator - i = compts.begin(); i != compts.end(); ++i ) { - string simpath = i->path() + "/##"; - Id ksolve; - if ( isGsolve ) - ksolve = s->doCreate( "Gsolve", *i, "gsolve", 1 ); - else - ksolve = s->doCreate( "Ksolve", *i, "ksolve", 1 ); - dsolve = s->doCreate("Dsolve,") - Id stoich = s->doCreate( "Stoich", *i, "stoich", 1 ); - stoichVec.push_back( stoich ); - Field< Id >::set( stoich, "compartment", *i ); - Field< Id >::set( stoich, "ksolve", ksolve ); - Field< string >::set( stoich, "path", simpath ); - } - */ - /* Not needed now that we use xfer pools to cross compartments. - if ( stoichVec.size() == 2 ) { - SetGet1< Id >::set( stoichVec[1], "buildXreacs", stoichVec[0] ); - } - if ( stoichVec.size() == 3 ) { - SetGet1< Id >::set( stoichVec[1], "buildXreacs", stoichVec[0] ); - SetGet1< Id >::set( stoichVec[1], "buildXreacs", stoichVec[2] ); - } - for ( vector< Id >::iterator - i = stoichVec.begin(); i != stoichVec.end(); ++i ) { - SetGet0::set( *i, "filterXreacs" ); - } - */ + if ( compts.size() > 3 ) + { + cout << "Warning: ReadKkit::makeSolverOnCompt: Cannot handle " << + compts.size() << " chemical compartments\n"; + return; + } + vector< Id > stoichVec; + /* + if ( compts.size() == 2 ) { + double side = Field< double >::get( compts[1], "dy" ); + positionCompt( compts[0], side, true ); + } + if ( compts.size() == 3 ) { + double side = Field< double >::get( compts[1], "dy" ); + positionCompt( compts[0], side, true ); + positionCompt( compts[2], side, false ); + } + */ + /* + for ( vector< ObjId >::const_iterator + i = compts.begin(); i != compts.end(); ++i ) { + string simpath = i->path() + "/##"; + Id ksolve; + if ( isGsolve ) + ksolve = s->doCreate( "Gsolve", *i, "gsolve", 1 ); + else + ksolve = s->doCreate( "Ksolve", *i, "ksolve", 1 ); + dsolve = s->doCreate("Dsolve,") + Id stoich = s->doCreate( "Stoich", *i, "stoich", 1 ); + stoichVec.push_back( stoich ); + Field< Id >::set( stoich, "compartment", *i ); + Field< Id >::set( stoich, "ksolve", ksolve ); + Field< string >::set( stoich, "path", simpath ); + } + */ + /* Not needed now that we use xfer pools to cross compartments. + if ( stoichVec.size() == 2 ) { + SetGet1< Id >::set( stoichVec[1], "buildXreacs", stoichVec[0] ); + } + if ( stoichVec.size() == 3 ) { + SetGet1< Id >::set( stoichVec[1], "buildXreacs", stoichVec[0] ); + SetGet1< Id >::set( stoichVec[1], "buildXreacs", stoichVec[2] ); + } + for ( vector< Id >::iterator + i = stoichVec.begin(); i != stoichVec.end(); ++i ) { + SetGet0::set( *i, "filterXreacs" ); + } + */ } void setMethod( Shell* s, Id mgr, double simdt, double plotdt, - const string& method ) + const string& method ) { - vector< ObjId > ret; - simpleWildcardFind( mgr.path() + "/#[ISA=ChemCompt]", ret ); - assert( ret.size() > 0 ); - - Id compt( mgr.path() + "/kinetics" ); - assert( compt != Id() ); - string simpath2 = mgr.path() + "/##[ISA=StimulusTable]," + - mgr.path() + "/##[ISA=PulseGen]"; - string m = lower( method ); + vector< ObjId > ret; + simpleWildcardFind( mgr.path() + "/#[ISA=ChemCompt]", ret ); + assert( ret.size() > 0 ); + + Id compt( mgr.path() + "/kinetics" ); + assert( compt != Id() ); + string simpath2 = mgr.path() + "/##[ISA=StimulusTable]," + + mgr.path() + "/##[ISA=PulseGen]"; + string m = lower( method ); /* - if ( m == "ksolve" || m =="gsl" || m == "gssa" || m == "gsolve" || - m == "gillespie" || m == "stochastic" ) - { - cout << " Warning: Default solver set is Exponential Euler. To set \'gsl\' or \'gssa\' solver use function mooseaddChemSolver(modelpath,\'solverType\')"<<"\n"; - } - - - if ( m == "rk4" ) { - cout << "Warning, not yet implemented. Using rk5 instead\n"; - m = "rk5"; - } - if ( m == "ksolve" || m == "gsl" || - m == "rk5" || m == "rkf" || m == "rk" ) { - makeSolverOnCompt( s, mgr, ret, false ); - } else if ( m == "gssa" || m == "gsolve" || - m == "gillespie" || m == "stochastic" ) { - makeSolverOnCompt( s, mgr,ret, true ); - } else if ( m == "ee" || m == "neutral" ) { - // s->doUseClock( simpath, "process", 4 ); - // s->doSetClock( 4, simdt ); - } else { - cout << "ReadKkit::setMethod: option " << method << - " not known, using Exponential Euler (ee)\n"; - // s->doUseClock( simpath, "process", 4 ); - // s->doSetClock( 4, simdt ); - } - */ - s->doUseClock( simpath2, "proc", 11 ); - s->doSetClock( 10, simdt ); - s->doSetClock( 11, simdt ); - s->doSetClock( 12, simdt ); - s->doSetClock( 13, simdt ); - s->doSetClock( 14, simdt ); - s->doSetClock( 15, plotdt ); // Gsolve and Ksolve - s->doSetClock( 16, plotdt ); // Gsolve and Ksolve - s->doSetClock( 17, plotdt ); // Stats objects - s->doSetClock( 18, plotdt ); // Table2 objects. + if ( m == "ksolve" || m =="gsl" || m == "gssa" || m == "gsolve" || + m == "gillespie" || m == "stochastic" ) + { + cout << " Warning: Default solver set is Exponential Euler. To set \'gsl\' or \'gssa\' solver use function mooseaddChemSolver(modelpath,\'solverType\')"<<"\n"; + } + + + if ( m == "rk4" ) { + cout << "Warning, not yet implemented. Using rk5 instead\n"; + m = "rk5"; + } + if ( m == "ksolve" || m == "gsl" || + m == "rk5" || m == "rkf" || m == "rk" ) { + makeSolverOnCompt( s, mgr, ret, false ); + } else if ( m == "gssa" || m == "gsolve" || + m == "gillespie" || m == "stochastic" ) { + makeSolverOnCompt( s, mgr,ret, true ); + } else if ( m == "ee" || m == "neutral" ) { + // s->doUseClock( simpath, "process", 4 ); + // s->doSetClock( 4, simdt ); + } else { + cout << "ReadKkit::setMethod: option " << method << + " not known, using Exponential Euler (ee)\n"; + // s->doUseClock( simpath, "process", 4 ); + // s->doSetClock( 4, simdt ); + } + */ + s->doUseClock( simpath2, "proc", 11 ); + s->doSetClock( 10, simdt ); + s->doSetClock( 11, simdt ); + s->doSetClock( 12, simdt ); + s->doSetClock( 13, simdt ); + s->doSetClock( 14, simdt ); + s->doSetClock( 15, plotdt ); // Gsolve and Ksolve + s->doSetClock( 16, plotdt ); // Gsolve and Ksolve + s->doSetClock( 17, plotdt ); // Stats objects + s->doSetClock( 18, plotdt ); // Table2 objects. } /** * The readcell function implements the old GENESIS cellreader @@ -275,348 +280,381 @@ void setMethod( Shell* s, Id mgr, double simdt, double plotdt, * of parser and is likely to remain a legacy for a while. */ Id ReadKkit::read( - const string& filename, - const string& modelname, - Id pa, const string& methodArg ) + const string& filename, + const string& modelname, + Id pa, const string& methodArg ) { - string method = methodArg; - ifstream fin( filename.c_str() ); - if (!fin){ - cerr << "ReadKkit::read: could not open file " << filename << endl; - return Id(); - } - - if ( method.substr(0, 4) == "old_" ) { - moveOntoCompartment_ = false; - method = method.substr( 4 ); - } - - Shell* s = reinterpret_cast< Shell* >( ObjId().data() ); - Id mgr = makeStandardElements( pa, modelname ); - assert( mgr != Id() ); - baseId_ = mgr; - basePath_ = mgr.path(); - enzCplxMols_.resize( 0 ); - - innerRead( fin ); - assignPoolCompartments(); - assignReacCompartments(); - assignEnzCompartments(); - assignMMenzCompartments(); - - convertParametersToConcUnits(); - - setMethod( s, mgr, simdt_, plotdt_, method ); - - //Harsha: Storing solver and runtime at model level rather than model level - Id kinetics( basePath_+"/kinetics"); - assert(kinetics != Id()); - Id cInfo = s->doCreate( "Annotator", basePath_, "info", 1 ); - assert( cInfo != Id() ); - Field< string > ::set(cInfo, "solver", "ee"); - Field< double > ::set(cInfo, "runtime", maxtime_); - s->doReinit(); - return mgr; + string method = methodArg; + ifstream fin( filename.c_str() ); + if (!fin) + { + cerr << "ReadKkit::read: could not open file " << filename << endl; + return Id(); + } + + if ( method.substr(0, 4) == "old_" ) + { + moveOntoCompartment_ = false; + method = method.substr( 4 ); + } + + Shell* s = reinterpret_cast< Shell* >( ObjId().data() ); + Id mgr = makeStandardElements( pa, modelname ); + assert( mgr != Id() ); + baseId_ = mgr; + basePath_ = mgr.path(); + enzCplxMols_.resize( 0 ); + + innerRead( fin ); + assignPoolCompartments(); + assignReacCompartments(); + assignEnzCompartments(); + assignMMenzCompartments(); + + convertParametersToConcUnits(); + + setMethod( s, mgr, simdt_, plotdt_, method ); + + //Harsha: Storing solver and runtime at model level rather than model level + Id kinetics( basePath_+"/kinetics"); + assert(kinetics != Id()); + Id cInfo = s->doCreate( "Annotator", basePath_, "info", 1 ); + assert( cInfo != Id() ); + Field< string > ::set(cInfo, "solver", "ee"); + Field< double > ::set(cInfo, "runtime", maxtime_); + s->doReinit(); + return mgr; } void ReadKkit::run() { - shell_->doSetClock( 11, simdt_ ); - shell_->doSetClock( 12, simdt_ ); - shell_->doSetClock( 13, simdt_ ); - shell_->doSetClock( 14, simdt_ ); - shell_->doSetClock( 16, plotdt_ ); - shell_->doSetClock( 17, plotdt_ ); - shell_->doSetClock( 18, plotdt_ ); - shell_->doReinit(); - if ( useVariableDt_ ) { - shell_->doSetClock( 11, fastdt_ ); - shell_->doSetClock( 12, fastdt_ ); - shell_->doSetClock( 13, fastdt_ ); - shell_->doSetClock( 14, fastdt_ ); - shell_->doStart( transientTime_ ); - shell_->doSetClock( 11, simdt_ ); - shell_->doSetClock( 12, simdt_ ); - shell_->doSetClock( 13, simdt_ ); - shell_->doSetClock( 14, simdt_ ); - shell_->doStart( maxtime_ - transientTime_ ); - } else { - shell_->doStart( maxtime_ ); - } + shell_->doSetClock( 11, simdt_ ); + shell_->doSetClock( 12, simdt_ ); + shell_->doSetClock( 13, simdt_ ); + shell_->doSetClock( 14, simdt_ ); + shell_->doSetClock( 16, plotdt_ ); + shell_->doSetClock( 17, plotdt_ ); + shell_->doSetClock( 18, plotdt_ ); + shell_->doReinit(); + if ( useVariableDt_ ) + { + shell_->doSetClock( 11, fastdt_ ); + shell_->doSetClock( 12, fastdt_ ); + shell_->doSetClock( 13, fastdt_ ); + shell_->doSetClock( 14, fastdt_ ); + shell_->doStart( transientTime_ ); + shell_->doSetClock( 11, simdt_ ); + shell_->doSetClock( 12, simdt_ ); + shell_->doSetClock( 13, simdt_ ); + shell_->doSetClock( 14, simdt_ ); + shell_->doStart( maxtime_ - transientTime_ ); + } + else + { + shell_->doStart( maxtime_ ); + } } void ReadKkit::dumpPlots( const string& filename ) { - // ofstream fout ( filename.c_str() ); - vector< ObjId > plots; - string plotpath = basePath_ + "/graphs/##[TYPE=Table2]," + - basePath_ + "/moregraphs/##[TYPE=Table2]"; - wildcardFind( plotpath, plots ); - for ( vector< ObjId >::iterator - i = plots.begin(); i != plots.end(); ++i ) - SetGet2< string, string >::set( *i, "xplot", - filename, i->element()->getName() ); + // ofstream fout ( filename.c_str() ); + vector< ObjId > plots; + string plotpath = basePath_ + "/graphs/##[TYPE=Table2]," + + basePath_ + "/moregraphs/##[TYPE=Table2]"; + wildcardFind( plotpath, plots ); + for ( vector< ObjId >::iterator + i = plots.begin(); i != plots.end(); ++i ) + SetGet2< string, string >::set( *i, "xplot", + filename, i->element()->getName() ); } void ReadKkit::innerRead( ifstream& fin ) { - string line; - string temp; - lineNum_ = 0; - string::size_type pos; - bool clearLine = 1; - ParseMode parseMode = INIT; - - while ( getline( fin, temp ) ) { - lineNum_++; - if ( clearLine ) - line = ""; - temp = moose::trim(temp); - if ( temp.length() == 0 ) - continue; - pos = temp.find_last_not_of( "\t " ); - if ( pos == string::npos ) { - // Nothing new in line, go with what was left earlier, - // and clear out line for the next cycle. - temp = ""; - clearLine = 1; - } else { - if ( temp[pos] == '\\' ) { - temp[pos] = ' '; - line.append( temp ); - clearLine = 0; - continue; - } else { - line.append( temp ); - clearLine = 1; - } - } - - pos = line.find_first_not_of( "\t " ); - if ( pos == string::npos ) - continue; - else - line = line.substr( pos ); - if ( line.substr( 0, 2 ) == "//" ) - continue; - if ( (pos = line.find("//")) != string::npos ) - line = line.substr( 0, pos ); - if ( line.substr( 0, 2 ) == "/*" ) { - parseMode = COMMENT; - line = line.substr( 2 ); - } - - if ( parseMode == COMMENT ) { - pos = line.find( "*/" ); - if ( pos != string::npos ) { - parseMode = DATA; - if ( line.length() > pos + 2 ) - line = line.substr( pos + 2 ); - } - } - - if ( parseMode == DATA ) - readData( line ); - else if ( parseMode == INIT ) { - parseMode = readInit( line ); - } - } - - /* - cout << " innerRead: " << - lineNum_ << " lines read, " << - numCompartments_ << " compartments, " << - numPools_ << " molecules, " << - numReacs_ << " reacs, " << - numEnz_ << " enzs, " << - numMMenz_ << " MM enzs, " << - numOthers_ << " others," << - numPlot_ << " plots," << - " PlotDt = " << plotdt_ << - endl; - */ + string line; + string temp; + lineNum_ = 0; + string::size_type pos; + bool clearLine = 1; + ParseMode parseMode = INIT; + + while ( getline( fin, temp ) ) + { + lineNum_++; + if ( clearLine ) + line = ""; + temp = moose::trim(temp); + if ( temp.length() == 0 ) + continue; + pos = temp.find_last_not_of( "\t " ); + if ( pos == string::npos ) + { + // Nothing new in line, go with what was left earlier, + // and clear out line for the next cycle. + temp = ""; + clearLine = 1; + } + else + { + if ( temp[pos] == '\\' ) + { + temp[pos] = ' '; + line.append( temp ); + clearLine = 0; + continue; + } + else + { + line.append( temp ); + clearLine = 1; + } + } + + pos = line.find_first_not_of( "\t " ); + if ( pos == string::npos ) + continue; + else + line = line.substr( pos ); + if ( line.substr( 0, 2 ) == "//" ) + continue; + if ( (pos = line.find("//")) != string::npos ) + line = line.substr( 0, pos ); + if ( line.substr( 0, 2 ) == "/*" ) + { + parseMode = COMMENT; + line = line.substr( 2 ); + } + + if ( parseMode == COMMENT ) + { + pos = line.find( "*/" ); + if ( pos != string::npos ) + { + parseMode = DATA; + if ( line.length() > pos + 2 ) + line = line.substr( pos + 2 ); + } + } + + if ( parseMode == DATA ) + readData( line ); + else if ( parseMode == INIT ) + { + parseMode = readInit( line ); + } + } + + /* + cout << " innerRead: " << + lineNum_ << " lines read, " << + numCompartments_ << " compartments, " << + numPools_ << " molecules, " << + numReacs_ << " reacs, " << + numEnz_ << " enzs, " << + numMMenz_ << " MM enzs, " << + numOthers_ << " others," << + numPlot_ << " plots," << + " PlotDt = " << plotdt_ << + endl; + */ } ReadKkit::ParseMode ReadKkit::readInit( const string& line ) { - vector< string > argv; - chopLine( line, argv ); - if ( argv.size() < 3 ) - return INIT; - - if ( argv[0] == "FASTDT" ) { - fastdt_ = atof( argv[2].c_str() ); - return INIT; - } - if ( argv[0] == "SIMDT" ) { - simdt_ = atof( argv[2].c_str() ); - return INIT; - } - if ( argv[0] == "CONTROLDT" ) { - controldt_ = atof( argv[2].c_str() ); - return INIT; - } - if ( argv[0] == "PLOTDT" ) { - plotdt_ = atof( argv[2].c_str() ); - return INIT; - } - if ( argv[0] == "MAXTIME" ) { - maxtime_ = atof( argv[2].c_str() ); - return INIT; - } - if ( argv[0] == "TRANSIENT_TIME" ) { - transientTime_ = atof( argv[2].c_str() ); - return INIT; - } - if ( argv[0] == "VARIABLE_DT_FLAG" ) { - useVariableDt_ = atoi( argv[2].c_str() ); - return INIT; - } - if ( argv[0] == "DEFAULT_VOL" ) { - defaultVol_ = atof( argv[2].c_str() ); - return INIT; - } - if ( argv[0] == "VERSION" ) { - version_ = atoi( argv[2].c_str() ); - return INIT; - } - - if ( argv[0] == "initdump" ) { - initdumpVersion_ = atoi( argv[2].c_str() ); - return DATA; - } - return INIT; + vector< string > argv; + chopLine( line, argv ); + if ( argv.size() < 3 ) + return INIT; + + if ( argv[0] == "FASTDT" ) + { + fastdt_ = atof( argv[2].c_str() ); + return INIT; + } + if ( argv[0] == "SIMDT" ) + { + simdt_ = atof( argv[2].c_str() ); + return INIT; + } + if ( argv[0] == "CONTROLDT" ) + { + controldt_ = atof( argv[2].c_str() ); + return INIT; + } + if ( argv[0] == "PLOTDT" ) + { + plotdt_ = atof( argv[2].c_str() ); + return INIT; + } + if ( argv[0] == "MAXTIME" ) + { + maxtime_ = atof( argv[2].c_str() ); + return INIT; + } + if ( argv[0] == "TRANSIENT_TIME" ) + { + transientTime_ = atof( argv[2].c_str() ); + return INIT; + } + if ( argv[0] == "VARIABLE_DT_FLAG" ) + { + useVariableDt_ = atoi( argv[2].c_str() ); + return INIT; + } + if ( argv[0] == "DEFAULT_VOL" ) + { + defaultVol_ = atof( argv[2].c_str() ); + return INIT; + } + if ( argv[0] == "VERSION" ) + { + version_ = atoi( argv[2].c_str() ); + return INIT; + } + + if ( argv[0] == "initdump" ) + { + initdumpVersion_ = atoi( argv[2].c_str() ); + return DATA; + } + return INIT; } void ReadKkit::readData( const string& line ) { - vector< string > argv; - chopLine( line, argv ); - - if ( argv[0] == "simundump" ) - undump( argv ); - else if ( argv[0] == "addmsg" ) - addmsg( argv ); - else if ( argv[0] == "call" ) - call( argv ); - else if ( argv[0] == "simobjdump" ) - objdump( argv ); - else if ( argv[0] == "xtextload" ) - textload( argv ); - else if ( argv[0] == "loadtab" ) - loadTab( argv ); + vector< string > argv; + chopLine( line, argv ); + + if ( argv[0] == "simundump" ) + undump( argv ); + else if ( argv[0] == "addmsg" ) + addmsg( argv ); + else if ( argv[0] == "call" ) + call( argv ); + else if ( argv[0] == "simobjdump" ) + objdump( argv ); + else if ( argv[0] == "xtextload" ) + textload( argv ); + else if ( argv[0] == "loadtab" ) + loadTab( argv ); } string ReadKkit::pathTail( const string& path, string& head ) const { - string::size_type pos = path.find_last_of( "/" ); - assert( pos != string::npos ); + string::size_type pos = path.find_last_of( "/" ); + assert( pos != string::npos ); - head = basePath_ + path.substr( 0, pos ); - return path.substr( pos + 1 ); + head = basePath_ + path.substr( 0, pos ); + return path.substr( pos + 1 ); } string ReadKkit::cleanPath( const string& path ) const { - // Could surely do this better with STL. But harder to understand. - // Harsha: Cleaned up this function - // minus was getting replaced with underscore, but in some genesis model - // pool and reaction/Enzyme has same string name with - // difference of minus and underscore like eIF4G_A-clx and eIF4G_A_clx, - // which later created a problem as the same name exist in moose when minus - // was replaced with underscore. - //So replacing minus with _minus_ like I do in SBML - size_t Iindex = 0; - string cleanDigit="/"; - while(true) - { - size_t sindex = path.find('/',Iindex+1); - if (sindex == string::npos) - { if (isdigit((path.substr(Iindex+1,sindex-Iindex-1))[0]) ) - cleanDigit += '_' ; - cleanDigit += path.substr(Iindex+1,sindex-Iindex-1); - break; - } - if (isdigit((path.substr(Iindex+1,sindex-Iindex-1))[0])) - cleanDigit+='_'; - cleanDigit += path.substr(Iindex+1,sindex-Iindex); - Iindex = sindex; - } - string ret = cleanDigit; - //string ret = path; - string cleanString; - for ( unsigned int i = 0; i < cleanDigit.length(); ++i ) { - char c = ret[i]; - if ( c == '*' ) - cleanString += "_p"; - else if ( c == '[' || c == ']' || c == '@' || c == ' ') - cleanString += '_'; - else if (c == '-') - cleanString += "_"; - else - cleanString += c; - } - return cleanString; + // Could surely do this better with STL. But harder to understand. + // Harsha: Cleaned up this function + // minus was getting replaced with underscore, but in some genesis model + // pool and reaction/Enzyme has same string name with + // difference of minus and underscore like eIF4G_A-clx and eIF4G_A_clx, + // which later created a problem as the same name exist in moose when minus + // was replaced with underscore. + //So replacing minus with _minus_ like I do in SBML + size_t Iindex = 0; + string cleanDigit="/"; + while(true) + { + size_t sindex = path.find('/',Iindex+1); + if (sindex == string::npos) + { + if (isdigit((path.substr(Iindex+1,sindex-Iindex-1))[0]) ) + cleanDigit += '_' ; + cleanDigit += path.substr(Iindex+1,sindex-Iindex-1); + break; + } + if (isdigit((path.substr(Iindex+1,sindex-Iindex-1))[0])) + cleanDigit+='_'; + cleanDigit += path.substr(Iindex+1,sindex-Iindex); + Iindex = sindex; + } + string ret = cleanDigit; + //string ret = path; + string cleanString; + for ( unsigned int i = 0; i < cleanDigit.length(); ++i ) + { + char c = ret[i]; + if ( c == '*' ) + cleanString += "_p"; + else if ( c == '[' || c == ']' || c == '@' || c == ' ') + cleanString += '_'; + else if (c == '-') + cleanString += "_"; + else + cleanString += c; + } + return cleanString; } void assignArgs( map< string, int >& argConv, const vector< string >& args ) { - for ( unsigned int i = 2; i != args.size(); ++i ) - argConv[ args[i] ] = i + 2; + for ( unsigned int i = 2; i != args.size(); ++i ) + argConv[ args[i] ] = i + 2; } void ReadKkit::objdump( const vector< string >& args) -{ if ( args[1] == "kpool" ) - assignArgs( poolMap_, args ); - else if ( args[1] == "kreac" ) - assignArgs( reacMap_, args ); - else if ( args[1] == "kenz" ) - assignArgs( enzMap_, args ); - else if ( args[1] == "group" ) - assignArgs( groupMap_, args ); - else if ( args[1] == "xtab" ) - assignArgs( tableMap_, args ); - else if ( args[1] == "stim" ) - assignArgs( stimMap_, args ); - else if ( args[1] == "kchan" ) - assignArgs( chanMap_, args ); +{ + if ( args[1] == "kpool" ) + assignArgs( poolMap_, args ); + else if ( args[1] == "kreac" ) + assignArgs( reacMap_, args ); + else if ( args[1] == "kenz" ) + assignArgs( enzMap_, args ); + else if ( args[1] == "group" ) + assignArgs( groupMap_, args ); + else if ( args[1] == "xtab" ) + assignArgs( tableMap_, args ); + else if ( args[1] == "stim" ) + assignArgs( stimMap_, args ); + else if ( args[1] == "kchan" ) + assignArgs( chanMap_, args ); } void ReadKkit::call( const vector< string >& args) { - /// call /kinetics/foo/notes LOAD notes_string_here - if ( args.size() > 3 ) { - unsigned int len = args[1].length(); - if ( ( args[1].substr( len - 5 ) == "notes" ) && - args[2] == "LOAD" ) { - if ( args[3].length() == 0 ) - return; - //HARSHA: Added CleanPath. - string objName = cleanPath(args[1].substr( 0, len - 5 )); - Id test(basePath_+objName); - Id obj( basePath_ + objName + "info" ); - if ( obj != Id() ) { - string notes = ""; - string space = ""; - for ( unsigned int i = 3; i < args.size(); ++i ) { - unsigned int innerLength = args[i].length(); - if ( innerLength == 0 ) - continue; - unsigned int start = 0; - unsigned int end = innerLength; - if ( args[i][0] == '\"' ) - start = 1; - if ( args[i][innerLength - 1] == '\"' ) - end = innerLength - 1 - start; - - notes += space + args[i].substr( start, end ); - space = " "; - } - Field< string >::set( obj, "notes", notes ); - } - } - } + /// call /kinetics/foo/notes LOAD notes_string_here + if ( args.size() > 3 ) + { + unsigned int len = args[1].length(); + if ( ( args[1].substr( len - 5 ) == "notes" ) && + args[2] == "LOAD" ) + { + if ( args[3].length() == 0 ) + return; + //HARSHA: Added CleanPath. + string objName = cleanPath(args[1].substr( 0, len - 5 )); + Id test(basePath_+objName); + Id obj( basePath_ + objName + "info" ); + if ( obj != Id() ) + { + string notes = ""; + string space = ""; + for ( unsigned int i = 3; i < args.size(); ++i ) + { + unsigned int innerLength = args[i].length(); + if ( innerLength == 0 ) + continue; + unsigned int start = 0; + unsigned int end = innerLength; + if ( args[i][0] == '\"' ) + start = 1; + if ( args[i][innerLength - 1] == '\"' ) + end = innerLength - 1 - start; + + notes += space + args[i].substr( start, end ); + space = " "; + } + Field< string >::set( obj, "notes", notes ); + } + } + } } void ReadKkit::textload( const vector< string >& args) @@ -624,182 +662,192 @@ void ReadKkit::textload( const vector< string >& args) } void ReadKkit::undump( const vector< string >& args) -{ if ( args[1] == "kpool" ) - buildPool( args ); - else if ( args[1] == "kreac" ) - buildReac( args ); - else if ( args[1] == "kenz" ) - buildEnz( args ); - else if ( args[1] == "text" ) - buildText( args ); - else if ( args[1] == "xplot" ) - buildPlot( args ); - else if ( args[1] == "xgraph" ) - buildGraph( args ); - else if ( args[1] == "group" ) - buildGroup( args ); - else if ( args[1] == "geometry" ) - buildGeometry( args ); - else if ( args[1] == "stim" ) - buildStim( args ); - else if ( args[1] == "xcoredraw" ) - ; - else if ( args[1] == "xtree" ) - ; - else if ( args[1] == "xtext" ) - ; - else if ( args[1] == "doqcsinfo" ) - ; - else if ( args[1] == "kchan" ) - buildChan( args ); - else if ( args[1] == "xtab" ) - buildTable( args ); - else - cout << "ReadKkit::undump: Do not know how to build '" << args[1] << - "'\n"; +{ + if ( args[1] == "kpool" ) + buildPool( args ); + else if ( args[1] == "kreac" ) + buildReac( args ); + else if ( args[1] == "kenz" ) + buildEnz( args ); + else if ( args[1] == "text" ) + buildText( args ); + else if ( args[1] == "xplot" ) + buildPlot( args ); + else if ( args[1] == "xgraph" ) + buildGraph( args ); + else if ( args[1] == "group" ) + buildGroup( args ); + else if ( args[1] == "geometry" ) + buildGeometry( args ); + else if ( args[1] == "stim" ) + buildStim( args ); + else if ( args[1] == "xcoredraw" ) + ; + else if ( args[1] == "xtree" ) + ; + else if ( args[1] == "xtext" ) + ; + else if ( args[1] == "doqcsinfo" ) + ; + else if ( args[1] == "kchan" ) + buildChan( args ); + else if ( args[1] == "xtab" ) + buildTable( args ); + else + cout << "ReadKkit::undump: Do not know how to build '" << args[1] << + "'\n"; } Id ReadKkit::buildCompartment( const vector< string >& args ) { - Id compt; - numCompartments_++; - return compt; + Id compt; + numCompartments_++; + return compt; } Id ReadKkit::buildReac( const vector< string >& args ) { - string head; - string clean = cleanPath( args[2] ); - string tail = pathTail( clean, head ); - Id pa = shell_->doFind( head ).id; - assert( pa != Id() ); - - double kf = atof( args[ reacMap_[ "kf" ] ].c_str() ); - double kb = atof( args[ reacMap_[ "kb" ] ].c_str() ); - - // We have a slight problem because MOOSE has a more precise value for - // NA than does kkit. Here we assume that the conc units from Kkit are - // meant to be OK, so they override the #/cell (lower case k) units. - // So we convert all the Kfs and Kbs in the entire system after - // the model has been created, once we know the order of each reac. - - Id reac = shell_->doCreate( "Reac", pa, tail, 1 ); - reacIds_[ clean.substr( 10 ) ] = reac; - // Here is another hack: The native values stored in the reac are - // Kf and Kb, in conc units. However the 'clean' values from kkit - // are the number values numKf and numKb. In the - // function convertReacRatesToNumUnits we take the numKf and numKb and - // do proper conc scaling. - Field< double >::set( reac, "Kf", kf ); - Field< double >::set( reac, "Kb", kb ); - - Id info = buildInfo( reac, reacMap_, args ); - numReacs_++; - return reac; + string head; + string clean = cleanPath( args[2] ); + string tail = pathTail( clean, head ); + Id pa = shell_->doFind( head ).id; + assert( pa != Id() ); + + double kf = atof( args[ reacMap_[ "kf" ] ].c_str() ); + double kb = atof( args[ reacMap_[ "kb" ] ].c_str() ); + + // We have a slight problem because MOOSE has a more precise value for + // NA than does kkit. Here we assume that the conc units from Kkit are + // meant to be OK, so they override the #/cell (lower case k) units. + // So we convert all the Kfs and Kbs in the entire system after + // the model has been created, once we know the order of each reac. + + Id reac = shell_->doCreate( "Reac", pa, tail, 1 ); + reacIds_[ clean.substr( 10 ) ] = reac; + // Here is another hack: The native values stored in the reac are + // Kf and Kb, in conc units. However the 'clean' values from kkit + // are the number values numKf and numKb. In the + // function convertReacRatesToNumUnits we take the numKf and numKb and + // do proper conc scaling. + Field< double >::set( reac, "Kf", kf ); + Field< double >::set( reac, "Kb", kb ); + + Id info = buildInfo( reac, reacMap_, args ); + numReacs_++; + return reac; } void ReadKkit::separateVols( Id pool, double vol ) { - static const double TINY = 1e-3; - - for ( unsigned int i = 0 ; i < vols_.size(); ++i ) { - if ( fabs( vols_[i] - vol ) / ( fabs( vols_[i] ) + fabs( vol ) ) < TINY ) { - volCategories_[i].push_back( pool ); - return; - } - } - vols_.push_back( vol ); - vector< Id > temp( 1, pool ); - volCategories_.push_back( temp ); + static const double TINY = 1e-3; + + for ( unsigned int i = 0 ; i < vols_.size(); ++i ) + { + if ( fabs( vols_[i] - vol ) / ( fabs( vols_[i] ) + fabs( vol ) ) < TINY ) + { + volCategories_[i].push_back( pool ); + return; + } + } + vols_.push_back( vol ); + vector< Id > temp( 1, pool ); + volCategories_.push_back( temp ); } bool volCompare( - const pair< unsigned int, double >& A, - const pair< unsigned int, double >& B ) + const pair< unsigned int, double >& A, + const pair< unsigned int, double >& B ) { - return A.second < B.second; + return A.second < B.second; } // Returns the ranking of each volume. Largest is 0. This would be the // suffix to attach to the compartment name. vector< unsigned int > findVolOrder( const vector< double >& vols ) { - vector< pair< unsigned int, double > > p( vols.size() ); - for ( unsigned int i = 0; i < vols.size(); ++i ) { - p[i].first = i; - p[i].second = vols[i]; - } - sort( p.begin(), p.end(), volCompare ); - vector< unsigned int > ret( vols.size() ); - for ( unsigned int i = 0; i < vols.size(); ++i ) { - ret[ vols.size() -i -1 ] = p[i].first; - } - return ret; + vector< pair< unsigned int, double > > p( vols.size() ); + for ( unsigned int i = 0; i < vols.size(); ++i ) + { + p[i].first = i; + p[i].second = vols[i]; + } + sort( p.begin(), p.end(), volCompare ); + vector< unsigned int > ret( vols.size() ); + for ( unsigned int i = 0; i < vols.size(); ++i ) + { + ret[ vols.size() -i -1 ] = p[i].first; + } + return ret; } // We assume that the biggest compartment contains all the rest. // This is not true in synapses, where they are adjacent. void ReadKkit::assignPoolCompartments() { - Id kinetics = Neutral::child( baseId_.eref(), "kinetics" ); - assert( kinetics != Id() ); - vector< unsigned int > volOrder = findVolOrder( vols_ ); - assert( volCategories_.size() == vols_.size() ); - assert( volCategories_.size() == volOrder.size() ); - - for ( unsigned int j = 0 ; j < volOrder.size(); ++j ) { - unsigned int i = volOrder[j]; - if ( vols_[i] < 0 ) // Special case for enz complexes: vol == -1. - continue; - string name; - Id kinId = Neutral::child( baseId_.eref(), "kinetics" ); - assert( kinId != Id() ); - Id comptId; - // if ( i == maxi ) - if ( j == 0 ) { - comptId = kinId; - } else { - stringstream ss; - ss << "compartment_" << j; - name = ss.str(); - comptId = Neutral::child( baseId_.eref(), name ); - if ( comptId == Id() ) - comptId = shell_->doCreate( "CubeMesh", baseId_, name, 1 ); - } - SetGet1< double >::set( comptId, "setVolumeNotRates",vols_[i]); - /* - if ( comptId.element()->cinfo()->isA( "CubeMesh" ) ) { - double side = pow( vols_[i], 1.0 / 3.0 ); - vector< double > coords( 9, side ); - coords[0] = coords[1] = coords[2] = 0; - // Field< double >::set( comptId, "volume", vols_[i] ); - Field< vector< double > >::set( comptId, "coords", coords ); - } else { - } - */ - // compartments_.push_back( comptId ); - for ( vector< Id >::iterator k = volCategories_[i].begin(); - k != volCategories_[i].end(); ++k ) { - // if ( moveOntoCompartment_ ) { - if ( ! (getCompt( *k ).id == comptId ) ) - shell_->doMove( *k, comptId ); - // } - } - } + Id kinetics = Neutral::child( baseId_.eref(), "kinetics" ); + assert( kinetics != Id() ); + vector< unsigned int > volOrder = findVolOrder( vols_ ); + assert( volCategories_.size() == vols_.size() ); + assert( volCategories_.size() == volOrder.size() ); + + for ( unsigned int j = 0 ; j < volOrder.size(); ++j ) + { + unsigned int i = volOrder[j]; + if ( vols_[i] < 0 ) // Special case for enz complexes: vol == -1. + continue; + string name; + Id kinId = Neutral::child( baseId_.eref(), "kinetics" ); + assert( kinId != Id() ); + Id comptId; + // if ( i == maxi ) + if ( j == 0 ) + { + comptId = kinId; + } + else + { + stringstream ss; + ss << "compartment_" << j; + name = ss.str(); + comptId = Neutral::child( baseId_.eref(), name ); + if ( comptId == Id() ) + comptId = shell_->doCreate( "CubeMesh", baseId_, name, 1 ); + } + SetGet1< double >::set( comptId, "setVolumeNotRates",vols_[i]); + /* + if ( comptId.element()->cinfo()->isA( "CubeMesh" ) ) { + double side = pow( vols_[i], 1.0 / 3.0 ); + vector< double > coords( 9, side ); + coords[0] = coords[1] = coords[2] = 0; + // Field< double >::set( comptId, "volume", vols_[i] ); + Field< vector< double > >::set( comptId, "coords", coords ); + } else { + } + */ + // compartments_.push_back( comptId ); + for ( vector< Id >::iterator k = volCategories_[i].begin(); + k != volCategories_[i].end(); ++k ) + { + // if ( moveOntoCompartment_ ) { + if ( ! (getCompt( *k ).id == comptId ) ) + shell_->doMove( *k, comptId ); + // } + } + } } Id findParentComptOfReac( Id reac ) { - static const Finfo* subFinfo = - ReacBase::initCinfo()->findFinfo( "subOut" ); - assert( subFinfo ); - - vector< Id > subVec; - reac.element()->getNeighbors( subVec, subFinfo ); - if ( subVec.size() == 0 ) // Dangling reaction - return Id(); - // For now just put the reac in the compt belonging to the - // first substrate - return getCompt( subVec[0] ); + static const Finfo* subFinfo = + ReacBase::initCinfo()->findFinfo( "subOut" ); + assert( subFinfo ); + + vector< Id > subVec; + reac.element()->getNeighbors( subVec, subFinfo ); + if ( subVec.size() == 0 ) // Dangling reaction + return Id(); + // For now just put the reac in the compt belonging to the + // first substrate + return getCompt( subVec[0] ); } /** @@ -810,14 +858,16 @@ Id findParentComptOfReac( Id reac ) */ void ReadKkit::assignReacCompartments() { - for ( map< string, Id >::iterator i = reacIds_.begin(); - i != reacIds_.end(); ++i ) { - Id compt = findParentComptOfReac( i->second ); - if ( compt != Id() ) { - if ( ! (getCompt( i->second ).id == compt ) ) - shell_->doMove( i->second, compt ); - } - } + for ( map< string, Id >::iterator i = reacIds_.begin(); + i != reacIds_.end(); ++i ) + { + Id compt = findParentComptOfReac( i->second ); + if ( compt != Id() ) + { + if ( ! (getCompt( i->second ).id == compt ) ) + shell_->doMove( i->second, compt ); + } + } } @@ -828,15 +878,15 @@ void ReadKkit::assignReacCompartments() */ Id findMeshOfEnz( Id enz ) { - static const Finfo* enzFinfo = - EnzBase::initCinfo()->findFinfo( "enzOut" ); - assert( enzFinfo ); - - vector< Id > enzVec; - enz.element()->getNeighbors( enzVec, enzFinfo ); - assert( enzVec.size() == 1 ); - vector< Id > meshEntries; - return getCompt( enzVec[0] ); + static const Finfo* enzFinfo = + EnzBase::initCinfo()->findFinfo( "enzOut" ); + assert( enzFinfo ); + + vector< Id > enzVec; + enz.element()->getNeighbors( enzVec, enzFinfo ); + assert( enzVec.size() == 1 ); + vector< Id > meshEntries; + return getCompt( enzVec[0] ); } /** @@ -847,17 +897,17 @@ Id findMeshOfEnz( Id enz ) */ void ReadKkit::assignEnzCompartments() { - /* - Should not be needed, because the parent pool will move. - for ( map< string, Id >::iterator i = enzIds_.begin(); - i != enzIds_.end(); ++i ) { - Id compt = getCompt( Neutral::parent( i->second ).id ); - if ( moveOntoCompartment_ ) { - if ( ! (getCompt( i->second ).id == compt ) ) - shell_->doMove( i->second, compt ); - } - } - */ + /* + Should not be needed, because the parent pool will move. + for ( map< string, Id >::iterator i = enzIds_.begin(); + i != enzIds_.end(); ++i ) { + Id compt = getCompt( Neutral::parent( i->second ).id ); + if ( moveOntoCompartment_ ) { + if ( ! (getCompt( i->second ).id == compt ) ) + shell_->doMove( i->second, compt ); + } + } + */ } /** @@ -868,140 +918,143 @@ void ReadKkit::assignEnzCompartments() */ void ReadKkit::assignMMenzCompartments() { - /* - Should not be needed, because the parent pool will move. - for ( map< string, Id >::iterator i = mmEnzIds_.begin(); - i != mmEnzIds_.end(); ++i ) { - Id compt = getCompt( Neutral::parent( i->second ).id ); - if ( moveOntoCompartment_ ) { - if ( ! (getCompt( i->second ).id == compt ) ) - shell_->doMove( i->second, compt ); - } - } - */ + /* + Should not be needed, because the parent pool will move. + for ( map< string, Id >::iterator i = mmEnzIds_.begin(); + i != mmEnzIds_.end(); ++i ) { + Id compt = getCompt( Neutral::parent( i->second ).id ); + if ( moveOntoCompartment_ ) { + if ( ! (getCompt( i->second ).id == compt ) ) + shell_->doMove( i->second, compt ); + } + } + */ } Id ReadKkit::buildEnz( const vector< string >& args ) { - string head; - string clean = cleanPath( args[2] ); - string tail = pathTail( clean, head ); - Id pa = shell_->doFind( head ).id; - assert ( pa != Id() ); - - double k1 = atof( args[ enzMap_[ "k1" ] ].c_str() ); - double k2 = atof( args[ enzMap_[ "k2" ] ].c_str() ); - double k3 = atof( args[ enzMap_[ "k3" ] ].c_str() ); - // double volscale = atof( args[ enzMap_[ "vol" ] ].c_str() ); - double nComplexInit = - atof( args[ enzMap_[ "nComplexInit" ] ].c_str() ); - // double vol = atof( args[ enzMap_[ "vol" ] ].c_str()); - bool isMM = atoi( args[ enzMap_[ "usecomplex" ] ].c_str()); - assert( poolVols_.find( pa ) != poolVols_.end() ); - double vol = poolVols_[ pa ]; - - /** - * vsf is vol scale factor, which is what GENESIS stores in 'vol' field - * n = vsf * conc( uM ) - * Also, n = ( conc (uM) / 1e6 ) * NA * vol - * so, vol = 1e6 * vsf / NA - */ - - if ( isMM ) { - Id enz = shell_->doCreate( "MMenz", pa, tail, 1 ); - assert( enz != Id () ); - string mmEnzPath = clean.substr( 10 ); - mmEnzIds_[ mmEnzPath ] = enz; - - assert( k1 > EPSILON ); - double Km = ( k2 + k3 ) / k1; - - Field< double >::set( enz, "Km", Km ); - Field< double >::set( enz, "kcat", k3 ); - Id info = buildInfo( enz, enzMap_, args ); - numMMenz_++; - return enz; - } else { - Id enz = shell_->doCreate( "Enz", pa, tail, 1 ); - // double parentVol = Field< double >::get( pa, "volume" ); - assert( enz != Id () ); - string enzPath = clean.substr( 10 ); - enzIds_[ enzPath ] = enz; - - // Need to figure out what to do about these. Perhaps it is OK - // to do this assignments in raw #/cell units. - Field< double >::set( enz, "k3", k3 ); - Field< double >::set( enz, "k2", k2 ); - // Here we explicitly calculate Km because the substrates are - // not set up till later, and without them the volume calculations - // are confused. - double volScale = lookupVolumeFromMesh(pa.eref()); - double Km = (k2+k3)/(k1 * KKIT_NA * vol ); // Scaling for uM to mM. - SetGet2< double, double >::set( enz, "setKmK1", Km, k1 ); - - string cplxName = tail + "_cplx"; - string cplxPath = enzPath + "/" + cplxName; - Id cplx = shell_->doCreate( "Pool", enz, cplxName, 1 ); - assert( cplx != Id () ); - poolIds_[ cplxPath ] = cplx; - // Field< double >::set( cplx, "nInit", nComplexInit ); - Field< double >::set( cplx, "nInit", nComplexInit ); - - // Use this later to assign mesh entries to enz cplx. - enzCplxMols_.push_back( pair< Id, Id >( pa, cplx ) ); - separateVols( cplx, -1 ); // -1 vol is a flag to defer mesh assignment for the cplx pool. - - ObjId ret = shell_->doAddMsg( "OneToAll", - ObjId( enz, 0 ), "cplx", - ObjId( cplx, 0 ), "reac" ); - assert( ret != ObjId() ); - - - // cplx()->showFields(); - // enz()->showFields(); - // pa()->showFields(); - Id info = buildInfo( enz, enzMap_, args ); - numEnz_++; - return enz; - } + string head; + string clean = cleanPath( args[2] ); + string tail = pathTail( clean, head ); + Id pa = shell_->doFind( head ).id; + assert ( pa != Id() ); + + double k1 = atof( args[ enzMap_[ "k1" ] ].c_str() ); + double k2 = atof( args[ enzMap_[ "k2" ] ].c_str() ); + double k3 = atof( args[ enzMap_[ "k3" ] ].c_str() ); + // double volscale = atof( args[ enzMap_[ "vol" ] ].c_str() ); + double nComplexInit = + atof( args[ enzMap_[ "nComplexInit" ] ].c_str() ); + // double vol = atof( args[ enzMap_[ "vol" ] ].c_str()); + bool isMM = atoi( args[ enzMap_[ "usecomplex" ] ].c_str()); + assert( poolVols_.find( pa ) != poolVols_.end() ); + double vol = poolVols_[ pa ]; + + /** + * vsf is vol scale factor, which is what GENESIS stores in 'vol' field + * n = vsf * conc( uM ) + * Also, n = ( conc (uM) / 1e6 ) * NA * vol + * so, vol = 1e6 * vsf / NA + */ + + if ( isMM ) + { + Id enz = shell_->doCreate( "MMenz", pa, tail, 1 ); + assert( enz != Id () ); + string mmEnzPath = clean.substr( 10 ); + mmEnzIds_[ mmEnzPath ] = enz; + + assert( k1 > EPSILON ); + double Km = ( k2 + k3 ) / k1; + + Field< double >::set( enz, "Km", Km ); + Field< double >::set( enz, "kcat", k3 ); + Id info = buildInfo( enz, enzMap_, args ); + numMMenz_++; + return enz; + } + else + { + Id enz = shell_->doCreate( "Enz", pa, tail, 1 ); + // double parentVol = Field< double >::get( pa, "volume" ); + assert( enz != Id () ); + string enzPath = clean.substr( 10 ); + enzIds_[ enzPath ] = enz; + + // Need to figure out what to do about these. Perhaps it is OK + // to do this assignments in raw #/cell units. + Field< double >::set( enz, "k3", k3 ); + Field< double >::set( enz, "k2", k2 ); + // Here we explicitly calculate Km because the substrates are + // not set up till later, and without them the volume calculations + // are confused. + double volScale = lookupVolumeFromMesh(pa.eref()); + double Km = (k2+k3)/(k1 * KKIT_NA * vol ); // Scaling for uM to mM. + SetGet2< double, double >::set( enz, "setKmK1", Km, k1 ); + + string cplxName = tail + "_cplx"; + string cplxPath = enzPath + "/" + cplxName; + Id cplx = shell_->doCreate( "Pool", enz, cplxName, 1 ); + assert( cplx != Id () ); + poolIds_[ cplxPath ] = cplx; + // Field< double >::set( cplx, "nInit", nComplexInit ); + Field< double >::set( cplx, "nInit", nComplexInit ); + + // Use this later to assign mesh entries to enz cplx. + enzCplxMols_.push_back( pair< Id, Id >( pa, cplx ) ); + separateVols( cplx, -1 ); // -1 vol is a flag to defer mesh assignment for the cplx pool. + + ObjId ret = shell_->doAddMsg( "OneToAll", + ObjId( enz, 0 ), "cplx", + ObjId( cplx, 0 ), "reac" ); + assert( ret != ObjId() ); + + + // cplx()->showFields(); + // enz()->showFields(); + // pa()->showFields(); + Id info = buildInfo( enz, enzMap_, args ); + numEnz_++; + return enz; + } } Id ReadKkit::buildText( const vector< string >& args ) { - Id text; - numOthers_++; - return text; + Id text; + numOthers_++; + return text; } Id ReadKkit::buildInfo( Id parent, - map< string, int >& m, const vector< string >& args ) + map< string, int >& m, const vector< string >& args ) { - Id info = shell_->doCreate( "Annotator", parent, "info", 1 ); - assert( info != Id() ); - - double x = atof( args[ m[ "x" ] ].c_str() ); - double y = atof( args[ m[ "y" ] ].c_str() ); - - Field< double >::set( info, "x", x ); - Field< double >::set( info, "y", y ); - Field< string >::set( info, "color", args[ m[ "xtree_fg_req" ] ] ); - Field< string >::set( info, "textColor", - args[ m[ "xtree_textfg_req" ] ] ); - return info; + Id info = shell_->doCreate( "Annotator", parent, "info", 1 ); + assert( info != Id() ); + + double x = atof( args[ m[ "x" ] ].c_str() ); + double y = atof( args[ m[ "y" ] ].c_str() ); + + Field< double >::set( info, "x", x ); + Field< double >::set( info, "y", y ); + Field< string >::set( info, "color", args[ m[ "xtree_fg_req" ] ] ); + Field< string >::set( info, "textColor", + args[ m[ "xtree_textfg_req" ] ] ); + return info; } Id ReadKkit::buildGroup( const vector< string >& args ) { - string head; - string tail = pathTail( cleanPath( args[2] ), head ); - Id pa = shell_->doFind( head ).id; - assert( pa != Id() ); - Id group = shell_->doCreate( "Neutral", pa, tail, 1 ); - assert( group != Id() ); - Id info = buildInfo( group, groupMap_, args ); - - numOthers_++; - return group; + string head; + string tail = pathTail( cleanPath( args[2] ), head ); + Id pa = shell_->doFind( head ).id; + assert( pa != Id() ); + Id group = shell_->doCreate( "Neutral", pa, tail, 1 ); + assert( group != Id() ); + Id info = buildInfo( group, groupMap_, args ); + + numOthers_++; + return group; } /** @@ -1014,62 +1067,67 @@ Id ReadKkit::buildGroup( const vector< string >& args ) * traffic are originally framed in terms of number of receptors, not conc. */ Id ReadKkit::buildPool( const vector< string >& args ) -{ - string head; - string clean = cleanPath( args[2] ); - string tail = pathTail( clean, head ); - Id pa = shell_->doFind( head ).id; - assert( pa != Id() ); - - double nInit = atof( args[ poolMap_[ "nInit" ] ].c_str() ); - double vsf = atof( args[ poolMap_[ "vol" ] ].c_str() ); - /** - * vsf is vol scale factor, which is what GENESIS stores in 'vol' field - * n = vsf * conc( uM ) - * Also, n = ( conc (uM) / 1e6 ) * NA * vol - * so, vol = 1e6 * vsf / NA - */ - double vol = 1.0e3 * vsf / KKIT_NA; // Converts volscale to actual vol in m^3 - int slaveEnable = atoi( args[ poolMap_[ "slave_enable" ] ].c_str() ); - double diffConst = atof( args[ poolMap_[ "DiffConst" ] ].c_str() ); - - // I used -ve D as a flag to replace pool-specific D - // with the global value of D. Here we just ignore it. - if ( diffConst < 0 ) - diffConst = 0; - - Id pool; - if ( slaveEnable == 0 ) { - pool = shell_->doCreate( "Pool", pa, tail, 1 ); - } else if ( slaveEnable & 4 ) { - pool = shell_->doCreate( "BufPool", pa, tail, 1 ); - } else { - pool = shell_->doCreate( "Pool", pa, tail, 1 ); - /* - cout << "ReadKkit::buildPool: Unknown slave_enable flag '" << - slaveEnable << "' on " << clean << "\n"; - */ - poolFlags_[pool] = slaveEnable; - } - assert( pool != Id() ); - // skip the 10 chars of "/kinetics/" - poolIds_[ clean.substr( 10 ) ] = pool; - - Field< double >::set( pool, "nInit", nInit ); - Field< double >::set( pool, "diffConst", diffConst ); - // SetGet1< double >::set( pool, "setVolume", vol ); - separateVols( pool, vol ); - poolVols_[pool] = vol; - - Id info = buildInfo( pool, poolMap_, args ); - /* - cout << setw( 20 ) << head << setw( 15 ) << tail << " " << - setw( 12 ) << nInit << " " << - vol << " " << diffConst << " " << - slaveEnable << endl; - */ - numPools_++; - return pool; +{ + string head; + string clean = cleanPath( args[2] ); + string tail = pathTail( clean, head ); + Id pa = shell_->doFind( head ).id; + assert( pa != Id() ); + + double nInit = atof( args[ poolMap_[ "nInit" ] ].c_str() ); + double vsf = atof( args[ poolMap_[ "vol" ] ].c_str() ); + /** + * vsf is vol scale factor, which is what GENESIS stores in 'vol' field + * n = vsf * conc( uM ) + * Also, n = ( conc (uM) / 1e6 ) * NA * vol + * so, vol = 1e6 * vsf / NA + */ + double vol = 1.0e3 * vsf / KKIT_NA; // Converts volscale to actual vol in m^3 + int slaveEnable = atoi( args[ poolMap_[ "slave_enable" ] ].c_str() ); + double diffConst = atof( args[ poolMap_[ "DiffConst" ] ].c_str() ); + + // I used -ve D as a flag to replace pool-specific D + // with the global value of D. Here we just ignore it. + if ( diffConst < 0 ) + diffConst = 0; + + Id pool; + if ( slaveEnable == 0 ) + { + pool = shell_->doCreate( "Pool", pa, tail, 1 ); + } + else if ( slaveEnable & 4 ) + { + pool = shell_->doCreate( "BufPool", pa, tail, 1 ); + } + else + { + pool = shell_->doCreate( "Pool", pa, tail, 1 ); + /* + cout << "ReadKkit::buildPool: Unknown slave_enable flag '" << + slaveEnable << "' on " << clean << "\n"; + */ + poolFlags_[pool] = slaveEnable; + } + assert( pool != Id() ); + // skip the 10 chars of "/kinetics/" + poolIds_[ clean.substr( 10 ) ] = pool; + + Field< double >::set( pool, "nInit", nInit ); + Field< double >::set( pool, "diffConst", diffConst ); + // SetGet1< double >::set( pool, "setVolume", vol ); + separateVols( pool, vol ); + poolVols_[pool] = vol; + + Id info = buildInfo( pool, poolMap_, args ); + /* + cout << setw( 20 ) << head << setw( 15 ) << tail << " " << + setw( 12 ) << nInit << " " << + vol << " " << diffConst << " " << + slaveEnable << endl; + */ + numPools_++; + return pool; } /** @@ -1078,68 +1136,76 @@ Id ReadKkit::buildPool( const vector< string >& args ) */ Id ReadKkit::findSumTotSrc( const string& src ) { - map< string, Id >::iterator i = poolIds_.find( src ); - if ( i != poolIds_.end() ) { - return i->second; - } - i = enzIds_.find( src ); - if ( i != enzIds_.end() ) { - string head; - string cplx = src + '/' + pathTail( src, head ) + "_cplx"; - i = poolIds_.find( cplx ); - if ( i != poolIds_.end() ) { - return i->second; - } - } - cout << "Error: ReadKkit::findSumTotSrc: Cannot find source pool '" << src << endl; - assert( 0 ); - return Id(); + map< string, Id >::iterator i = poolIds_.find( src ); + if ( i != poolIds_.end() ) + { + return i->second; + } + i = enzIds_.find( src ); + if ( i != enzIds_.end() ) + { + string head; + string cplx = src + '/' + pathTail( src, head ) + "_cplx"; + i = poolIds_.find( cplx ); + if ( i != poolIds_.end() ) + { + return i->second; + } + } + cout << "Error: ReadKkit::findSumTotSrc: Cannot find source pool '" << src << endl; + assert( 0 ); + return Id(); } void ReadKkit::buildSumTotal( const string& src, const string& dest ) { - map< string, Id >::iterator i = poolIds_.find( dest ); - assert( i != poolIds_.end() ); - Id destId = i->second; - - Id sumId; - // Check if the pool has not yet been converted to handle SumTots. - if ( destId.element()->cinfo()->name() == "Pool" ) { - sumId = shell_->doCreate( "Function", destId, "func", 1 ); - // Turn dest into a FuncPool. - destId.element()->zombieSwap( BufPool::initCinfo() ); - - ObjId ret = shell_->doAddMsg( "single", - ObjId( sumId, 0 ), "valueOut", - ObjId( destId, 0 ), "setN" ); - assert( ret != ObjId() ); - } else { - sumId = Neutral::child( destId.eref(), "func" ); - } - - if ( sumId == Id() ) { - cout << "Error: ReadKkit::buildSumTotal: could not make Function on '" - << dest << "'\n"; - return; - } - - Id srcId = findSumTotSrc( src ); - unsigned int numVars = Field< unsigned int >::get( sumId, "numVars" ); - ObjId xi( sumId.value() + 1, 0, numVars ); - Field< unsigned int >::set( sumId, "numVars", numVars + 1 ); - - ObjId ret = shell_->doAddMsg( "single", - ObjId( srcId, 0 ), "nOut", - xi, "input" ); - assert( ret != ObjId() ); - - - stringstream ss; - for ( unsigned int i = 0; i < numVars; ++i ) { - ss << "x" << i << "+"; - } - ss << "x" << numVars; - Field< string >::set( sumId, "expr", ss.str() ); + map::iterator i = poolIds_.find(dest); + assert( i != poolIds_.end() ); + Id destId = i->second; + + Id sumId; + // Check if the pool has not yet been converted to handle SumTots. + if ( destId.element()->cinfo()->name() == "Pool" ) + { + sumId = shell_->doCreate( "Function", destId, "func", 1 ); + Field< bool >::set( sumId, "allowUnknownVariable", false ); + + // Turn dest into a FuncPool. + destId.element()->zombieSwap( BufPool::initCinfo() ); + + ObjId ret = shell_->doAddMsg( "single", + ObjId( sumId, 0 ), "valueOut", + ObjId( destId, 0 ), "setN" ); + assert( ret != ObjId() ); + } + else + { + sumId = Neutral::child( destId.eref(), "func" ); + } + + if ( sumId == Id() ) + { + cout << "Error: ReadKkit::buildSumTotal: could not make Function on '" + << dest << "'\n"; + return; + } + + Id srcId = findSumTotSrc( src ); + unsigned int numVars = Field< unsigned int >::get( sumId, "numVars" ); + ObjId xi(sumId.value()+1, 0, numVars ); + Field::set( sumId, "numVars", numVars+1); + + ObjId ret = shell_->doAddMsg( "single", + ObjId( srcId, 0 ), "nOut", + xi, "input" ); + assert( ret != ObjId() ); + + + stringstream ss; + for ( unsigned int i = 0; i < numVars; ++i ) + ss << "x" << i << "+"; + ss << "x" << numVars; + Field< string >::set( sumId, "expr", ss.str() ); } /** @@ -1147,34 +1213,34 @@ void ReadKkit::buildSumTotal( const string& src, const string& dest ) */ Id ReadKkit::buildStim( const vector< string >& args ) { - string head; - string clean = cleanPath( args[2] ); - string tail = pathTail( clean, head ); - Id pa = shell_->doFind( head ).id; - assert( pa != Id() ); - - double level1 = atof( args[ stimMap_[ "firstLevel" ] ].c_str() ); - double width1 = atof( args[ stimMap_[ "firstWidth" ] ].c_str() ); - double delay1 = atof( args[ stimMap_[ "firstDelay" ] ].c_str() ); - double level2 = atof( args[ stimMap_[ "secondLevel" ] ].c_str() ); - double width2 = atof( args[ stimMap_[ "secondWidth" ] ].c_str() ); - double delay2 = atof( args[ stimMap_[ "secondLevel" ] ].c_str() ); - double baselevel = atof( args[ stimMap_[ "baseLevel" ] ].c_str() ); - - Id stim = shell_->doCreate( "PulseGen", pa, tail, 1 ); - assert( stim != Id() ); - string stimPath = clean.substr( 10 ); - stimIds_[ stimPath ] = stim; - Field< double >::set( stim, "firstLevel", level1 ); - Field< double >::set( stim, "firstWidth", width1 ); - Field< double >::set( stim, "firstDelay", delay1 ); - Field< double >::set( stim, "secondLevel", level2 ); - Field< double >::set( stim, "secondWidth", width2 ); - Field< double >::set( stim, "secondDelay", delay2 ); - Field< double >::set( stim, "baseLevel", baselevel ); - - numStim_++; - return stim; + string head; + string clean = cleanPath( args[2] ); + string tail = pathTail( clean, head ); + Id pa = shell_->doFind( head ).id; + assert( pa != Id() ); + + double level1 = atof( args[ stimMap_[ "firstLevel" ] ].c_str() ); + double width1 = atof( args[ stimMap_[ "firstWidth" ] ].c_str() ); + double delay1 = atof( args[ stimMap_[ "firstDelay" ] ].c_str() ); + double level2 = atof( args[ stimMap_[ "secondLevel" ] ].c_str() ); + double width2 = atof( args[ stimMap_[ "secondWidth" ] ].c_str() ); + double delay2 = atof( args[ stimMap_[ "secondLevel" ] ].c_str() ); + double baselevel = atof( args[ stimMap_[ "baseLevel" ] ].c_str() ); + + Id stim = shell_->doCreate( "PulseGen", pa, tail, 1 ); + assert( stim != Id() ); + string stimPath = clean.substr( 10 ); + stimIds_[ stimPath ] = stim; + Field< double >::set( stim, "firstLevel", level1 ); + Field< double >::set( stim, "firstWidth", width1 ); + Field< double >::set( stim, "firstDelay", delay1 ); + Field< double >::set( stim, "secondLevel", level2 ); + Field< double >::set( stim, "secondWidth", width2 ); + Field< double >::set( stim, "secondDelay", delay2 ); + Field< double >::set( stim, "baseLevel", baselevel ); + + numStim_++; + return stim; } /** @@ -1182,320 +1248,365 @@ Id ReadKkit::buildStim( const vector< string >& args ) */ Id ReadKkit::buildChan( const vector< string >& args ) { - string head; - string clean = cleanPath( args[2] ); - string tail = pathTail( clean, head ); - Id pa = shell_->doFind( head ).id; - assert( pa != Id() ); - - // cout << "Warning: Kchan not yet supported in MOOSE, creating dummy:\n" << " " << clean << "\n"; - // - double permeability = atof( args[ chanMap_["perm"] ].c_str() ); - Id chan = shell_->doCreate( "ConcChan", pa, tail, 1 ); - Field< double >::set( chan, "permeability", permeability ); - assert( chan != Id() ); - string chanPath = clean.substr( 10 ); - chanIds_[ chanPath ] = chan; - Id info = buildInfo( chan, chanMap_, args ); - return chan; + string head; + string clean = cleanPath( args[2] ); + string tail = pathTail( clean, head ); + Id pa = shell_->doFind( head ).id; + assert( pa != Id() ); + + // cout << "Warning: Kchan not yet supported in MOOSE, creating dummy:\n" << " " << clean << "\n"; + // + double permeability = atof( args[ chanMap_["perm"] ].c_str() ); + Id chan = shell_->doCreate( "ConcChan", pa, tail, 1 ); + // Convert from perm in uM in GENESIS, to mM for MOOSE. + Field< double >::set( chan, "permeability", permeability *1000.0 ); + assert( chan != Id() ); + string chanPath = clean.substr( 10 ); + chanIds_[ chanPath ] = chan; + Id info = buildInfo( chan, chanMap_, args ); + return chan; } Id ReadKkit::buildGeometry( const vector< string >& args ) { - Id geometry; - numOthers_++; - return geometry; + Id geometry; + numOthers_++; + return geometry; } Id ReadKkit::buildGraph( const vector< string >& args ) { - string head; - string tail = pathTail( cleanPath( args[2] ), head ); - - Id pa = shell_->doFind( head ).id; - assert( pa != Id() ); - Id graph = shell_->doCreate( "Neutral", pa, tail, 1 ); - assert( graph != Id() ); - numOthers_++; - return graph; + string head; + string tail = pathTail( cleanPath( args[2] ), head ); + + Id pa = shell_->doFind( head ).id; + assert( pa != Id() ); + Id graph = shell_->doCreate( "Neutral", pa, tail, 1 ); + assert( graph != Id() ); + numOthers_++; + return graph; } Id ReadKkit::buildPlot( const vector< string >& args ) { - string head; - string tail = pathTail( cleanPath( args[2] ), head ); // Name of plot - string temp; - string graph = pathTail( head, temp ); // Name of graph + string head; + string tail = pathTail( cleanPath( args[2] ), head ); // Name of plot + string temp; + string graph = pathTail( head, temp ); // Name of graph - Id pa = shell_->doFind( head ).id; - assert( pa != Id() ); + Id pa = shell_->doFind( head ).id; + assert( pa != Id() ); - Id plot = shell_->doCreate( "Table2", pa, tail, 1 ); - assert( plot != Id() ); + Id plot = shell_->doCreate( "Table2", pa, tail, 1 ); + assert( plot != Id() ); - temp = graph + "/" + tail; - plotIds_[ temp ] = plot; + temp = graph + "/" + tail; + plotIds_[ temp ] = plot; - numPlot_++; - return plot; + numPlot_++; + return plot; } enum GenesisTableModes {TAB_IO, TAB_LOOP, TAB_ONCE, TAB_BUF, TAB_SPIKE, - TAB_FIELDS, TAB_DELAY }; + TAB_FIELDS, TAB_DELAY + }; Id ReadKkit::buildTable( const vector< string >& args ) { - string head; - string clean = cleanPath( args[2] ); - string tail = pathTail( clean, head ); // Name of xtab - - Id pa = shell_->doFind( head ).id; - assert( pa != Id() ); - Id tab; - - int mode = atoi( args[ tableMap_[ "step_mode" ] ].c_str() ); - if ( mode == TAB_IO ) { - } else if ( mode == TAB_LOOP || mode == TAB_ONCE ) { - tab = shell_->doCreate( "StimulusTable", pa, tail, 1 ); - assert( tab != Id() ); - double stepSize = atof( args[ tableMap_[ "stepsize" ] ].c_str() ); - Field< double >::set( tab, "stepSize", stepSize ); - if ( mode == TAB_LOOP ) - Field< bool >::set( tab, "doLoop", 1 ); - double input = atof( args[ tableMap_[ "input" ] ].c_str() ); - Field< double >::set( tab, "startTime", -input ); - // The other StimulusTable parameters will have to wait till the - // loadTab is invoked. - } - - - string temp = clean.substr( 10 ); - tabIds_[ temp ] = tab; - - Id info = buildInfo( tab, tableMap_, args ); - - return tab; + string head; + string clean = cleanPath( args[2] ); + string tail = pathTail( clean, head ); // Name of xtab + + Id pa = shell_->doFind( head ).id; + assert( pa != Id() ); + Id tab; + + int mode = atoi( args[ tableMap_[ "step_mode" ] ].c_str() ); + if ( mode == TAB_IO ) + { + } + else if ( mode == TAB_LOOP || mode == TAB_ONCE ) + { + tab = shell_->doCreate( "StimulusTable", pa, tail, 1 ); + assert( tab != Id() ); + double stepSize = atof( args[ tableMap_[ "stepsize" ] ].c_str() ); + Field< double >::set( tab, "stepSize", stepSize ); + if ( mode == TAB_LOOP ) + Field< bool >::set( tab, "doLoop", 1 ); + double input = atof( args[ tableMap_[ "input" ] ].c_str() ); + Field< double >::set( tab, "startTime", -input ); + // The other StimulusTable parameters will have to wait till the + // loadTab is invoked. + } + + + string temp = clean.substr( 10 ); + tabIds_[ temp ] = tab; + + Id info = buildInfo( tab, tableMap_, args ); + + return tab; } unsigned int ReadKkit::loadTab( const vector< string >& args ) { - Id tab; - unsigned int start = 0; - if ( args[1].substr( 0, 5 ) == "-cont" || args[1] == "-end" ) { - start = 2; - tab = lastTab_; - assert( tab != Id() ); - } else { - tabEntries_.resize( 0 ); - start = 7; - assert( args.size() >= start ); - lastTab_ = tab = Id( basePath_ + args[1] ); - assert( tab != Id() ); - // int calc_mode = atoi( args[3].c_str() ); - // int xdivs = atoi( args[4].c_str() ); - if ( tab.element()->cinfo()->isA( "StimulusTable" ) ) { - double xmin = atof( args[5].c_str() ); - double xmax = atof( args[6].c_str() ); - double start = Field< double >::get( tab, "startTime" ); - start += xmin; - Field< double >::set( tab, "startTime", start ); - Field< double >::set( tab, "stopTime", xmax ); - } - } - - for ( unsigned int i = start; i < args.size(); ++i ) { - tabEntries_.push_back( atof( args[i].c_str() ) ); - } - Field< vector< double > >::set( tab, "vector", tabEntries_ ); - - // cout << "Loading table for " << args[0] << "," << args[1] << "," << clean << endl; - - if ( args[1] == "-end" ) - lastTab_ = Id(); - - return 0; + Id tab; + unsigned int start = 0; + if ( args[1].substr( 0, 5 ) == "-cont" || args[1] == "-end" ) + { + start = 2; + tab = lastTab_; + assert( tab != Id() ); + } + else + { + tabEntries_.resize( 0 ); + start = 7; + assert( args.size() >= start ); + lastTab_ = tab = Id( basePath_ + args[1] ); + assert( tab != Id() ); + // int calc_mode = atoi( args[3].c_str() ); + // int xdivs = atoi( args[4].c_str() ); + if ( tab.element()->cinfo()->isA( "StimulusTable" ) ) + { + double xmin = atof( args[5].c_str() ); + double xmax = atof( args[6].c_str() ); + double start = Field< double >::get( tab, "startTime" ); + start += xmin; + Field< double >::set( tab, "startTime", start ); + Field< double >::set( tab, "stopTime", xmax ); + } + } + + for ( unsigned int i = start; i < args.size(); ++i ) + { + tabEntries_.push_back( atof( args[i].c_str() ) ); + } + Field< vector< double > >::set( tab, "vector", tabEntries_ ); + + // cout << "Loading table for " << args[0] << "," << args[1] << "," << clean << endl; + + if ( args[1] == "-end" ) + lastTab_ = Id(); + + return 0; } void ReadKkit::innerAddMsg( - const string& src, const map< string, Id >& m1, const string& srcMsg, - const string& dest, const map< string, Id >& m2, const string& destMsg, - bool isBackward ) + const string& src, const map< string, Id >& m1, const string& srcMsg, + const string& dest, const map< string, Id >& m2, const string& destMsg, + bool isBackward ) { - map< string, Id >::const_iterator i = m1.find( src ); - assert( i != m1.end() ); - Id srcId = i->second; - - i = m2.find( dest ); - assert( i != m2.end() ); - Id destId = i->second; - - // dest pool is substrate of src reac - if ( isBackward ) { - ObjId ret = shell_->doAddMsg( "AllToOne", - ObjId( srcId, 0 ), srcMsg, - ObjId( destId, 0 ), destMsg ); - assert( ret != ObjId() ); - } else { - ObjId ret = shell_->doAddMsg( "OneToAll", - ObjId( srcId, 0 ), srcMsg, - ObjId( destId, 0 ), destMsg ); - assert( ret != ObjId() ); - } + map< string, Id >::const_iterator i = m1.find( src ); + assert( i != m1.end() ); + Id srcId = i->second; + + i = m2.find( dest ); + assert( i != m2.end() ); + Id destId = i->second; + + // dest pool is substrate of src reac + if ( isBackward ) + { + ObjId ret = shell_->doAddMsg( "AllToOne", + ObjId( srcId, 0 ), srcMsg, + ObjId( destId, 0 ), destMsg ); + assert( ret != ObjId() ); + } + else + { + ObjId ret = shell_->doAddMsg( "OneToAll", + ObjId( srcId, 0 ), srcMsg, + ObjId( destId, 0 ), destMsg ); + assert( ret != ObjId() ); + } } void ReadKkit::addmsg( const vector< string >& args) { - string src = cleanPath( args[1] ).substr( 10 ); - string dest = cleanPath( args[2] ).substr( 10 ); - - if ( args[3] == "REAC" ) { - if ( args[4] == "A" && args[5] == "B" ) { - if ( chanIds_.find( src ) != chanIds_.end() ) - innerAddMsg( src, chanIds_, "in", dest, poolIds_, "reac"); - else - innerAddMsg( src, reacIds_, "sub", dest, poolIds_, "reac"); - } - else if ( args[4] == "B" && args[5] == "A" ) { - if ( chanIds_.find( src ) != chanIds_.end() ) - innerAddMsg( src, chanIds_, "out", dest, poolIds_, "reac"); - else - // dest pool is product of src reac - innerAddMsg( src, reacIds_, "prd", dest, poolIds_, "reac"); - } - else if ( args[4] == "sA" && args[5] == "B" ) { - // Msg from enzyme to substrate. - if ( mmEnzIds_.find( src ) == mmEnzIds_.end() ) - innerAddMsg( src, enzIds_, "sub", dest, poolIds_, "reac" ); - else - innerAddMsg( src, mmEnzIds_, "sub", dest, poolIds_, "reac" ); - } - } - else if ( args[3] == "ENZYME" ) { // Msg from enz pool to enz site - if ( mmEnzIds_.find( dest ) == mmEnzIds_.end() ) - innerAddMsg( dest, enzIds_, "enz", src, poolIds_, "reac" ); - else - innerAddMsg( src, poolIds_, "nOut", dest, mmEnzIds_, "enzDest", 1); - // innerAddMsg( dest, mmEnzIds_, "enz", src, poolIds_, "nOut", 1); - /* - if ( mmEnzIds_.find( dest ) == mmEnzIds_.end() ) - innerAddMsg( src, poolIds_, "reac", dest, enzIds_, "enz" ); - else - innerAddMsg( src, poolIds_, "nOut", dest, mmEnzIds_, "enz" ); - */ - } - else if ( args[3] == "MM_PRD" ) { // Msg from enz to Prd pool - if ( mmEnzIds_.find( src ) == mmEnzIds_.end() ) - innerAddMsg( src, enzIds_, "prd", dest, poolIds_, "reac" ); - else - innerAddMsg( src, mmEnzIds_, "prd", dest, poolIds_, "reac" ); - } - else if ( args[3] == "NUMCHAN" ) { // Msg from chan pool to concchan - if ( chanIds_.find( dest ) != chanIds_.end() ) - innerAddMsg( src, poolIds_, "nOut", dest, chanIds_, "setNumChan"); - } - else if ( args[3] == "PLOT" ) { // Time-course output for pool - string head; - string temp; - dest = pathTail( cleanPath( args[2] ), head ); - string graph = pathTail( head, temp ); - temp = graph + "/" + dest; - map< string, Id >::const_iterator i = plotIds_.find( temp ); - assert( i != plotIds_.end() ); - Id plot = i->second; - - i = poolIds_.find( src ); - Id pool; - if ( i == poolIds_.end() ) { - i = enzIds_.find( src ); // might be plotting an enzCplx. - if ( i == enzIds_.end() ) { - cout << "Error: ReadKkit: Unable to find src for plot: " << - src << ", " << dest << endl; - assert( 0 ); - return; - } - vector< Id > enzcplx; - i->second.element()->getNeighbors( enzcplx, - i->second.element()->cinfo()->findFinfo( "cplxOut" ) ); - assert( enzcplx.size() == 1 ); - pool = enzcplx[0]; - } else { - pool = i->second; - } - - if ( args[4] == "Co" || args[4] == "CoComplex" ) { - ObjId ret = shell_->doAddMsg( "Single", - plot, "requestOut", pool, "getConc" ); - assert( ret != ObjId() ); - } else if ( args[4] == "n" || args[4] == "nComplex") { - ObjId ret = shell_->doAddMsg( "Single", - plot, "requestOut", pool, "getN" ); - assert( ret != ObjId() ); - } else { - cout << "Unknown PLOT msg field '" << args[4] << "'\n"; - } - } - else if ( args[3] == "SUMTOTAL" ) { // Summation function. - buildSumTotal( src, dest ); - } - else if ( args[3] == "SLAVE" ) { // Summation function. - if ( args[4] == "output" ) { - setupSlaveMsg( src, dest ); - } - } + string src = cleanPath( args[1] ).substr( 10 ); + string dest = cleanPath( args[2] ).substr( 10 ); + + if ( args[3] == "REAC" ) + { + if ( args[4] == "A" && args[5] == "B" ) + { + if ( chanIds_.find( src ) != chanIds_.end() ) + innerAddMsg( src, chanIds_, "in", dest, poolIds_, "reac"); + else + innerAddMsg( src, reacIds_, "sub", dest, poolIds_, "reac"); + } + else if ( args[4] == "B" && args[5] == "A" ) + { + if ( chanIds_.find( src ) != chanIds_.end() ) + innerAddMsg( src, chanIds_, "out", dest, poolIds_, "reac"); + else + // dest pool is product of src reac + innerAddMsg( src, reacIds_, "prd", dest, poolIds_, "reac"); + } + else if ( args[4] == "sA" && args[5] == "B" ) + { + // Msg from enzyme to substrate. + if ( mmEnzIds_.find( src ) == mmEnzIds_.end() ) + innerAddMsg( src, enzIds_, "sub", dest, poolIds_, "reac" ); + else + innerAddMsg( src, mmEnzIds_, "sub", dest, poolIds_, "reac" ); + } + } + else if ( args[3] == "ENZYME" ) // Msg from enz pool to enz site + { + if ( mmEnzIds_.find( dest ) == mmEnzIds_.end() ) + innerAddMsg( dest, enzIds_, "enz", src, poolIds_, "reac" ); + else + innerAddMsg( src, poolIds_, "nOut", dest, mmEnzIds_, "enzDest", 1); + // innerAddMsg( dest, mmEnzIds_, "enz", src, poolIds_, "nOut", 1); + /* + if ( mmEnzIds_.find( dest ) == mmEnzIds_.end() ) + innerAddMsg( src, poolIds_, "reac", dest, enzIds_, "enz" ); + else + innerAddMsg( src, poolIds_, "nOut", dest, mmEnzIds_, "enz" ); + */ + } + else if ( args[3] == "MM_PRD" ) // Msg from enz to Prd pool + { + if ( mmEnzIds_.find( src ) == mmEnzIds_.end() ) + innerAddMsg( src, enzIds_, "prd", dest, poolIds_, "reac" ); + else + innerAddMsg( src, mmEnzIds_, "prd", dest, poolIds_, "reac" ); + } + else if ( args[3] == "NUMCHAN" ) // Msg from chan pool to concchan + { + if ( chanIds_.find( dest ) != chanIds_.end() ) + innerAddMsg( src, poolIds_, "nOut", dest, chanIds_, "setNumChan"); + } + else if ( args[3] == "PLOT" ) // Time-course output for pool + { + string head; + string temp; + dest = pathTail( cleanPath( args[2] ), head ); + string graph = pathTail( head, temp ); + temp = graph + "/" + dest; + map< string, Id >::const_iterator i = plotIds_.find( temp ); + assert( i != plotIds_.end() ); + Id plot = i->second; + + i = poolIds_.find( src ); + Id pool; + if ( i == poolIds_.end() ) + { + i = enzIds_.find( src ); // might be plotting an enzCplx. + if ( i == enzIds_.end() ) + { + cout << "Error: ReadKkit: Unable to find src for plot: " << + src << ", " << dest << endl; + assert( 0 ); + return; + } + vector< Id > enzcplx; + i->second.element()->getNeighbors( enzcplx, + i->second.element()->cinfo()->findFinfo( "cplxOut" ) ); + assert( enzcplx.size() == 1 ); + pool = enzcplx[0]; + } + else + { + pool = i->second; + } + + if ( args[4] == "Co" || args[4] == "CoComplex" ) + { + ObjId ret = shell_->doAddMsg( "Single", + plot, "requestOut", pool, "getConc" ); + assert( ret != ObjId() ); + } + else if ( args[4] == "n" || args[4] == "nComplex") + { + ObjId ret = shell_->doAddMsg( "Single", + plot, "requestOut", pool, "getN" ); + assert( ret != ObjId() ); + } + else + { + cout << "Unknown PLOT msg field '" << args[4] << "'\n"; + } + } + else if ( args[3] == "SUMTOTAL" ) // Summation function. + { + buildSumTotal( src, dest ); + } + else if ( args[3] == "SLAVE" ) // Summation function. + { + if ( args[4] == "output" ) + { + setupSlaveMsg( src, dest ); + } + } } void ReadKkit::setupSlaveMsg( const string& src, const string& dest ) { - // Convert the pool to a BufPool, if it isn't one already - Id destId( basePath_ + "/kinetics/" + dest ); - assert( destId != Id() ); - - if( !destId.element()->cinfo()->isA( "BufPool" )) { - destId.element()->zombieSwap( BufPool::initCinfo() ); - } - - map< string, Id >* nameMap; - // Check if the src is a table or a stim - Id srcId( basePath_ + "/kinetics/" + src ); - assert( srcId != Id() ); - string output = "output"; - if ( srcId.element()->cinfo()->isA( "TableBase" ) ) { - nameMap = &tabIds_; - } else if ( srcId.element()->cinfo()->isA( "PulseGen" ) ) { - nameMap = &stimIds_; - output = "output"; - } else { - cout << "Error: Unknown source for SLAVE msg: (" << src << - ", " << dest << ")\n"; - return; - } - - // NSLAVE is 1, CONCSLAVE is 2. - map< Id, int >::iterator i = poolFlags_.find( destId ); - if ( i == poolFlags_.end() || !( i->second & 2 ) ) { - innerAddMsg( src, *nameMap, output, dest, poolIds_, - "setNInit" ); - } else { - innerAddMsg( src, *nameMap, output, dest, poolIds_, - "setConcInit" ); - - double CONCSCALE = 0.001; - // Rescale from uM to millimolar. - if ( nameMap == &tabIds_ ) { - SetGet2< double, double >::set( srcId, "linearTransform", - CONCSCALE, 0 ); - } else if ( nameMap == &stimIds_ ) { - double x = Field< double >::get( srcId, "baseLevel" ); - Field< double >::set( srcId, "baseLevel", x * CONCSCALE ); - x = Field< double >::get( srcId, "firstLevel" ); - Field< double >::set( srcId, "firstLevel", x * CONCSCALE ); - x = Field< double >::get( srcId, "secondLevel" ); - Field< double >::set( srcId, "secondLevel", x * CONCSCALE ); - } - } - // cout << "Added slave msg from " << src << " to " << dest << endl; + // Convert the pool to a BufPool, if it isn't one already + Id destId( basePath_ + "/kinetics/" + dest ); + assert( destId != Id() ); + + if( !destId.element()->cinfo()->isA( "BufPool" )) + { + destId.element()->zombieSwap( BufPool::initCinfo() ); + } + + map< string, Id >* nameMap; + // Check if the src is a table or a stim + Id srcId( basePath_ + "/kinetics/" + src ); + assert( srcId != Id() ); + string output = "output"; + if ( srcId.element()->cinfo()->isA( "TableBase" ) ) + { + nameMap = &tabIds_; + } + else if ( srcId.element()->cinfo()->isA( "PulseGen" ) ) + { + nameMap = &stimIds_; + output = "output"; + } + else + { + cout << "Error: Unknown source for SLAVE msg: (" << src << + ", " << dest << ")\n"; + return; + } + + // NSLAVE is 1, CONCSLAVE is 2. + map< Id, int >::iterator i = poolFlags_.find( destId ); + if ( i == poolFlags_.end() || !( i->second & 2 ) ) + { + innerAddMsg( src, *nameMap, output, dest, poolIds_, + "setNInit" ); + } + else + { + innerAddMsg( src, *nameMap, output, dest, poolIds_, + "setConcInit" ); + + double CONCSCALE = 0.001; + // Rescale from uM to millimolar. + if ( nameMap == &tabIds_ ) + { + SetGet2< double, double >::set( srcId, "linearTransform", + CONCSCALE, 0 ); + } + else if ( nameMap == &stimIds_ ) + { + double x = Field< double >::get( srcId, "baseLevel" ); + Field< double >::set( srcId, "baseLevel", x * CONCSCALE ); + x = Field< double >::get( srcId, "firstLevel" ); + Field< double >::set( srcId, "firstLevel", x * CONCSCALE ); + x = Field< double >::get( srcId, "secondLevel" ); + Field< double >::set( srcId, "secondLevel", x * CONCSCALE ); + } + } + // cout << "Added slave msg from " << src << " to " << dest << endl; } // We have a slight problem because MOOSE has a more precise value for @@ -1507,80 +1618,83 @@ void ReadKkit::setupSlaveMsg( const string& src, const string& dest ) // the model has been created, once we know the order of each reac. void ReadKkit::convertParametersToConcUnits() { - convertPoolAmountToConcUnits(); - convertReacRatesToConcUnits(); - convertMMenzRatesToConcUnits(); - convertEnzRatesToConcUnits(); + convertPoolAmountToConcUnits(); + convertReacRatesToConcUnits(); + convertMMenzRatesToConcUnits(); + convertEnzRatesToConcUnits(); } void ReadKkit::convertPoolAmountToConcUnits() { - const double NA_RATIO = KKIT_NA / NA; - for ( map< string, Id >::iterator i = poolIds_.begin(); - i != poolIds_.end(); ++i ) { - Id pool = i->second; - double nInit = Field< double >::get( pool, "nInit" ); - double n = Field< double >::get( pool, "n" ); - - nInit /= NA_RATIO; - n /= NA_RATIO; - Field< double >::set( pool, "nInit", nInit ); - Field< double >::set( pool, "n", n ); - } + const double NA_RATIO = KKIT_NA / NA; + for ( map< string, Id >::iterator i = poolIds_.begin(); + i != poolIds_.end(); ++i ) + { + Id pool = i->second; + double nInit = Field< double >::get( pool, "nInit" ); + double n = Field< double >::get( pool, "n" ); + + nInit /= NA_RATIO; + n /= NA_RATIO; + Field< double >::set( pool, "nInit", nInit ); + Field< double >::set( pool, "n", n ); + } } void ReadKkit::convertReacRatesToConcUnits() { - const double NA_RATIO = KKIT_NA / NA; - for ( map< string, Id >::iterator i = reacIds_.begin(); - i != reacIds_.end(); ++i ) { - Id reac = i->second; - double kf = Field< double >::get( reac, "Kf" ); - double kb = Field< double >::get( reac, "Kb" ); - // Note funny access here, using the Conc unit term (Kf) to get the - // num unit term (kf). When reading, there are no volumes so the - // Kf gets assigned to what was the kf value from kkit. - - // At this point the kf and kb are off because the - // NA for kkit is not accurate. So we correct for this. - unsigned int numSub = - Field< unsigned int >::get( reac, "numSubstrates" ); - unsigned int numPrd = - Field< unsigned int >::get( reac, "numProducts" ); - - if ( numSub > 1 ) - kf *= pow( NA_RATIO, numSub - 1.0 ); - - if ( numPrd > 1 ) - kb *= pow( NA_RATIO, numPrd - 1.0 ); - - // Now we have the correct numKf and numKb, plug them into the - // reac, and let it internally fix up the Kf and Kb. - Field< double >::set( reac, "numKf", kf ); - Field< double >::set( reac, "numKb", kb ); - } + const double NA_RATIO = KKIT_NA / NA; + for ( map< string, Id >::iterator i = reacIds_.begin(); + i != reacIds_.end(); ++i ) + { + Id reac = i->second; + double kf = Field< double >::get( reac, "Kf" ); + double kb = Field< double >::get( reac, "Kb" ); + // Note funny access here, using the Conc unit term (Kf) to get the + // num unit term (kf). When reading, there are no volumes so the + // Kf gets assigned to what was the kf value from kkit. + + // At this point the kf and kb are off because the + // NA for kkit is not accurate. So we correct for this. + unsigned int numSub = + Field< unsigned int >::get( reac, "numSubstrates" ); + unsigned int numPrd = + Field< unsigned int >::get( reac, "numProducts" ); + + if ( numSub > 1 ) + kf *= pow( NA_RATIO, numSub - 1.0 ); + + if ( numPrd > 1 ) + kb *= pow( NA_RATIO, numPrd - 1.0 ); + + // Now we have the correct numKf and numKb, plug them into the + // reac, and let it internally fix up the Kf and Kb. + Field< double >::set( reac, "numKf", kf ); + Field< double >::set( reac, "numKb", kb ); + } } void ReadKkit::convertMMenzRatesToConcUnits() { - const double NA_RATIO = KKIT_NA / NA; - for ( map< string, Id >::iterator i = mmEnzIds_.begin(); - i != mmEnzIds_.end(); ++i ) { - Id enz = i->second; - // This was set in the original # units. - double numKm = Field< double >::get( enz, "Km" ); - // At this point the numKm is inaaccurate because the - // NA for kkit is not accurate. So we correct for this. - double numSub = - Field< unsigned int >::get( enz, "numSubstrates" ); - // Note that we always have the enz itself as a substrate term. - if ( numSub > 0 ) - numKm *= pow( NA_RATIO, -numSub ); - - // Now we have the correct numKm, plug it into the MMenz, and - // let it internally fix up the Km - Field< double >::set( enz, "numKm", numKm ); - } + const double NA_RATIO = KKIT_NA / NA; + for ( map< string, Id >::iterator i = mmEnzIds_.begin(); + i != mmEnzIds_.end(); ++i ) + { + Id enz = i->second; + // This was set in the original # units. + double numKm = Field< double >::get( enz, "Km" ); + // At this point the numKm is inaaccurate because the + // NA for kkit is not accurate. So we correct for this. + double numSub = + Field< unsigned int >::get( enz, "numSubstrates" ); + // Note that we always have the enz itself as a substrate term. + if ( numSub > 0 ) + numKm *= pow( NA_RATIO, -numSub ); + + // Now we have the correct numKm, plug it into the MMenz, and + // let it internally fix up the Km + Field< double >::set( enz, "numKm", numKm ); + } } // we take k2 and k3 as correct, since those are just time^-1. @@ -1589,18 +1703,19 @@ void ReadKkit::convertMMenzRatesToConcUnits() // of the NA and KKIT_NA discrepancy. void ReadKkit::convertEnzRatesToConcUnits() { - const double NA_RATIO = KKIT_NA / NA; - for ( map< string, Id >::iterator i = enzIds_.begin(); - i != enzIds_.end(); ++i ) { - Id enz = i->second; - double k1 = Field< double >::get( enz, "k1" ); - // At this point the k1 is inaaccurate because the - // NA for kkit is not accurate. So we correct for this. - double numSub = - Field< unsigned int >::get( enz, "numSubstrates" ); - // Note that we always have the enz itself as a substrate term. - if ( numSub > 0 ) - k1 *= pow( NA_RATIO, numSub ); - Field< double >::set( enz, "k1", k1 ); - } + const double NA_RATIO = KKIT_NA / NA; + for ( map< string, Id >::iterator i = enzIds_.begin(); + i != enzIds_.end(); ++i ) + { + Id enz = i->second; + double k1 = Field< double >::get( enz, "k1" ); + // At this point the k1 is inaaccurate because the + // NA for kkit is not accurate. So we correct for this. + double numSub = + Field< unsigned int >::get( enz, "numSubstrates" ); + // Note that we always have the enz itself as a substrate term. + if ( numSub > 0 ) + k1 *= pow( NA_RATIO, numSub ); + Field< double >::set( enz, "k1", k1 ); + } } diff --git a/kinetics/ReadKkit.h b/kinetics/ReadKkit.h index 1dae27bf..483714e3 100644 --- a/kinetics/ReadKkit.h +++ b/kinetics/ReadKkit.h @@ -27,232 +27,233 @@ */ class ReadKkit { - public: - enum ParseMode { - DATA, - INIT, - COMMENT, - LINE_CONTINUE - }; - - ReadKkit(); - - ////////////////////////////////////////////////////////////////// - // Field assignment stuff - ////////////////////////////////////////////////////////////////// - double getMaxTime() const; - double getPlotDt() const; - double getDefaultVol() const; - string getBasePath() const; - unsigned int getVersion() const; - bool getMoveOntoCompartment() const; - void setMoveOntoCompartment( bool v ); - - ////////////////////////////////////////////////////////////////// - // Undump operations - ////////////////////////////////////////////////////////////////// - - void innerRead( ifstream& fin ); - ParseMode readInit( const string& line ); - Id read( const string& filename, const string& cellname, - Id parent, const string& solverClass = "Stoich" ); - void readData( const string& line ); - void undump( const vector< string >& args ); - - /** - * This function sets up the kkit model for a run using the GSL, - * which means numerical integration using the GSL, all the plots - * specified by the kkit file, and the timestep for plots as - * specified by the kkit file. - */ - // void setupGslRun(); - - void run(); - void dumpPlots( const string& filename ); - - ////////////////////////////////////////////////////////////////// - // Building up the model - ////////////////////////////////////////////////////////////////// - Id buildCompartment( const vector< string >& args ); - Id buildPool( const vector< string >& args ); - Id buildReac( const vector< string >& args ); - Id buildEnz( const vector< string >& args ); - Id buildPlot( const vector< string >& args ); - Id buildTable( const vector< string >& args ); - unsigned int loadTab( const vector< string >& args ); - Id buildGroup( const vector< string >& args ); - Id buildText( const vector< string >& args ); - Id buildGraph( const vector< string >& args ); - Id buildGeometry( const vector< string >& args ); - Id buildStim( const vector< string >& args ); - Id buildChan( const vector< string >& args ); - Id buildInfo( Id parent, map< string, int >& m, - const vector< string >& args ); - void buildSumTotal( const string& src, const string& dest ); - /** - * Finds the source pool for a SumTot. It also deals with cases where - * the source is an enz-substrate complex - */ - Id findSumTotSrc( const string& src ); - - ////////////////////////////////////////////////////////////////// - // Special ops in the model definition - ////////////////////////////////////////////////////////////////// - void addmsg( const vector< string >& args ); - void setupSlaveMsg( const string& src, const string& dest ); - void innerAddMsg( - const string& src, const map< string, Id >& m1, - const string& srcMsg, - const string& dest, const map< string, Id >& m2, - const string& destMsg, - bool isBackward = 0 ); - void call( const vector< string >& args ); - void objdump( const vector< string >& args ); - void textload( const vector< string >& args ); - void separateVols( Id pool, double vol ); - void assignPoolCompartments(); - - /** - * Goes through all Reacs and connects them up to each of the - * compartments in which one or more of their reactants resides. - * Thus, if any of these compartments changes volume, the Reac will - * be informed. - */ - void assignReacCompartments(); - void assignEnzCompartments(); - void assignMMenzCompartments(); - - /** - * We have a slight problem because MOOSE has a more precise value - * for NA than does kkit. Also, at the time the model is loaded, - * the volume relationships are unknown. So we need to fix up conc - * units of all pools reacs post-facto. - * Here we assume that the conc units from Kkit are - * meant to be OK, so they override the #/cell (lower case k) units. - * So we convert all the Kfs and Kbs in the entire system after - * the model has been created, once we know the order of each reac. - */ - void convertParametersToConcUnits(); - - /// Convert pool amounts. Initially given in n, but scaling issue. - void convertPoolAmountToConcUnits(); - - /// Convert Reac rates, initially in n units. - void convertReacRatesToConcUnits(); - - /** - * Convert MMEnz rates. Km should be in conc units. Actually rates - * stored as k1, k2, k3 in num units, so this has to be computed - * and then converted. - */ - void convertMMenzRatesToConcUnits(); - - /** - * Convert regular Enz rates. Binding step k1 has similar issues - * as reac rates. k2 and k3 are both in units of 1/time, so OK. - */ - void convertEnzRatesToConcUnits(); - - ////////////////////////////////////////////////////////////////// - // Utility functions - ////////////////////////////////////////////////////////////////// - - /** - * Splits up kkit path into head and tail portions, - * tail is returned. - * Note that this prepends the basePath to the head. - */ - string pathTail( const string& path, string& head ) const; - - /** - * Utility function. Cleans up path strings. In most cases, it - * replaces things with underscores. - * Replaces square braces with underscores. - * Replaces '*' with 'p' - * as it is usually there to indicate phosphorylation - * Replaces '-' with underscore - * Replaces '@' with underscore - * Replaces ' ' with underscore - */ - string cleanPath( const string& path ) const; - - private: - string basePath_; /// Base path into which entire kkit model will go - Id baseId_; /// Base Id onto which entire kkit model will go. - - double fastdt_; /// fast numerical timestep from kkit. - double simdt_; /// regular numerical timestep from kkit. - double controldt_; /// Timestep for updating control graphics - double plotdt_; /// Timestep for updating plots - double maxtime_; /// Simulation run time. - double transientTime_; /// Time to run model at fastdt - bool useVariableDt_; /// Use both fast and sim dts. - double defaultVol_; /// Default volume for new compartments. - unsigned int version_; /// KKit version. - unsigned int initdumpVersion_; /// Initdump too has a version. - /** - * Normally ReadKkit puts things on the same tree as the kkit tree. - * This flag tells the system to - * reorganize the tree so that each pool or reac or enz is on - * an appropriate compartment. Reacs are a bit arbitrary though, - * just go onto same compt as substrate. - * Defaults to false. - */ - bool moveOntoCompartment_; - - unsigned int numCompartments_; - unsigned int numPools_; - unsigned int numReacs_; - unsigned int numEnz_; - unsigned int numMMenz_; - unsigned int numPlot_; - unsigned int numStim_; - unsigned int numOthers_; - - unsigned int lineNum_; - - map< string, int > poolMap_; - map< string, int > reacMap_; - map< string, int > enzMap_; - map< string, int > groupMap_; - map< string, int > tableMap_; - map< string, int > stimMap_; - map< string, int > chanMap_; - map< string, Id > poolIds_; - map< string, Id > reacIds_; - map< string, Id > enzIds_; - map< string, Id > mmEnzIds_; - map< string, Id > plotIds_; - map< string, Id > tabIds_; - map< string, Id > stimIds_; - map< string, Id > chanIds_; - - /* - vector< Id > pools_; - /// This keeps track of all vols, since the pools no longer do. - vector< double > poolVols_; - */ - - /// This keeps track of unique volumes - vector< double > vols_; - - /// This keeps track of the last Table used in loadtab - Id lastTab_; - /// This holds the vector of array entries for loadtab - vector< double > tabEntries_; - - /// List of Ids in each unique volume. - vector< vector< Id > > volCategories_; - vector< Id > compartments_; - vector< pair< Id, Id > > enzCplxMols_; - - map< Id, int > poolFlags_; - - map< Id, double > poolVols_; // Need for enz complexes. - - Shell* shell_; - - static const double EPSILON; +public: + enum ParseMode + { + DATA, + INIT, + COMMENT, + LINE_CONTINUE + }; + + ReadKkit(); + + ////////////////////////////////////////////////////////////////// + // Field assignment stuff + ////////////////////////////////////////////////////////////////// + double getMaxTime() const; + double getPlotDt() const; + double getDefaultVol() const; + string getBasePath() const; + unsigned int getVersion() const; + bool getMoveOntoCompartment() const; + void setMoveOntoCompartment( bool v ); + + ////////////////////////////////////////////////////////////////// + // Undump operations + ////////////////////////////////////////////////////////////////// + + void innerRead( ifstream& fin ); + ParseMode readInit( const string& line ); + Id read( const string& filename, const string& cellname, + Id parent, const string& solverClass = "Stoich" ); + void readData( const string& line ); + void undump( const vector< string >& args ); + + /** + * This function sets up the kkit model for a run using the GSL, + * which means numerical integration using the GSL, all the plots + * specified by the kkit file, and the timestep for plots as + * specified by the kkit file. + */ + // void setupGslRun(); + + void run(); + void dumpPlots( const string& filename ); + + ////////////////////////////////////////////////////////////////// + // Building up the model + ////////////////////////////////////////////////////////////////// + Id buildCompartment( const vector< string >& args ); + Id buildPool( const vector< string >& args ); + Id buildReac( const vector< string >& args ); + Id buildEnz( const vector< string >& args ); + Id buildPlot( const vector< string >& args ); + Id buildTable( const vector< string >& args ); + unsigned int loadTab( const vector< string >& args ); + Id buildGroup( const vector< string >& args ); + Id buildText( const vector< string >& args ); + Id buildGraph( const vector< string >& args ); + Id buildGeometry( const vector< string >& args ); + Id buildStim( const vector< string >& args ); + Id buildChan( const vector< string >& args ); + Id buildInfo( Id parent, map< string, int >& m, + const vector< string >& args ); + void buildSumTotal( const string& src, const string& dest ); + /** + * Finds the source pool for a SumTot. It also deals with cases where + * the source is an enz-substrate complex + */ + Id findSumTotSrc( const string& src ); + + ////////////////////////////////////////////////////////////////// + // Special ops in the model definition + ////////////////////////////////////////////////////////////////// + void addmsg( const vector< string >& args ); + void setupSlaveMsg( const string& src, const string& dest ); + void innerAddMsg( + const string& src, const map< string, Id >& m1, + const string& srcMsg, + const string& dest, const map< string, Id >& m2, + const string& destMsg, + bool isBackward = 0 ); + void call( const vector< string >& args ); + void objdump( const vector< string >& args ); + void textload( const vector< string >& args ); + void separateVols( Id pool, double vol ); + void assignPoolCompartments(); + + /** + * Goes through all Reacs and connects them up to each of the + * compartments in which one or more of their reactants resides. + * Thus, if any of these compartments changes volume, the Reac will + * be informed. + */ + void assignReacCompartments(); + void assignEnzCompartments(); + void assignMMenzCompartments(); + + /** + * We have a slight problem because MOOSE has a more precise value + * for NA than does kkit. Also, at the time the model is loaded, + * the volume relationships are unknown. So we need to fix up conc + * units of all pools reacs post-facto. + * Here we assume that the conc units from Kkit are + * meant to be OK, so they override the #/cell (lower case k) units. + * So we convert all the Kfs and Kbs in the entire system after + * the model has been created, once we know the order of each reac. + */ + void convertParametersToConcUnits(); + + /// Convert pool amounts. Initially given in n, but scaling issue. + void convertPoolAmountToConcUnits(); + + /// Convert Reac rates, initially in n units. + void convertReacRatesToConcUnits(); + + /** + * Convert MMEnz rates. Km should be in conc units. Actually rates + * stored as k1, k2, k3 in num units, so this has to be computed + * and then converted. + */ + void convertMMenzRatesToConcUnits(); + + /** + * Convert regular Enz rates. Binding step k1 has similar issues + * as reac rates. k2 and k3 are both in units of 1/time, so OK. + */ + void convertEnzRatesToConcUnits(); + + ////////////////////////////////////////////////////////////////// + // Utility functions + ////////////////////////////////////////////////////////////////// + + /** + * Splits up kkit path into head and tail portions, + * tail is returned. + * Note that this prepends the basePath to the head. + */ + string pathTail( const string& path, string& head ) const; + + /** + * Utility function. Cleans up path strings. In most cases, it + * replaces things with underscores. + * Replaces square braces with underscores. + * Replaces '*' with 'p' + * as it is usually there to indicate phosphorylation + * Replaces '-' with underscore + * Replaces '@' with underscore + * Replaces ' ' with underscore + */ + string cleanPath( const string& path ) const; + +private: + string basePath_; /// Base path into which entire kkit model will go + Id baseId_; /// Base Id onto which entire kkit model will go. + + double fastdt_; /// fast numerical timestep from kkit. + double simdt_; /// regular numerical timestep from kkit. + double controldt_; /// Timestep for updating control graphics + double plotdt_; /// Timestep for updating plots + double maxtime_; /// Simulation run time. + double transientTime_; /// Time to run model at fastdt + bool useVariableDt_; /// Use both fast and sim dts. + double defaultVol_; /// Default volume for new compartments. + unsigned int version_; /// KKit version. + unsigned int initdumpVersion_; /// Initdump too has a version. + /** + * Normally ReadKkit puts things on the same tree as the kkit tree. + * This flag tells the system to + * reorganize the tree so that each pool or reac or enz is on + * an appropriate compartment. Reacs are a bit arbitrary though, + * just go onto same compt as substrate. + * Defaults to false. + */ + bool moveOntoCompartment_; + + unsigned int numCompartments_; + unsigned int numPools_; + unsigned int numReacs_; + unsigned int numEnz_; + unsigned int numMMenz_; + unsigned int numPlot_; + unsigned int numStim_; + unsigned int numOthers_; + + unsigned int lineNum_; + + map< string, int > poolMap_; + map< string, int > reacMap_; + map< string, int > enzMap_; + map< string, int > groupMap_; + map< string, int > tableMap_; + map< string, int > stimMap_; + map< string, int > chanMap_; + map< string, Id > poolIds_; + map< string, Id > reacIds_; + map< string, Id > enzIds_; + map< string, Id > mmEnzIds_; + map< string, Id > plotIds_; + map< string, Id > tabIds_; + map< string, Id > stimIds_; + map< string, Id > chanIds_; + + /* + vector< Id > pools_; + /// This keeps track of all vols, since the pools no longer do. + vector< double > poolVols_; + */ + + /// This keeps track of unique volumes + vector< double > vols_; + + /// This keeps track of the last Table used in loadtab + Id lastTab_; + /// This holds the vector of array entries for loadtab + vector< double > tabEntries_; + + /// List of Ids in each unique volume. + vector< vector< Id > > volCategories_; + vector< Id > compartments_; + vector< pair< Id, Id > > enzCplxMols_; + + map< Id, int > poolFlags_; + + map< Id, double > poolVols_; // Need for enz complexes. + + Shell* shell_; + + static const double EPSILON; }; #endif // READ_KKIT_H diff --git a/kinetics/lookupVolumeFromMesh.cpp b/kinetics/lookupVolumeFromMesh.cpp index e0457b6b..397e3895 100644 --- a/kinetics/lookupVolumeFromMesh.cpp +++ b/kinetics/lookupVolumeFromMesh.cpp @@ -16,12 +16,12 @@ // compartment. Pools use a special msg, but this works for reacs too. ObjId getCompt( Id id ) { - ObjId pa = Neutral::parent( id.eref() ).id; - if ( pa == ObjId() ) - return pa; - else if ( pa.element()->cinfo()->isA( "ChemCompt" ) ) - return pa; - return getCompt( pa ); + ObjId pa = Neutral::parent( id.eref() ).id; + if ( pa == ObjId() ) + return pa; + else if ( pa.element()->cinfo()->isA( "ChemCompt" ) ) + return pa; + return getCompt( pa ); } @@ -29,11 +29,11 @@ ObjId getCompt( Id id ) /// match between pool indices and mesh indices: that is what they are for. double lookupVolumeFromMesh( const Eref& e ) { - ObjId compt = getCompt( e.id() ); - if ( compt == ObjId() ) - return 1.0; - return LookupField< unsigned int, double >:: - get( compt, "oneVoxelVolume", e.dataIndex() ); + ObjId compt = getCompt( e.id() ); + if ( compt == ObjId() ) + return 1.0; + return LookupField< unsigned int, double >:: + get( compt, "oneVoxelVolume", e.dataIndex() ); } /** @@ -50,35 +50,40 @@ double lookupVolumeFromMesh( const Eref& e ) */ unsigned int getReactantVols( const Eref& reac, const SrcFinfo* pools, - vector< double >& vols ) + vector< double >& vols ) { - static const unsigned int meshIndex = 0; - - const vector< MsgFuncBinding >* mfb = - reac.element()->getMsgAndFunc( pools->getBindIndex() ); - unsigned int smallIndex = 0; - - vols.resize( 0 ); - if ( mfb ) { - for ( unsigned int i = 0; i < mfb->size(); ++i ) { - double v = 1; - Element* pool = Msg::getMsg( (*mfb)[i].mid )->e2(); - if ( pool == reac.element() ) - pool = Msg::getMsg( (*mfb)[i].mid )->e1(); - assert( pool != reac.element() ); - Eref pooler( pool, meshIndex ); - if ( pool->cinfo()->isA( "PoolBase" ) ) { - v = lookupVolumeFromMesh( pooler ); - } else { - cout << "Error: getReactantVols: pool is of unknown type\n"; - assert( 0 ); - } - vols.push_back( v ); - if ( v < vols[0] ) - smallIndex = i; - } - } - return smallIndex; + static const unsigned int meshIndex = 0; + + const vector< MsgFuncBinding >* mfb = + reac.element()->getMsgAndFunc( pools->getBindIndex() ); + unsigned int smallIndex = 0; + + vols.resize( 0 ); + if ( mfb ) + { + for ( unsigned int i = 0; i < mfb->size(); ++i ) + { + double v = 1; + Element* pool = Msg::getMsg( (*mfb)[i].mid )->e2(); + if ( pool == reac.element() ) + pool = Msg::getMsg( (*mfb)[i].mid )->e1(); + assert( pool != reac.element() ); + Eref pooler( pool, meshIndex ); + if ( pool->cinfo()->isA( "PoolBase" ) ) + { + v = lookupVolumeFromMesh( pooler ); + } + else + { + cout << "Error: getReactantVols: pool is of unknown type\n"; + assert( 0 ); + } + vols.push_back( v ); + if ( v < vols[0] ) + smallIndex = i; + } + } + return smallIndex; } /** @@ -106,43 +111,49 @@ unsigned int getReactantVols( const Eref& reac, const SrcFinfo* pools, */ double convertConcToNumRateUsingMesh( const Eref& e, const SrcFinfo* pools, - bool doPartialConversion ) + bool doPartialConversion ) { - vector< double > vols; - // unsigned int smallest = getReactantVols( e, pools, vols ); - double conv = 1.0; - getReactantVols( e, pools, vols ); - if ( vols.size() == 0 ) { // Should this be an assertion? - // cout << "Warning: convertConcToNumRateUsingMesh: zero reactants on " << e.id().path() << endl; - return 1.0; - } - for ( unsigned int i = 0; i < vols.size(); ++i ) { - conv *= vols[i] * NA; - } - if ( !doPartialConversion ) { - if ( pools->name() == "subOut" ) { - conv /= vols[0] * NA; - } else { - const Finfo* f = e.element()->cinfo()->findFinfo( "subOut" ); - assert( f ); - const SrcFinfo* toSub = dynamic_cast< const SrcFinfo* >( f ); - assert( toSub ); - vector< double > subVols; - getReactantVols( e, toSub, subVols ); - if ( subVols.size() == 0 ) // no substrates! - return 1.0; - conv /= subVols[0] * NA; - } - /* - Id compt = getCompt( e.id() ); - if ( compt != Id() ) { - Id mesh( compt.value() + 1 ); - double meshVol = Field< double >::get( mesh, "volume" ); - conv /= meshVol * NA; - } - */ - } - return conv; + vector< double > vols; + // unsigned int smallest = getReactantVols( e, pools, vols ); + double conv = 1.0; + getReactantVols( e, pools, vols ); + if ( vols.size() == 0 ) // Should this be an assertion? + { + // cout << "Warning: convertConcToNumRateUsingMesh: zero reactants on " << e.id().path() << endl; + return 1.0; + } + for ( unsigned int i = 0; i < vols.size(); ++i ) + { + conv *= vols[i] * NA; + } + if ( !doPartialConversion ) + { + if ( pools->name() == "subOut" ) + { + conv /= vols[0] * NA; + } + else + { + const Finfo* f = e.element()->cinfo()->findFinfo( "subOut" ); + assert( f ); + const SrcFinfo* toSub = dynamic_cast< const SrcFinfo* >( f ); + assert( toSub ); + vector< double > subVols; + getReactantVols( e, toSub, subVols ); + if ( subVols.size() == 0 ) // no substrates! + return 1.0; + conv /= subVols[0] * NA; + } + /* + Id compt = getCompt( e.id() ); + if ( compt != Id() ) { + Id mesh( compt.value() + 1 ); + double meshVol = Field< double >::get( mesh, "volume" ); + conv /= meshVol * NA; + } + */ + } + return conv; } @@ -152,24 +163,27 @@ double convertConcToNumRateUsingMesh( const Eref& e, const SrcFinfo* pools, * reactants. */ double convertConcToNumRateUsingVol( const Eref& e, const SrcFinfo* pools, - double volume, double scale, bool doPartialConversion ) + double volume, double scale, bool doPartialConversion ) { - const vector< MsgFuncBinding >* mfb = - e.element()->getMsgAndFunc( pools->getBindIndex() ); - double conversion = 1.0; - if ( mfb && mfb->size() > 0 ) { - if ( doPartialConversion || mfb->size() > 1 ) { - conversion = scale * NA * volume; - double power = doPartialConversion + mfb->size() - 1; - if ( power > 1.0 ) { - conversion = pow( conversion, power ); - } - } - if ( conversion <= 0 ) - conversion = 1.0; - } - - return conversion; + const vector< MsgFuncBinding >* mfb = + e.element()->getMsgAndFunc( pools->getBindIndex() ); + double conversion = 1.0; + if ( mfb && mfb->size() > 0 ) + { + if ( doPartialConversion || mfb->size() > 1 ) + { + conversion = scale * NA * volume; + double power = doPartialConversion + mfb->size() - 1; + if ( power > 1.0 ) + { + conversion = pow( conversion, power ); + } + } + if ( conversion <= 0 ) + conversion = 1.0; + } + + return conversion; } /** @@ -179,17 +193,17 @@ double convertConcToNumRateUsingVol( const Eref& e, const SrcFinfo* pools, * We already know the reactants and their affiliations. */ double convertConcToNumRateInTwoCompts( double v1, unsigned int n1, - double v2, unsigned int n2, double scale ) + double v2, unsigned int n2, double scale ) { - double conversion = 1.0; + double conversion = 1.0; - for ( unsigned int i = 1; i < n1; ++i ) - conversion *= scale * NA * v1; - for ( unsigned int i = 0; i < n2; ++i ) - conversion *= scale * NA * v2; + for ( unsigned int i = 1; i < n1; ++i ) + conversion *= scale * NA * v1; + for ( unsigned int i = 0; i < n2; ++i ) + conversion *= scale * NA * v2; - if ( conversion <= 0 ) - conversion = 1.0; + if ( conversion <= 0 ) + conversion = 1.0; - return conversion; + return conversion; } diff --git a/ksolve/BoostSys.cpp b/ksolve/BoostSys.cpp index 0a6e4eb3..04f88a8a 100644 --- a/ksolve/BoostSys.cpp +++ b/ksolve/BoostSys.cpp @@ -14,7 +14,7 @@ * ===================================================================================== */ -#include "BoostSys.h" +#include "../utility/boost_ode.h" #include #include "VoxelPools.h" diff --git a/ksolve/CMakeLists.txt b/ksolve/CMakeLists.txt index 8dd567a7..43aa6e84 100644 --- a/ksolve/CMakeLists.txt +++ b/ksolve/CMakeLists.txt @@ -4,18 +4,24 @@ include( ${CMAKE_CURRENT_SOURCE_DIR}/../CheckCXXCompiler.cmake) if(WITH_BOOST) find_package(Boost 1.53 REQUIRED COMPONENTS thread) - add_definitions( -DUSE_BOOST_ASYNC ) + add_definitions(-DUSE_BOOST ) set(WITH_BOOST_ODE ON) include_directories( ${Boost_INCLUDE_DIRS} ) # This is still not part of official bindings. include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../external/boost-numeric-bindings) endif() -IF(WITH_BOOST_ODE) +# if boost ode is being used, don't use GSL. +if(WITH_BOOST_ODE) + # This is still not part of official bindings. + set(WITH_GSL OFF) + include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../external/boost-numeric-bindings) + add_definitions(-DUSE_BOOST_ODE -UUSE_GSL) include_directories(${Boost_INCLUDE_DIRS}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../external/boost-numeric-bindings) elseif(WITH_GSL) include_directories( ${GSL_INCLUDE_DIRS} ) + add_definitions(-DUSE_GSL -UUSE_BOOST_ODE -UUSE_BOOST) endif(WITH_BOOST_ODE) set(KSOLVE_SRCS diff --git a/ksolve/FuncRateTerm.h b/ksolve/FuncRateTerm.h index b04d7d0a..720026fe 100644 --- a/ksolve/FuncRateTerm.h +++ b/ksolve/FuncRateTerm.h @@ -21,20 +21,24 @@ class FuncRate: public ExternReac { public: - FuncRate( double k, unsigned int targetPoolIndex ) - : k_( k ), funcVolPower_( 0.0 ) - { - func_.setTarget( targetPoolIndex ); - } + FuncRate( double k, unsigned int targetPoolIndex ) : + k_( k ) + , func_(shared_ptr(new FuncTerm())) + , funcVolPower_( 0.0 ) + { + func_->setTarget( targetPoolIndex ); + } double operator() ( const double* S ) const { double t = Field< double >::get( Id(1), "currentTime" ); - return func_( S, t ); // get rate from func calculation. + auto v = (*func_)( S, t ); // get rate from func calculation. + assert(! std::isnan(v)); + return v; } unsigned int getReactants( vector< unsigned int >& molIndex ) const{ molIndex.resize( 1 ); - molIndex[0] = func_.getTarget(); + molIndex[0] = func_->getTarget(); // This is the number of substrates to the reac. It is zero. return 0; @@ -43,41 +47,39 @@ class FuncRate: public ExternReac void setReactants( const vector< unsigned int >& molIndex ) { assert( molIndex.size() > 0 ); - func_.setTarget( molIndex[0] ); + func_->setTarget( molIndex[0] ); } const vector< unsigned int >& getFuncArgIndex() { - return func_.getReactantIndex(); + return func_->getReactantIndex(); } void setFuncArgIndex( const vector< unsigned int >& mol ) { - func_.setReactantIndex( mol ); + func_->setReactantIndex( mol ); } void setExpr( const string& s ) { - func_.setExpr( s ); + func_->setExpr( s ); } const string& getExpr() const { - return func_.getExpr(); + return func_->getExpr(); } - RateTerm* copyWithVolScaling( - double vol, double sub, double prd ) const + RateTerm* copyWithVolScaling(double vol, double sub, double prd ) const { + assert(! std::isnan(vol)); double ratio = sub * pow( NA * vol, funcVolPower_ ); - FuncRate* ret = new FuncRate( k_ / ratio, func_.getTarget() ); + FuncRate* ret = new FuncRate( k_ / ratio, func_->getTarget() ); ret->funcVolPower_ = funcVolPower_; ret->func_ = func_; - // return new FuncRate( k_ / ratio ); return ret; } protected: - FuncTerm func_; double k_; + shared_ptr func_; double funcVolPower_; - }; @@ -103,9 +105,10 @@ class FuncReac: public FuncRate v_( v ) {;} - double operator() ( const double* S ) const { + double operator() ( const double* S ) const + { // double ret = k_ * func_( S, 0.0 ); // get rate from func calculation. - double ret = func_( S, 0.0 ); // get rate from func calculation. + double ret = (*func_)( S, 0.0 ); // get rate from func calculation. vector< unsigned int >::const_iterator i; for ( i = v_.begin(); i != v_.end(); i++) { assert( !std::isnan( S[ *i ] ) ); @@ -114,12 +117,14 @@ class FuncReac: public FuncRate return ret; } - unsigned int getReactants( vector< unsigned int >& molIndex ) const{ + unsigned int getReactants( vector< unsigned int >& molIndex ) const + { molIndex = v_; return numSubstrates_; } - void setReactants( const vector< unsigned int >& molIndex ) { + void setReactants( const vector< unsigned int >& molIndex ) + { v_ = molIndex; } @@ -143,7 +148,6 @@ class FuncReac: public FuncRate ret->func_ = func_; ret->funcVolPower_ = funcVolPower_; return ret; - // return new FuncReac( k_ / ratio, v_ ); } private: diff --git a/ksolve/FuncTerm.cpp b/ksolve/FuncTerm.cpp index 527744f7..64fbc8b6 100644 --- a/ksolve/FuncTerm.cpp +++ b/ksolve/FuncTerm.cpp @@ -26,41 +26,37 @@ using namespace std; #include "FuncTerm.h" #include "../utility/numutil.h" -FuncTerm::FuncTerm() - : reactantIndex_( 1, 0 ), - volScale_( 1.0 ), - target_( ~0U) +FuncTerm::FuncTerm(): + reactantIndex_(1, 0) , volScale_(1.0) , target_(~0U) , args_(nullptr) { - args_ = 0; - parser_.DefineConst(_T("pi"), (mu::value_type)M_PI); - parser_.DefineConst(_T("e"), (mu::value_type)M_E); } FuncTerm::~FuncTerm() { - if (args_) { + if(args_) delete[] args_; - } } void FuncTerm::setReactantIndex( const vector< unsigned int >& mol ) { reactantIndex_ = mol; - if ( args_ ) { + if ( args_ ) + { delete[] args_; - args_ = 0; + parser_.ClearAll(); } - args_ = new double[ mol.size() + 1 ]; - // args_.resize( mol.size() + 1, 0.0 ); - for ( unsigned int i = 0; i < mol.size(); ++i ) { - stringstream ss; + + args_ = new double[mol.size()+1]; + for ( unsigned int i = 0; i < mol.size(); ++i ) + { args_[i] = 0.0; - ss << "x" << i; - parser_.DefineVar( ss.str(), &args_[i] ); + parser_.DefineVar( 'x'+to_string(i), &args_[i] ); } + // Define a 't' variable even if we don't always use it. args_[mol.size()] = 0.0; parser_.DefineVar( "t", &args_[mol.size()] ); + setExpr(expr_); } const vector< unsigned int >& FuncTerm::getReactantIndex() const @@ -69,25 +65,36 @@ const vector< unsigned int >& FuncTerm::getReactantIndex() const } -void showError(mu::Parser::exception_type &e) +void showError(moose::Parser::exception_type &e) { - cout << "Error occurred in parser.\n" - << "Message: " << e.GetMsg() << "\n" - << "Formula: " << e.GetExpr() << "\n" - << "Token: " << e.GetToken() << "\n" - << "Position: " << e.GetPos() << "\n" - << "Error code: " << e.GetCode() << endl; + cerr << "Error occurred in parser.\n" + << "Message: " << e.GetMsg() << endl; } +/* --------------------------------------------------------------------------*/ +/** + * @Synopsis Set expression on FuncTerm. Before calling this function, user + * should make sure that symbol_table has been linked to pointers to the variables. + * + * @Param expr + */ +/* ----------------------------------------------------------------------------*/ void FuncTerm::setExpr( const string& expr ) { - try { - parser_.SetExpr( expr ); + // Empty expression are not allowed. + if(expr.empty()) + return; + + try + { + if(! parser_.SetExpr(expr)) + MOOSE_WARN("Failed to set expression: '" << expr << "'"); expr_ = expr; - } catch(mu::Parser::exception_type &e) { + } + catch(moose::Parser::exception_type &e) + { showError(e); - //return; - throw(e); + return; } } @@ -118,12 +125,13 @@ double FuncTerm::getVolScale() const const FuncTerm& FuncTerm::operator=( const FuncTerm& other ) { - args_ = 0; // Don't delete it, the original one is still using it. - parser_ = other.parser_; + args_ = nullptr; // other is still using it. expr_ = other.expr_; volScale_ = other.volScale_; target_ = other.target_; - setReactantIndex( other.reactantIndex_ ); + reactantIndex_ = other.reactantIndex_; + parser_ = other.parser_; + setReactantIndex(reactantIndex_); return *this; } @@ -133,40 +141,43 @@ const FuncTerm& FuncTerm::operator=( const FuncTerm& other ) */ double FuncTerm::operator() ( const double* S, double t ) const { - if ( !args_ ) + if ( ! args_ ) return 0.0; - unsigned int i; + + unsigned int i = 0; for ( i = 0; i < reactantIndex_.size(); ++i ) args_[i] = S[reactantIndex_[i]]; args_[i] = t; - try - { - double result = parser_.Eval() * volScale_; - return result; - } - catch (mu::Parser::exception_type &e ) - { - cerr << "Error: " << e.GetMsg() << endl; - throw e; - } + try + { + return parser_.Eval() * volScale_; + } + catch (moose::Parser::exception_type &e ) + { + cerr << "Error: " << e.GetMsg() << endl; + throw e; + } } void FuncTerm::evalPool( double* S, double t ) const { if ( !args_ || target_ == ~0U ) return; + unsigned int i; for ( i = 0; i < reactantIndex_.size(); ++i ) args_[i] = S[reactantIndex_[i]]; args_[i] = t; - try - { - S[ target_] = parser_.Eval() * volScale_; - } - catch ( mu::Parser::exception_type & e ) - { - showError( e ); - //throw e; - } + + try + { + S[ target_] = parser_.Eval() * volScale_; + //assert(! std::isnan(S[target_])); + } + catch ( moose::Parser::exception_type & e ) + { + showError( e ); + return; + } } diff --git a/ksolve/FuncTerm.h b/ksolve/FuncTerm.h index 71bf2de7..0d2af32a 100644 --- a/ksolve/FuncTerm.h +++ b/ksolve/FuncTerm.h @@ -14,46 +14,49 @@ class FuncTerm { - public: - FuncTerm(); - ~FuncTerm(); - /** - * This computes the value. The time t is an argument needed by - * some functions. - */ - double operator() ( const double* S, double t ) const; - const FuncTerm& operator=( const FuncTerm& other ); - - void evalPool( double* s, double t ) const; - - /** - * This function finds the reactant indices in the vector - * S. It returns the number of indices found, which are the - * entries in molIndex. - */ - void setReactantIndex( const vector< unsigned int >& mol ); - const vector< unsigned int >& getReactantIndex() const; - const string& getExpr() const; - void setExpr( const string& e ); - const unsigned int getTarget() const; - void setTarget( unsigned int tgt ); - void setVolScale( double vs ); - double getVolScale() const; - - private: - double* args_; - // Look up reactants in the S vec. - vector< unsigned int > reactantIndex_; - MooseParser parser_; - string expr_; - /** - * Scale factor to account for pool volume if we are assigning conc - * rather than N. Note that this conc will not be further updated - * so this is an undesirable option. - */ - double volScale_; - unsigned int target_; /// Index of the entity to be updated by Func +public: + FuncTerm(); + ~FuncTerm(); + /** + * This computes the value. The time t is an argument needed by + * some functions. + */ + double operator() ( const double* S, double t ) const; + const FuncTerm& operator=( const FuncTerm& other ); + + void evalPool( double* s, double t ) const; + + /** + * This function finds the reactant indices in the vector + * S. It returns the number of indices found, which are the + * entries in molIndex. + */ + void setReactantIndex( const vector< unsigned int >& mol ); + const vector< unsigned int >& getReactantIndex() const; + const string& getExpr() const; + void setExpr( const string& e ); + const unsigned int getTarget() const; + void setTarget( unsigned int tgt ); + void setVolScale( double vs ); + double getVolScale() const; + +private: + // Look up reactants in the S vec. + vector< unsigned int > reactantIndex_; + + /** + * Scale factor to account for pool volume if we are assigning conc + * rather than N. Note that this conc will not be further updated + * so this is an undesirable option. + */ + double volScale_; + unsigned int target_; /// Index of the entity to be updated by Func + + double* args_; + + string expr_; + moose::MooseParser parser_; }; #endif // _FUNC_TERM_H diff --git a/ksolve/Gsolve.cpp b/ksolve/Gsolve.cpp index 4b31deec..3f4514da 100644 --- a/ksolve/Gsolve.cpp +++ b/ksolve/Gsolve.cpp @@ -11,6 +11,7 @@ #include "../mesh/VoxelJunction.h" #include "../utility/print_function.hpp" +#include "../utility/utility.h" #include "VoxelPoolsBase.h" #include "XferInfo.h" @@ -43,10 +44,9 @@ #define SIMPLE_ROUNDING 0 -// When set use std::async rather than std::thread -// TODO: Profiling. +// When set use std::async rather than std::thread. This is slightly faster +// (roughly 3% with gcc7). #define USING_ASYNC 1 - #if USING_ASYNC #define THREAD_LAUNCH_POLICY std::launch::async #endif @@ -149,25 +149,25 @@ const Cinfo* Gsolve::initCinfo() // DestFinfo definitions static DestFinfo process( "process", - "Handles process call", - new ProcOpFunc< Gsolve >( &Gsolve::process ) ); + "Handles process call", + new ProcOpFunc< Gsolve >( &Gsolve::process ) ); static DestFinfo reinit( "reinit", - "Handles reinit call", - new ProcOpFunc< Gsolve >( &Gsolve::reinit ) ); + "Handles reinit call", + new ProcOpFunc< Gsolve >( &Gsolve::reinit ) ); static DestFinfo voxelVol( "voxelVol", - "Handles updates to all voxels. Comes from parent " - "ChemCompt object.", - new OpFunc1< Gsolve, vector< double > >( - &Gsolve::updateVoxelVol ) - ); + "Handles updates to all voxels. Comes from parent " + "ChemCompt object.", + new OpFunc1< Gsolve, vector< double > >( + &Gsolve::updateVoxelVol ) + ); static DestFinfo initProc( "initProc", - "Handles initProc call from Clock", - new ProcOpFunc< Gsolve >( &Gsolve::initProc ) ); + "Handles initProc call from Clock", + new ProcOpFunc< Gsolve >( &Gsolve::initProc ) ); static DestFinfo initReinit( "initReinit", - "Handles initReinit call from Clock", - new ProcOpFunc< Gsolve >( &Gsolve::initReinit ) ); + "Handles initReinit call from Clock", + new ProcOpFunc< Gsolve >( &Gsolve::initReinit ) ); // Shared definitions static Finfo* procShared[] = @@ -176,19 +176,19 @@ const Cinfo* Gsolve::initCinfo() }; static SharedFinfo proc( "proc", - "Shared message for process and reinit", - procShared, sizeof( procShared ) / sizeof( const Finfo* ) - ); + "Shared message for process and reinit", + procShared, sizeof( procShared ) / sizeof( const Finfo* ) + ); static Finfo* initShared[] = { &initProc, &initReinit }; static SharedFinfo init( "init", - "Shared message for initProc and initReinit. This is used" - " when the system has cross-compartment reactions. ", - initShared, sizeof( initShared ) / sizeof( const Finfo* ) - ); + "Shared message for initProc and initReinit. This is used" + " when the system has cross-compartment reactions. ", + initShared, sizeof( initShared ) / sizeof( const Finfo* ) + ); /////////////////////////////////////////////////////// @@ -237,6 +237,7 @@ Gsolve::Gsolve() : { // Initialize with global seed. rng_.setSeed(moose::getGlobalSeed()); + numThreads_ = moose::getEnvInt("MOOSE_NUM_THREADS", 1); } Gsolve& Gsolve::operator=(const Gsolve& ) @@ -409,7 +410,7 @@ void Gsolve::process( const Eref& e, ProcPtr p ) vector< double >::iterator i = dvalues.begin() + 4; for ( ; i != dvalues.end(); ++i ) { -#if SIMPLE_ROUNDING +#if 0 *i = std::round( *i ); #else // *i = approximateWithInteger_debug(__FUNCTION__, *i, rng_); @@ -429,7 +430,7 @@ void Gsolve::process( const Eref& e, ProcPtr p ) { if( numThreads_ > 1 ) { - cerr << "Warn: Not enough voxels or threads. Reverting to serial mode. " << endl; + cerr << "Warn: Not enough voxel. Reverting back to serial mode. " << endl; numThreads_ = 1; } @@ -577,16 +578,18 @@ void Gsolve::reinit( const Eref& e, ProcPtr p ) for ( auto i = pools_.begin(); i != pools_.end(); ++i ) i->refreshAtot( &sys_ ); + // LoadBalancing. Recompute the optimal number of threads. size_t nvPools = pools_.size( ); grainSize_ = (size_t) std::ceil((double)nvPools / (double)numThreads_); assert( grainSize_ * numThreads_ >= nvPools); - numThreads_ = nvPools / grainSize_; + numThreads_ = (size_t) std::ceil((double)nvPools / (double)grainSize_); MOOSE_DEBUG( "Grain size is " << grainSize_ << ". Num threads " << numThreads_); - if(1 < getNumThreads()) + if(1 < numThreads_) cout << "Info: Setting up threaded gsolve with " << getNumThreads( ) << " threads. " << endl; + } ////////////////////////////////////////////////////////////// @@ -756,8 +759,7 @@ void Gsolve::fillPoolFuncDep() void Gsolve::fillIncrementFuncDep() { // create map of funcs that depend on specified molecule. - vector< vector< unsigned int > > funcMap( - stoichPtr_->getNumAllPools() ); + vector< vector< unsigned int > > funcMap( stoichPtr_->getNumAllPools() ); const vector< RateTerm* >& rates = stoichPtr_->getRateTerms(); vector< FuncRate* > incrementRates; vector< unsigned int > incrementRateIndex; @@ -1018,6 +1020,10 @@ void Gsolve::setNumPools( unsigned int numPoolSpecies ) } } +void Gsolve::setNumVarTotPools( unsigned int var, unsigned int tot ) { + setNumPools( tot ); +} + unsigned int Gsolve::getNumPools() const { if ( pools_.size() > 0 ) @@ -1094,14 +1100,14 @@ void Gsolve::updateRateTerms( unsigned int index ) for ( unsigned int i = 0 ; i < pools_.size(); ++i ) { pools_[i].updateAllRateTerms( stoichPtr_->getRateTerms(), - stoichPtr_->getNumCoreRates() ); + stoichPtr_->getNumCoreRates() ); } } else if ( index < stoichPtr_->getNumRates() ) { for ( unsigned int i = 0 ; i < pools_.size(); ++i ) pools_[i].updateRateTerms( stoichPtr_->getRateTerms(), - stoichPtr_->getNumCoreRates(), index ); + stoichPtr_->getNumCoreRates(), index ); } } diff --git a/ksolve/Gsolve.h b/ksolve/Gsolve.h index 594b5607..6b500118 100644 --- a/ksolve/Gsolve.h +++ b/ksolve/Gsolve.h @@ -46,6 +46,7 @@ class Gsolve: public ZombiePoolInterface */ void setNumPools( unsigned int num ); /// Inherited. unsigned int getNumPools() const; /// Inherited. + void setNumVarTotPools( unsigned int var, unsigned int tot );//Inherited VoxelPoolsBase* pools( unsigned int i ); /// Inherited. double volume( unsigned int i ) const; @@ -142,8 +143,6 @@ class Gsolve: public ZombiePoolInterface GssaSystem sys_; - moose::RNG rng_; - /** * Each VoxelPools entry handles all the pools in a single voxel. * Each entry knows how to update itself in order to complete @@ -169,6 +168,9 @@ class Gsolve: public ZombiePoolInterface /// Flag: True if atot should be updated every clock tick bool useClockedUpdate_; + + // private rng. + moose::RNG rng_; }; #endif // _GSOLVE_H diff --git a/ksolve/GssaVoxelPools.cpp b/ksolve/GssaVoxelPools.cpp index 85c4b6b3..9bd253c8 100644 --- a/ksolve/GssaVoxelPools.cpp +++ b/ksolve/GssaVoxelPools.cpp @@ -46,7 +46,7 @@ GssaVoxelPools::GssaVoxelPools(): VoxelPoolsBase(), t_( 0.0 ), atot_( 0.0 ) GssaVoxelPools::~GssaVoxelPools() { - for ( unsigned int i = 0; i < rates_.size(); ++i ) + for ( size_t i = 0; i < rates_.size(); ++i ) delete( rates_[i] ); } @@ -237,11 +237,11 @@ void GssaVoxelPools::reinit( const GssaSystem* g ) if( std::abs(error) >= 1.0 ) { MOOSE_WARN( "Extra " << error - << " molecules in system after converting fractional to integer." - ); + << " molecules in system after converting fractional to integer." + ); } } - else // Just round to the nearest int. + else // Just round to the nearest int. { for ( unsigned int i = 0; i < numVarPools; ++i ) n[i] = std::round(n[i]); @@ -266,10 +266,12 @@ void GssaVoxelPools::updateAllRateTerms( const vector< RateTerm* >& rates, { for ( unsigned int i = 0; i < rates_.size(); ++i ) delete( rates_[i] ); + rates_.resize( rates.size() ); for ( unsigned int i = 0; i < numCoreRates; ++i ) rates_[i] = rates[i]->copyWithVolScaling( getVolume(), 1, 1 ); + for ( unsigned int i = numCoreRates; i < rates.size(); ++i ) rates_[i] = rates[i]->copyWithVolScaling( getVolume(), getXreacScaleSubstrates(i - numCoreRates), @@ -288,10 +290,10 @@ void GssaVoxelPools::updateRateTerms( const vector< RateTerm* >& rates, rates_[index] = rates[index]->copyWithVolScaling( getVolume(), getXreacScaleSubstrates(index - numCoreRates), - getXreacScaleProducts(index - numCoreRates ) ); + getXreacScaleProducts(index - numCoreRates) + ); else - rates_[index] = rates[index]->copyWithVolScaling( - getVolume(), 1.0, 1.0 ); + rates_[index] = rates[index]->copyWithVolScaling(getVolume(), 1.0, 1.0); } /** * updateReacVelocities computes the velocity *v* of each reaction. diff --git a/ksolve/GssaVoxelPools.h b/ksolve/GssaVoxelPools.h index 01ca3275..65ab9495 100644 --- a/ksolve/GssaVoxelPools.h +++ b/ksolve/GssaVoxelPools.h @@ -10,6 +10,8 @@ #ifndef _GSSA_VOXEL_POOLS_BASE_H #define _GSSA_VOXEL_POOLS_BASE_H +#include "../randnum/RNG.h" + class Stoich; class GssaVoxelPools: public VoxelPoolsBase @@ -49,13 +51,13 @@ class GssaVoxelPools: public VoxelPoolsBase void reinit( const GssaSystem* g ); void updateAllRateTerms( const vector< RateTerm* >& rates, - unsigned int numCoreRates ); + unsigned int numCoreRates ); void updateRateTerms( const vector< RateTerm* >& rates, - unsigned int numCoreRates, unsigned int index ); + unsigned int numCoreRates, unsigned int index ); double getReacVelocity( unsigned int r, const double* s ) const; void updateReacVelocities( const GssaSystem* g, - const double* s, vector< double >& v ) const; + const double* s, vector< double >& v ) const; /** * Assign the volume, and handle the cascading effects by scaling @@ -68,7 +70,7 @@ class GssaVoxelPools: public VoxelPoolsBase * Sums the changes in the values onto the specified pools. */ void xferIn( XferInfo& xf, - unsigned int voxelIndex, const GssaSystem* g ); + unsigned int voxelIndex, const GssaSystem* g ); void setStoich( const Stoich* stoichPtr ); diff --git a/ksolve/KinSparseMatrix.cpp b/ksolve/KinSparseMatrix.cpp index 8716f48e..ac70328d 100644 --- a/ksolve/KinSparseMatrix.cpp +++ b/ksolve/KinSparseMatrix.cpp @@ -26,41 +26,24 @@ using namespace std; * v must have nColumns entries. */ double KinSparseMatrix::computeRowRate( - unsigned int row, const vector< double >& v - ) const + unsigned int row, const vector< double >& v +) const { - assert( nColumns() == 0 || row < nRows() ); - assert( v.size() == nColumns() ); - const int* entry = 0; - const unsigned int* colIndex = 0; - unsigned int numEntries = getRow( row, &entry, &colIndex ); - const int* end = entry + numEntries; - - double ret = 0.0; - for ( const int* i = entry; i != end; ++i ) { - ret += *i * v[ *colIndex++ ]; - } - -/* - for ( unsigned int i = 0; i < numEntries; ++i ) { - ret += entry[i] * v[ colIndex[i] ]; - - } - - vector< int >::const_iterator i; - unsigned int rs = rowStart_[ row ]; - vector< unsigned int >::const_iterator j = colIndex_.begin() + rs; - vector< int >::const_iterator end = N_.begin() + rowStart_[ row + 1 ]; - - double ret = 0.0; - for ( i = N_.begin() + rs; i != end; i++ ) - ret += *i * v[ *j++ ]; - - // assert ( !( ret !<>= 0.0 ) ); - */ - - assert ( !( std::isnan( ret ) ) ); - return ret; + assert( nColumns() == 0 || row < nRows() ); + assert( v.size() == nColumns() ); + const int* entry = 0; + const unsigned int* colIndex = 0; + unsigned int numEntries = getRow( row, &entry, &colIndex ); + const int* end = entry + numEntries; + + double ret = 0.0; + for ( const int* i = entry; i != end; ++i ) + { + ret += *i * v[ *colIndex++ ]; + assert(! std::isnan(ret)); + } + //assert ( !std::isnan(ret) ); + return ret; } @@ -71,38 +54,47 @@ double KinSparseMatrix::computeRowRate( * Does NOT ensure that list is unique. */ void KinSparseMatrix::getGillespieDependence( - unsigned int row, vector< unsigned int >& deps + unsigned int row, vector< unsigned int >& deps ) const { - deps.resize( 0 ); - // vector< unsigned int > deps; - for ( unsigned int i = 0; i < nrows_; ++i ) { - // i is index for reac # here. Note that matrix is transposed. - unsigned int j = rowStart_[ row ]; - unsigned int jend = rowStart_[ row + 1 ]; - unsigned int k = rowStart_[ i ]; - unsigned int kend = rowStart_[ i + 1 ]; - - while ( j < jend && k < kend ) { - if ( colIndex_[ j ] == colIndex_[ k ] ) { - /* Pre 28 Nov 2015. Why below zero? Shouldn't it be any? - if ( N_[ k ] < 0 ) { - deps.push_back( i ); - } - */ - assert( round( N_[k] ) != 0 ); - deps.push_back( i ); - ++j; - ++k; - } else if ( colIndex_[ j ] < colIndex_[ k ] ) { - ++j; - } else if ( colIndex_[ j ] > colIndex_[ k ] ) { - ++k; - } else { - assert( 0 ); - } - } - } + deps.resize( 0 ); + // vector< unsigned int > deps; + for ( unsigned int i = 0; i < nrows_; ++i ) + { + // i is index for reac # here. Note that matrix is transposed. + unsigned int j = rowStart_[ row ]; + unsigned int jend = rowStart_[ row + 1 ]; + unsigned int k = rowStart_[ i ]; + unsigned int kend = rowStart_[ i + 1 ]; + + while ( j < jend && k < kend ) + { + if ( colIndex_[ j ] == colIndex_[ k ] ) + { + /* Pre 28 Nov 2015. Why below zero? Shouldn't it be any? + if ( N_[ k ] < 0 ) { + deps.push_back( i ); + } + */ + assert( round( N_[k] ) != 0 ); + deps.push_back( i ); + ++j; + ++k; + } + else if ( colIndex_[ j ] < colIndex_[ k ] ) + { + ++j; + } + else if ( colIndex_[ j ] > colIndex_[ k ] ) + { + ++k; + } + else + { + assert( 0 ); + } + } + } } /** @@ -111,25 +103,26 @@ void KinSparseMatrix::getGillespieDependence( * Direction [-1,+1] specifies whether the reaction is forward or backward. */ void KinSparseMatrix::fireReac( unsigned int reacIndex, vector< double >& S, double direction ) - const +const { - assert( ncolumns_ == S.size() && reacIndex < nrows_ ); - unsigned int rowBeginIndex = rowStart_[ reacIndex ]; - // vector< int >::const_iterator rowEnd = N_.begin() + rowStart_[ reacIndex + 1]; - vector< int >::const_iterator rowBegin = - N_.begin() + rowBeginIndex; - vector< int >::const_iterator rowEnd = - N_.begin() + rowTruncated_[ reacIndex ]; - vector< unsigned int >::const_iterator molIndex = - colIndex_.begin() + rowBeginIndex; - - for ( vector< int >::const_iterator i = rowBegin; i != rowEnd; ++i ) { - double& x = S[ *molIndex++ ]; - x += *i * direction; - x *= (x > 0 ); - // assert( S[ *molIndex ] + *i * direction >= 0.0 ); - // S[ *molIndex++ ] += *i * direction; - } + assert( ncolumns_ == S.size() && reacIndex < nrows_ ); + unsigned int rowBeginIndex = rowStart_[ reacIndex ]; + // vector< int >::const_iterator rowEnd = N_.begin() + rowStart_[ reacIndex + 1]; + vector< int >::const_iterator rowBegin = + N_.begin() + rowBeginIndex; + vector< int >::const_iterator rowEnd = + N_.begin() + rowTruncated_[ reacIndex ]; + vector< unsigned int >::const_iterator molIndex = + colIndex_.begin() + rowBeginIndex; + + for ( vector< int >::const_iterator i = rowBegin; i != rowEnd; ++i ) + { + double& x = S[ *molIndex++ ]; + x += *i * direction; + x *= (x > 0 ); + // assert( S[ *molIndex ] + *i * direction >= 0.0 ); + // S[ *molIndex++ ] += *i * direction; + } } /** @@ -140,28 +133,33 @@ void KinSparseMatrix::fireReac( unsigned int reacIndex, vector< double >& S, dou */ void KinSparseMatrix::truncateRow( unsigned int maxColumnIndex ) { - rowTruncated_.resize( nrows_, 0 ); - if ( colIndex_.size() == 0 ) - return; - for ( unsigned int i = 0; i < nrows_; ++i ) { - unsigned int endCol = rowStart_[ i ]; - for ( unsigned int j = rowStart_[ i ]; - j < rowStart_[ i + 1 ]; ++j ) { - if ( colIndex_[ j ] < maxColumnIndex ) { - endCol = j + 1; - } else { - break; - } - } - rowTruncated_[ i ] = endCol; - } + rowTruncated_.resize( nrows_, 0 ); + if ( colIndex_.size() == 0 ) + return; + for ( unsigned int i = 0; i < nrows_; ++i ) + { + unsigned int endCol = rowStart_[ i ]; + for ( unsigned int j = rowStart_[ i ]; + j < rowStart_[ i + 1 ]; ++j ) + { + if ( colIndex_[ j ] < maxColumnIndex ) + { + endCol = j + 1; + } + else + { + break; + } + } + rowTruncated_[ i ] = endCol; + } } void makeVecUnique( vector< unsigned int >& v ) { - vector< unsigned int >::iterator pos = unique( v.begin(), v.end() ); - v.resize( pos - v.begin() ); + vector< unsigned int >::iterator pos = unique( v.begin(), v.end() ); + v.resize( pos - v.begin() ); } @@ -170,127 +168,131 @@ void makeVecUnique( vector< unsigned int >& v ) void testKinSparseMatrix() { - const double EPSILON = 1e-7; - // This is the stoichiometry matrix for the unidirectional reacns - // coming out of the following system: - // a + b <===> c - // c + d <===> e - // a + f <===> g - // a + e <===> 2g - // - // When halfreac 0 fires, it affects 0, 1, 2, 4, 6. - // and so on. - static int transposon[][ 8 ] = { - { -1, 1, 0, 0, -1, 1, -1, 1 }, - { -1, 1, 0, 0, 0, 0, 0, 0 }, - { 1, -1, -1, 1, 0, 0, 0, 0 }, - { 0, 0, -1, 1, 0, 0, 0, 0 }, - { 0, 0, 1, -1, 0, 0, -1, 1 }, - { 0, 0, 0, 0, -1, 1, 0, 0 }, - { 0, 0, 0, 0, 1, -1, 2, -2 } - }; - - cout << "\nTesting KinSparseMatrix" << flush; - const unsigned int NR = 4; - const unsigned int NC = 5; - - const unsigned int NTR = 7; // for transposon - const unsigned int NTC = 8; - - KinSparseMatrix sm; - sm.setSize( NR, NC ); - - for ( unsigned int i = 0; i < NR; i++ ) { - for ( unsigned int j = 0; j < NC; j++ ) { - sm.set( i, j, 10 * i + j ); - // cout << i << ", " << j << ", " << sm.nColumns() << endl; - int ret = sm.get( i, j ); - assert( ret == static_cast< int >( 10 * i + j ) ); - } - } - // cout << sm; - - vector< double > v( 5, 1.0 ); - double dret = sm.computeRowRate( 0, v ); - assert( fabs( dret - 10.0 ) < EPSILON ); - dret = sm.computeRowRate( 1, v ); - assert( fabs( dret - 60.0 ) < EPSILON ); - dret = sm.computeRowRate( 2, v ); - assert( fabs( dret - 110.0 ) < EPSILON ); - dret = sm.computeRowRate( 3, v ); - assert( fabs( dret - 160.0 ) < EPSILON ); - - //////////////////////////////////////////////////////////////// - // Checking transposition operation - //////////////////////////////////////////////////////////////// - KinSparseMatrix orig; - orig.setSize( NTR, NTC ); - for ( unsigned int i = 0; i < NTR; i++ ) - for ( unsigned int j = 0; j < NTC; j++ ) - orig.set( i, j, transposon[ i ][ j ] ); - - for ( unsigned int i = 0; i < NTR; i++ ) - for ( unsigned int j = 0; j < NTC; j++ ) - assert( orig.get( i, j ) == transposon[ i ][ j ] ); - - orig.transpose(); - for ( unsigned int i = 0; i < NTR; i++ ) - for ( unsigned int j = 0; j < NTC; j++ ) - assert( orig.get( j, i ) == transposon[ i ][ j ] ); - - - //////////////////////////////////////////////////////////////// - // Checking generation of dependency graphs. - //////////////////////////////////////////////////////////////// - - KinSparseMatrix trans; - vector< unsigned int > deps; - trans.getGillespieDependence( 0, deps ); - /* - makeVecUnique( deps ); - ASSERT( deps.size() == 5, "Gillespie dependence" ); - ASSERT( deps[0] == 0, "Gillespie dependence" ); - ASSERT( deps[1] == 1, "Gillespie dependence" ); - ASSERT( deps[2] == 2, "Gillespie dependence" ); - ASSERT( deps[3] == 4, "Gillespie dependence" ); - ASSERT( deps[4] == 6, "Gillespie dependence" ); - - trans.getGillespieDependence( 1, deps ); - makeVecUnique( deps ); - ASSERT( deps.size() == 5, "Gillespie dependence" ); - ASSERT( deps[0] == 0, "Gillespie dependence" ); - ASSERT( deps[1] == 1, "Gillespie dependence" ); - ASSERT( deps[2] == 2, "Gillespie dependence" ); - ASSERT( deps[3] == 4, "Gillespie dependence" ); - ASSERT( deps[4] == 6, "Gillespie dependence" ); - - trans.getGillespieDependence( 2, deps ); - makeVecUnique( deps ); - ASSERT( deps.size() == 4, "Gillespie dependence" ); - ASSERT( deps[0] == 1, "Gillespie dependence" ); - ASSERT( deps[1] == 2, "Gillespie dependence" ); - ASSERT( deps[2] == 3, "Gillespie dependence" ); - ASSERT( deps[3] == 6, "Gillespie dependence" ); - - trans.getGillespieDependence( 4, deps ); - makeVecUnique( deps ); - ASSERT( deps.size() == 5, "Gillespie dependence" ); - ASSERT( deps[0] == 0, "Gillespie dependence" ); - ASSERT( deps[1] == 4, "Gillespie dependence" ); - ASSERT( deps[2] == 5, "Gillespie dependence" ); - ASSERT( deps[3] == 6, "Gillespie dependence" ); - ASSERT( deps[4] == 7, "Gillespie dependence" ); - - trans.getGillespieDependence( 6, deps ); - makeVecUnique( deps ); - ASSERT( deps.size() == 6, "Gillespie dependence" ); - ASSERT( deps[0] == 0, "Gillespie dependence" ); - ASSERT( deps[1] == 3, "Gillespie dependence" ); - ASSERT( deps[2] == 4, "Gillespie dependence" ); - ASSERT( deps[3] == 5, "Gillespie dependence" ); - ASSERT( deps[4] == 6, "Gillespie dependence" ); - ASSERT( deps[5] == 7, "Gillespie dependence" ); - */ + const double EPSILON = 1e-7; + // This is the stoichiometry matrix for the unidirectional reacns + // coming out of the following system: + // a + b <===> c + // c + d <===> e + // a + f <===> g + // a + e <===> 2g + // + // When halfreac 0 fires, it affects 0, 1, 2, 4, 6. + // and so on. + static int transposon[][ 8 ] = + { + { -1, 1, 0, 0, -1, 1, -1, 1 }, + { -1, 1, 0, 0, 0, 0, 0, 0 }, + { 1, -1, -1, 1, 0, 0, 0, 0 }, + { 0, 0, -1, 1, 0, 0, 0, 0 }, + { 0, 0, 1, -1, 0, 0, -1, 1 }, + { 0, 0, 0, 0, -1, 1, 0, 0 }, + { 0, 0, 0, 0, 1, -1, 2, -2 } + }; + + cout << "\nTesting KinSparseMatrix" << flush; + const unsigned int NR = 4; + const unsigned int NC = 5; + + const unsigned int NTR = 7; // for transposon + const unsigned int NTC = 8; + + KinSparseMatrix sm; + sm.setSize( NR, NC ); + + for ( unsigned int i = 0; i < NR; i++ ) + { + for ( unsigned int j = 0; j < NC; j++ ) + { + sm.set( i, j, 10 * i + j ); + // cout << i << ", " << j << ", " << sm.nColumns() << endl; + int ret = sm.get( i, j ); + assert( ret == static_cast< int >( 10 * i + j ) ); + } + } + // cout << sm; + + vector< double > v( 5, 1.0 ); + double dret = sm.computeRowRate( 0, v ); + assert( fabs( dret - 10.0 ) < EPSILON ); + dret = sm.computeRowRate( 1, v ); + assert( fabs( dret - 60.0 ) < EPSILON ); + dret = sm.computeRowRate( 2, v ); + assert( fabs( dret - 110.0 ) < EPSILON ); + dret = sm.computeRowRate( 3, v ); + assert( fabs( dret - 160.0 ) < EPSILON ); + + //////////////////////////////////////////////////////////////// + // Checking transposition operation + //////////////////////////////////////////////////////////////// + KinSparseMatrix orig; + orig.setSize( NTR, NTC ); + for ( unsigned int i = 0; i < NTR; i++ ) + for ( unsigned int j = 0; j < NTC; j++ ) + orig.set( i, j, transposon[ i ][ j ] ); + + for ( unsigned int i = 0; i < NTR; i++ ) + for ( unsigned int j = 0; j < NTC; j++ ) + assert( orig.get( i, j ) == transposon[ i ][ j ] ); + + orig.transpose(); + for ( unsigned int i = 0; i < NTR; i++ ) + for ( unsigned int j = 0; j < NTC; j++ ) + assert( orig.get( j, i ) == transposon[ i ][ j ] ); + + + //////////////////////////////////////////////////////////////// + // Checking generation of dependency graphs. + //////////////////////////////////////////////////////////////// + + KinSparseMatrix trans; + vector< unsigned int > deps; + trans.getGillespieDependence( 0, deps ); + + /* + makeVecUnique( deps ); + ASSERT( deps.size() == 5, "Gillespie dependence" ); + ASSERT( deps[0] == 0, "Gillespie dependence" ); + ASSERT( deps[1] == 1, "Gillespie dependence" ); + ASSERT( deps[2] == 2, "Gillespie dependence" ); + ASSERT( deps[3] == 4, "Gillespie dependence" ); + ASSERT( deps[4] == 6, "Gillespie dependence" ); + + trans.getGillespieDependence( 1, deps ); + makeVecUnique( deps ); + ASSERT( deps.size() == 5, "Gillespie dependence" ); + ASSERT( deps[0] == 0, "Gillespie dependence" ); + ASSERT( deps[1] == 1, "Gillespie dependence" ); + ASSERT( deps[2] == 2, "Gillespie dependence" ); + ASSERT( deps[3] == 4, "Gillespie dependence" ); + ASSERT( deps[4] == 6, "Gillespie dependence" ); + + trans.getGillespieDependence( 2, deps ); + makeVecUnique( deps ); + ASSERT( deps.size() == 4, "Gillespie dependence" ); + ASSERT( deps[0] == 1, "Gillespie dependence" ); + ASSERT( deps[1] == 2, "Gillespie dependence" ); + ASSERT( deps[2] == 3, "Gillespie dependence" ); + ASSERT( deps[3] == 6, "Gillespie dependence" ); + + trans.getGillespieDependence( 4, deps ); + makeVecUnique( deps ); + ASSERT( deps.size() == 5, "Gillespie dependence" ); + ASSERT( deps[0] == 0, "Gillespie dependence" ); + ASSERT( deps[1] == 4, "Gillespie dependence" ); + ASSERT( deps[2] == 5, "Gillespie dependence" ); + ASSERT( deps[3] == 6, "Gillespie dependence" ); + ASSERT( deps[4] == 7, "Gillespie dependence" ); + + trans.getGillespieDependence( 6, deps ); + makeVecUnique( deps ); + ASSERT( deps.size() == 6, "Gillespie dependence" ); + ASSERT( deps[0] == 0, "Gillespie dependence" ); + ASSERT( deps[1] == 3, "Gillespie dependence" ); + ASSERT( deps[2] == 4, "Gillespie dependence" ); + ASSERT( deps[3] == 5, "Gillespie dependence" ); + ASSERT( deps[4] == 6, "Gillespie dependence" ); + ASSERT( deps[5] == 7, "Gillespie dependence" ); + */ } #endif diff --git a/ksolve/KinSparseMatrix.h b/ksolve/KinSparseMatrix.h index 52132dcc..1182126e 100644 --- a/ksolve/KinSparseMatrix.h +++ b/ksolve/KinSparseMatrix.h @@ -12,61 +12,59 @@ class KinSparseMatrix: public SparseMatrix< int > { - public: -// KinSparseMatrix(); -// KinSparseMatrix( unsigned int nrows, unsigned int ncolumns ); +public: - /** - * Returns all non-zero column indices, for the specified row. - * This gives reac #s in orig matrix, and molecule #s in the - * transposed matrix - * Not needed. The getRow function does all this, more efficiently. - int getRowIndices( - unsigned int row, vector< unsigned int >& indices ); - */ + /** + * Returns all non-zero column indices, for the specified row. + * This gives reac #s in orig matrix, and molecule #s in the + * transposed matrix + * Not needed. The getRow function does all this, more efficiently. + int getRowIndices( + unsigned int row, vector< unsigned int >& indices ); + */ - /** - * Returns the dot product of the specified row with the - * vector v. v corresponds to the vector of reaction rates. - * v must have nColumns entries. - */ - double computeRowRate( - unsigned int row, const vector< double >& v - ) const; + /** + * Returns the dot product of the specified row with the + * vector v. v corresponds to the vector of reaction rates. + * v must have nColumns entries. + */ + double computeRowRate( + unsigned int row, const vector< double >& v + ) const; - /** - * Does a special self-product of the specified row. Output - * is the set of nonzero indices in the product - * abs( Rij ) * neg( Rjk ) for the specified index i, where - * neg( val ) is true only if val < 0. - */ - void getGillespieDependence( - unsigned int row, vector< unsigned int >& cols - ) const; + /** + * Does a special self-product of the specified row. Output + * is the set of nonzero indices in the product + * abs( Rij ) * neg( Rjk ) for the specified index i, where + * neg( val ) is true only if val < 0. + */ + void getGillespieDependence( + unsigned int row, vector< unsigned int >& cols + ) const; - /** - * Fires a stochastic reaction: It undergoes a single transition - * This operation updates the mol concs due to the reacn. - * Direction is +1 or -1, specifies direction of reaction - */ - void fireReac( unsigned int reacIndex, vector< double >& S, - double direction ) const; + /** + * Fires a stochastic reaction: It undergoes a single transition + * This operation updates the mol concs due to the reacn. + * Direction is +1 or -1, specifies direction of reaction + */ + void fireReac( unsigned int reacIndex, vector< double >& S, + double direction ) const; - /** - * This function generates a new internal list of rowEnds, such - * that they are all less than the maxColumnIndex. - * It is used because in fireReac we don't want to update all the - * molecules, only those that are variable. - */ - void truncateRow( unsigned int maxColumnIndex ); + /** + * This function generates a new internal list of rowEnds, such + * that they are all less than the maxColumnIndex. + * It is used because in fireReac we don't want to update all the + * molecules, only those that are variable. + */ + void truncateRow( unsigned int maxColumnIndex ); - private: - /** - * End colIndex for rows (molecules in the transposed matrix) - * so that only variable molecules are below the colIndex. - */ - vector< unsigned int > rowTruncated_; +private: + /** + * End colIndex for rows (molecules in the transposed matrix) + * so that only variable molecules are below the colIndex. + */ + vector< unsigned int > rowTruncated_; }; #endif // _KIN_SPARSE_MATRIX_H diff --git a/ksolve/Ksolve.cpp b/ksolve/Ksolve.cpp index e81b4d8f..e000adc3 100644 --- a/ksolve/Ksolve.cpp +++ b/ksolve/Ksolve.cpp @@ -6,8 +6,11 @@ ** GNU Lesser General Public License version 2.1 ** See the file COPYING.LIB for the full notice. **********************************************************************/ + #include "../basecode/header.h" #include "../basecode/global.h" +#include "../utility/utility.h" + #ifdef USE_GSL #include #include @@ -21,7 +24,6 @@ #include "ZombiePoolInterface.h" #include "RateTerm.h" -#include "FuncTerm.h" #include "../basecode/SparseMatrix.h" #include "KinSparseMatrix.h" #include "Stoich.h" @@ -35,12 +37,6 @@ #include #include -#ifdef USE_BOOST_ASYNC -#define BOOST_THREAD_PROVIDES_FUTURE -#include -#include -#endif - #include #include #include @@ -63,7 +59,8 @@ const Cinfo* Ksolve::initCinfo() "rk4: The Runge-Kutta 4th order fixed dt method" "rk2: The Runge-Kutta 2,3 embedded fixed dt method" "rkck: The Runge-Kutta Cash-Karp (4,5) method" - "rk8: The Runge-Kutta Prince-Dormand (8,9) method" , + "rk8: The Runge-Kutta Prince-Dormand (8,9) method" + "lsoda: LSODA method", &Ksolve::setMethod, &Ksolve::getMethod ); @@ -114,7 +111,7 @@ const Cinfo* Ksolve::initCinfo() static ValueFinfo< Ksolve, unsigned int > numThreads ( "numThreads", - "Number of threads to use (applicable in deterministic case)", + "Number of threads to use", &Ksolve::setNumThreads, &Ksolve::getNumThreads ); @@ -198,18 +195,18 @@ const Cinfo* Ksolve::initCinfo() { &method, // Value &epsAbs, // Value - &epsRel , // Value - &numThreads, // Value - &compartment, // Value + &epsRel , // Value + &numThreads, // Value + &compartment, // Value &numLocalVoxels, // ReadOnlyValue - &nVec, // LookupValue - &numAllVoxels, // ReadOnlyValue - &numPools, // Value - &estimatedDt, // ReadOnlyValue + &nVec, // LookupValue + &numAllVoxels, // ReadOnlyValue + &numPools, // Value + &estimatedDt, // ReadOnlyValue &stoich, // ReadOnlyValue - &voxelVol, // DestFinfo - &proc, // SharedFinfo - &init, // SharedFinfo + &voxelVol, // DestFinfo + &proc, // SharedFinfo + &init, // SharedFinfo }; static Dinfo< Ksolve > dinfo; @@ -241,7 +238,8 @@ Ksolve::Ksolve() dsolve_(), dsolvePtr_( nullptr ) { - ; + numThreads_ = moose::getEnvInt("MOOSE_NUM_THREADS", 1); + } Ksolve::~Ksolve() @@ -260,20 +258,33 @@ string Ksolve::getMethod() const void Ksolve::setMethod( string method ) { + std::transform(method.begin(), method.end(), method.begin(), ::tolower); + // If user is trying to set ksolve method after ksolve has been initialized, + // show a warning. + if( isBuilt_ ) + { + moose::showWarn( + "You are trying to set Ksolve::method after moose::Stoich has been " + " initialized. This will be ignored. Please do before ksolve is assigned to " + " moose::Stoich." + ); + return; + } + #if USE_GSL if ( method == "rk5" || method == "gsl" ) { method_ = "rk5"; } else if ( method == "rk4" || method == "rk2" || - method == "rk8" || method == "rkck" ) + method == "rk8" || method == "rkck" || method == "lsoda" ) { method_ = method; } else { cout << "Warning: Ksolve::setMethod: '" << method << - "' not known, using rk5\n"; + "' is not known, using default rk5\n"; method_ = "rk5"; } #elif USE_BOOST_ODE @@ -507,7 +518,7 @@ void Ksolve::process( const Eref& e, ProcPtr p ) if ( isBuilt_ == false ) return; - t0_ = high_resolution_clock::now(); + //t0_ = high_resolution_clock::now(); // First, handle incoming diffusion values, update S with those. if ( dsolvePtr_ ) @@ -524,45 +535,38 @@ void Ksolve::process( const Eref& e, ProcPtr p ) setBlock( dvalues ); } - size_t nvPools = pools_.size( ); - - // Third, do the numerical integration for all reactions. - size_t grainSize = max( (size_t)1, min( nvPools, nvPools / numThreads_)); - size_t nWorkers = std::max(1, (int)(nvPools/grainSize) ); - - // Just to be sure. Its not very costly computation. - while( nWorkers * grainSize < nvPools ) - grainSize += 1; - - if( 1 == nWorkers || 1 == nvPools ) + if( 1 == numThreads_ || 1 == pools_.size() ) { if( numThreads_ > 1 ) { - cerr << "Warn: Not enough voxels or threads. Reverting to serial mode. " << endl; + cerr << "Warn: Not enough voxels for multithreading. " + << "Reverting to serial mode. " << endl; numThreads_ = 1; } - for ( unsigned int i = 0; i < nvPools; i++ ) + for ( unsigned int i = 0; i < pools_.size(); i++ ) pools_[i].advance( p ); } else { - /*----------------------------------------------------------------------------- - * Somewhat complicated computation to compute the number of threads. 1 - * thread per (at least) voxel pool is ideal situation. - *-----------------------------------------------------------------------------*/ - vector vecThreads; - // cout << nWorkers << " grain size " << grainSize << endl; + std::vector> vecFutures; - // lambdas are faster than std::bind - for (size_t i = 0; i < nWorkers; i++) + // lambdas is faster than std::bind + for (auto interval : intervals_) { - std::thread t( &Ksolve::advance_chunk, this, i*grainSize, (i+1)*grainSize, p ); - vecThreads.push_back( std::move(t) ); + vecFutures.push_back( + std::async( std::launch::async + , &Ksolve::advance_chunk + , this + , interval.first + , interval.second, p + ) + ); } - - for (auto &v : vecThreads ) - v.join(); + size_t tot = 0; + for (auto &v : vecFutures ) + tot += v.get(); + assert(tot == pools_.size()); } // Assemble and send the integrated values off for the Dsolve. @@ -580,8 +584,9 @@ void Ksolve::process( const Eref& e, ProcPtr p ) // for diffusion, channels, and xreacs dsolvePtr_->updateJunctions( p->dt ); } - t1_ = high_resolution_clock::now(); - moose::addSolverProf( "Ksolve", duration_cast> (t1_ - t0_ ).count(), 1 ); + + //t1_ = high_resolution_clock::now(); + //moose::addSolverProf( "Ksolve", duration_cast> (t1_ - t0_ ).count(), 1 ); } void Ksolve::advance_pool( const size_t i, ProcPtr p ) @@ -589,10 +594,15 @@ void Ksolve::advance_pool( const size_t i, ProcPtr p ) pools_[i].advance(p); } -void Ksolve::advance_chunk( const size_t begin, const size_t end, ProcPtr p ) +size_t Ksolve::advance_chunk( const size_t begin, const size_t end, ProcPtr p ) { - for (size_t i = begin; i < std::min(end, pools_.size() ); i++) + size_t tot = 0; + for (size_t i = begin; i < std::min(end, pools_.size()); i++) + { pools_[i].advance( p ); + tot += 1; + } + return tot; } @@ -612,9 +622,16 @@ void Ksolve::reinit( const Eref& e, ProcPtr p ) return; } - if( 1 < getNumThreads( ) ) - cout << "Info: Setting up ksolve with " << numThreads_ << " threads" << endl; + if(numThreads_ > pools_.size()) + numThreads_ = pools_.size(); + if(numThreads_ > 1) + cout << "Info: Multi-threaded Ksolve (" << numThreads_ << " threads)." + << endl; + + // Recompute the partition of interval. + intervals_.clear(); + moose::splitIntervalInNParts(pools_.size(), numThreads_, intervals_); } ////////////////////////////////////////////////////////////// @@ -639,10 +656,8 @@ void Ksolve::updateRateTerms( unsigned int index ) { if ( index == ~0U ) { - // unsigned int numCrossRates = stoichPtr_->getNumRates() - stoichPtr_->getNumCoreRates(); for ( unsigned int i = 0 ; i < pools_.size(); ++i ) { - // pools_[i].resetXreacScale( numCrossRates ); pools_[i].updateAllRateTerms( stoichPtr_->getRateTerms(), stoichPtr_->getNumCoreRates() ); } @@ -726,6 +741,15 @@ void Ksolve::setNumPools( unsigned int numPoolSpecies ) } } +void Ksolve::setNumVarTotPools( unsigned int var, unsigned int tot ) +{ + unsigned int numVoxels = pools_.size(); + for ( unsigned int i = 0 ; i < numVoxels; ++i ) + { + pools_[i].resizeArrays( tot ); + } +} + unsigned int Ksolve::getNumPools() const { if ( pools_.size() > 0 ) @@ -793,7 +817,6 @@ void Ksolve::setBlock( const vector< double >& values ) } } -////////////////////////////////////////////////////////////////////////// void Ksolve::updateVoxelVol( vector< double > vols ) { // For now we assume identical numbers of voxels. Also assume @@ -809,14 +832,8 @@ void Ksolve::updateVoxelVol( vector< double > vols ) } } -////////////////////////////////////////////////////////////////////////// // cross-compartment reaction stuff. -////////////////////////////////////////////////////////////////////////// - -///////////////////////////////////////////////////////////////////// // Functions for setup of cross-compartment transfer. -///////////////////////////////////////////////////////////////////// - void Ksolve::print() const { cout << "path = " << stoichPtr_->getKsolve().path() << diff --git a/ksolve/Ksolve.h b/ksolve/Ksolve.h index 89b87cd7..3c1eba96 100644 --- a/ksolve/Ksolve.h +++ b/ksolve/Ksolve.h @@ -37,6 +37,10 @@ class Ksolve: public ZombiePoolInterface double getEpsRel() const; void setEpsRel( double val ); + // To make API consistent with GssaVoxelPools + double getRelativeAccuracy( ) const; + double getAbsoluteAccuracy( ) const; + /// Assigns Stoich object to Ksolve. Id getStoich() const; void setStoich( Id stoich ); /// Inherited from ZombiePoolInterface. @@ -61,7 +65,7 @@ class Ksolve: public ZombiePoolInterface unsigned int getNumThreads( ) const; void setNumThreads( unsigned int x ); - void advance_chunk( const size_t begin, const size_t end, ProcPtr p ); + size_t advance_chunk( const size_t begin, const size_t end, ProcPtr p ); void advance_pool( const size_t i, ProcPtr p ); @@ -107,6 +111,7 @@ class Ksolve: public ZombiePoolInterface */ void setNumPools( unsigned int num ); unsigned int getNumPools() const; + void setNumVarTotPools( unsigned int var, unsigned int tot ); VoxelPoolsBase* pools( unsigned int i ); double volume( unsigned int i ) const; @@ -139,7 +144,8 @@ class Ksolve: public ZombiePoolInterface /** * @brief Number of threads to use. Only applicable for deterministic case. */ - unsigned int numThreads_; + size_t numThreads_; + size_t grainSize_; /** * Each VoxelPools entry handles all the pools in a single voxel. @@ -170,7 +176,9 @@ class Ksolve: public ZombiePoolInterface // Time taken in all process function in us. double totalTime_ = 0.0; - high_resolution_clock::time_point t0_, t1_; + vector> intervals_; + + //high_resolution_clock::time_point t0_, t1_; }; diff --git a/ksolve/RateTerm.cpp b/ksolve/RateTerm.cpp index 66f6ae33..fb4bb211 100644 --- a/ksolve/RateTerm.cpp +++ b/ksolve/RateTerm.cpp @@ -19,27 +19,29 @@ using namespace std; const double RateTerm::EPSILON = 1.0e-6; StochNOrder::StochNOrder( double k, vector< unsigned int > v ) - : NOrder( k, v ) + : NOrder( k, v ) { - // Here we sort the y vector so that if there are repeated - // substrates, they are put consecutively. This lets us use - // the algorithm below to deal with repeats. - sort( v_.begin(), v_.end() ); + // Here we sort the y vector so that if there are repeated + // substrates, they are put consecutively. This lets us use + // the algorithm below to deal with repeats. + sort( v_.begin(), v_.end() ); } -double StochNOrder::operator() ( const double* S ) const { - double ret = k_; - vector< unsigned int >::const_iterator i; - unsigned int lasty = 0; - double y = 0.0; - for ( i = v_.begin(); i != v_.end(); i++) { - assert( !std::isnan( S[ *i ] ) ); - if ( lasty == *i ) - y -= 1.0; - else - y = S[ *i ]; - ret *= y; - lasty = *i; - } - return ret; +double StochNOrder::operator() ( const double* S ) const +{ + double ret = k_; + vector< unsigned int >::const_iterator i; + unsigned int lasty = 0; + double y = 0.0; + for ( i = v_.begin(); i != v_.end(); i++) + { + assert( !std::isnan( S[ *i ] ) ); + if ( lasty == *i ) + y -= 1.0; + else + y = S[ *i ]; + ret *= y; + lasty = *i; + } + return ret; } diff --git a/ksolve/RateTerm.h b/ksolve/RateTerm.h index 9212c9a9..99184319 100644 --- a/ksolve/RateTerm.h +++ b/ksolve/RateTerm.h @@ -17,298 +17,328 @@ double assignRates( RateCalculation& r ) #include "../utility/numutil.h" class RateTerm { - public: - RateTerm() {;} - virtual ~RateTerm() {;} - /// Computes the rate. The argument is the molecule array. - virtual double operator() ( const double* S ) const = 0; - - /** - * Assign the rates. - */ - virtual void setRates( double k1, double k2 ) = 0; - - /// Used by Zombie to assign rate terms - virtual void setR1( double k1 ) = 0; - - /// Used by Zombie to assign rate terms - virtual void setR2( double k2 ) = 0; - - /// Used by Zombie to return rate terms - virtual double getR1() const = 0; - - /// Used by Zombie to return rate terms - virtual double getR2() const = 0; - - /** - * This function finds the reactant indices in the vector - * S. It returns the number of substrates found, which are the - * first entries in molIndex. The products are the remaining ones. - * Note that it does NOT find products for unidirectional - * reactions, which is a bit of a problem. - */ - virtual unsigned int getReactants( - vector< unsigned int >& molIndex ) const = 0; - static const double EPSILON; - - /** - * This is used to rescale the RateTerm kinetics when the - * compartment volume changes. This is needed because the kinetics - * are in extensive units, that is, mol numbers, rather than in - * intensive units like concentration. So when the volume changes - * the rate terms change. Each Rate term checks if any of its - * reactant molecules are affected, and if so, rescales. - * Ratio is newVol / oldVol - */ - virtual void rescaleVolume( short comptIndex, - const vector< short >& compartmentLookup, double ratio ) = 0; - - /** - * Duplicates rate term and then applies volume scaling. - * Arguments are volume of reference voxel, - * product of vol/refVol for all substrates: applied to R1 - * product of vol/refVol for all products: applied to R2 - * - * Note that unless the reaction is cross-compartment, the - * vol/refVol will be one. - */ - virtual RateTerm* copyWithVolScaling( - double vol, double sub, double prd ) const = 0; +public: + RateTerm() {;} + virtual ~RateTerm() {;} + /// Computes the rate. The argument is the molecule array. + virtual double operator() ( const double* S ) const = 0; + + /** + * Assign the rates. + */ + virtual void setRates( double k1, double k2 ) = 0; + + /// Used by Zombie to assign rate terms + virtual void setR1( double k1 ) = 0; + + /// Used by Zombie to assign rate terms + virtual void setR2( double k2 ) = 0; + + /// Used by Zombie to return rate terms + virtual double getR1() const = 0; + + /// Used by Zombie to return rate terms + virtual double getR2() const = 0; + + /** + * This function finds the reactant indices in the vector + * S. It returns the number of substrates found, which are the + * first entries in molIndex. The products are the remaining ones. + * Note that it does NOT find products for unidirectional + * reactions, which is a bit of a problem. + */ + virtual unsigned int getReactants( + vector< unsigned int >& molIndex ) const = 0; + static const double EPSILON; + + /** + * This is used to rescale the RateTerm kinetics when the + * compartment volume changes. This is needed because the kinetics + * are in extensive units, that is, mol numbers, rather than in + * intensive units like concentration. So when the volume changes + * the rate terms change. Each Rate term checks if any of its + * reactant molecules are affected, and if so, rescales. + * Ratio is newVol / oldVol + */ + virtual void rescaleVolume( short comptIndex, + const vector< short >& compartmentLookup, double ratio ) = 0; + + /** + * Duplicates rate term and then applies volume scaling. + * Arguments are volume of reference voxel, + * product of vol/refVol for all substrates: applied to R1 + * product of vol/refVol for all products: applied to R2 + * + * Note that unless the reaction is cross-compartment, the + * vol/refVol will be one. + */ + virtual RateTerm* copyWithVolScaling( + double vol, double sub, double prd ) const = 0; }; // Base class MMEnzme for the purposes of setting rates // Pure base class: cannot be instantiated, but useful as a handle. class MMEnzymeBase: public RateTerm { - public: - MMEnzymeBase( double Km, double kcat, unsigned int enz ) - : Km_( Km ), kcat_( kcat ), enz_( enz ) - { - assert( Km_ > 0.0 ); - } - - void setKm( double Km ) { - if ( Km > 0.0 ) - Km_ = Km; - } - - void setKcat( double kcat ) { - if ( kcat > 0 ) - kcat_ = kcat; - } - - void setRates( double Km, double kcat ) { - setKm( Km ); - setKcat( kcat ); - } - - void setR1( double Km ) { - setKm( Km ); - } - - void setR2( double kcat ) { - setKcat( kcat ); - } - - double getR1() const { - return Km_; - } - - double getR2() const { - return kcat_; - } - - void rescaleVolume( short comptIndex, - const vector< short >& compartmentLookup, double ratio ) - { - Km_ *= ratio; - } - - unsigned int getEnzIndex() const - { - return enz_; - } - - protected: - double Km_; // In # units, not conc units. - double kcat_; - unsigned int enz_; +public: + MMEnzymeBase( double Km, double kcat, unsigned int enz ) + : Km_( Km ), kcat_( kcat ), enz_( enz ) + { + assert( Km_ > 0.0 ); + } + + void setKm( double Km ) + { + if ( Km > 0.0 ) + Km_ = Km; + } + + void setKcat( double kcat ) + { + if ( kcat > 0 ) + kcat_ = kcat; + } + + void setRates( double Km, double kcat ) + { + setKm( Km ); + setKcat( kcat ); + } + + void setR1( double Km ) + { + setKm( Km ); + } + + void setR2( double kcat ) + { + setKcat( kcat ); + } + + double getR1() const + { + return Km_; + } + + double getR2() const + { + return kcat_; + } + + void rescaleVolume( short comptIndex, + const vector< short >& compartmentLookup, double ratio ) + { + Km_ *= ratio; + } + + unsigned int getEnzIndex() const + { + return enz_; + } + +protected: + double Km_; // In # units, not conc units. + double kcat_; + unsigned int enz_; }; // Single substrate MMEnzyme: by far the most common. class MMEnzyme1: public MMEnzymeBase { - public: - MMEnzyme1( double Km, double kcat, - unsigned int enz, unsigned int sub ) - : MMEnzymeBase( Km, kcat, enz ), sub_( sub ) - { - ; - } - - double operator() ( const double* S ) const { - // assert( S[ sub_ ] >= -EPSILON ); - return ( kcat_ * S[ sub_ ] * S[ enz_ ] ) / ( Km_ + S[ sub_ ] ); - } - - unsigned int getReactants( vector< unsigned int >& molIndex ) const{ - molIndex.resize( 2 ); - molIndex[0] = enz_; - molIndex[1] = sub_; - return 2; - } - - RateTerm* copyWithVolScaling( - double vol, double sub, double prd ) const - { - double ratio = vol * sub * NA; - return new MMEnzyme1( ratio * Km_, kcat_, enz_, sub_); - } - - private: - unsigned int sub_; +public: + MMEnzyme1( double Km, double kcat, + unsigned int enz, unsigned int sub ) + : MMEnzymeBase( Km, kcat, enz ), sub_( sub ) + { + ; + } + + double operator() ( const double* S ) const + { + // assert( S[ sub_ ] >= -EPSILON + auto val = ( kcat_ * S[ sub_ ] * S[ enz_ ] ) / ( Km_ + S[ sub_ ] ); + assert(! std::isnan(val)); + return val; + } + + unsigned int getReactants( vector< unsigned int >& molIndex ) const + { + molIndex.resize( 2 ); + molIndex[0] = enz_; + molIndex[1] = sub_; + return 2; + } + + RateTerm* copyWithVolScaling( + double vol, double sub, double prd ) const + { + double ratio = vol * sub * NA; + return new MMEnzyme1( ratio * Km_, kcat_, enz_, sub_); + } + +private: + unsigned int sub_; }; class MMEnzyme: public MMEnzymeBase { - public: - MMEnzyme( double Km, double kcat, - unsigned int enz, RateTerm* sub ) - : MMEnzymeBase( Km, kcat, enz ), substrates_( sub ) - { - ; - } - - double operator() ( const double* S ) const { - double sub = (*substrates_)( S ); - // the subtrates_() operator returns the conc product. - assert( sub >= -EPSILON ); - return ( sub * kcat_ * S[ enz_ ] ) / ( Km_ + sub ); - } - - unsigned int getReactants( vector< unsigned int >& molIndex ) const{ - substrates_->getReactants( molIndex ); - molIndex.insert( molIndex.begin(), enz_ ); - return molIndex.size(); - } - - RateTerm* copyWithVolScaling( - double vol, double sub, double prd ) const - { - double ratio = sub * vol * NA; - return new MMEnzyme( ratio * Km_, kcat_, enz_, substrates_ ); - } - private: - RateTerm* substrates_; +public: + MMEnzyme( double Km, double kcat, + unsigned int enz, RateTerm* sub ) + : MMEnzymeBase( Km, kcat, enz ), substrates_( sub ) + { + ; + } + + double operator() ( const double* S ) const + { + double sub = (*substrates_)( S ); + // the subtrates_() operator returns the conc product. + assert( sub >= -EPSILON ); + auto val = ( sub * kcat_ * S[ enz_ ] ) / ( Km_ + sub ); + assert(! std::isnan(val)); + return val; + } + + unsigned int getReactants( vector< unsigned int >& molIndex ) const + { + substrates_->getReactants( molIndex ); + molIndex.insert( molIndex.begin(), enz_ ); + return molIndex.size(); + } + + RateTerm* copyWithVolScaling( + double vol, double sub, double prd ) const + { + double ratio = sub * vol * NA; + return new MMEnzyme( ratio * Km_, kcat_, enz_, substrates_ ); + } +private: + RateTerm* substrates_; }; class ExternReac: public RateTerm { - public: - // All the terms will have been updated separately, and - // a reply obtained to this pointer here: - double operator() ( const double* S ) const { - double ret = 0.0; - return ret; - } - void setRates( double k1, double k2 ) { - ; // Dummy function to keep compiler happy - } - - void setR1( double k1 ) { - ; - } - - void setR2( double k2 ) { - ; - } - - double getR1() const { - return 0.0; - } - - double getR2() const { - return 0.0; - } - - unsigned int getReactants( vector< unsigned int >& molIndex ) const{ - molIndex.resize( 0 ); - return 0; - } - - void rescaleVolume( short comptIndex, - const vector< short >& compartmentLookup, double ratio ) - { - return; // Need to figure out what to do here. - } - - RateTerm* copyWithVolScaling( - double vol, double sub, double prd ) const - { - return new ExternReac(); - } - - private: +public: + // All the terms will have been updated separately, and + // a reply obtained to this pointer here: + double operator() ( const double* S ) const + { + double ret = 0.0; + return ret; + } + void setRates( double k1, double k2 ) + { + ; // Dummy function to keep compiler happy + } + + void setR1( double k1 ) + { + ; + } + + void setR2( double k2 ) + { + ; + } + + double getR1() const + { + return 0.0; + } + + double getR2() const + { + return 0.0; + } + + unsigned int getReactants( vector< unsigned int >& molIndex ) const + { + molIndex.resize( 0 ); + return 0; + } + + void rescaleVolume( short comptIndex, + const vector< short >& compartmentLookup, double ratio ) + { + return; // Need to figure out what to do here. + } + + RateTerm* copyWithVolScaling( + double vol, double sub, double prd ) const + { + return new ExternReac(); + } + +private: }; class ZeroOrder: public RateTerm { - public: - ZeroOrder( double k ) - : k_( k ) - { - assert( !std::isnan( k_ ) ); - } - - double operator() ( const double* S ) const { - assert( !std::isnan( k_ ) ); - return k_; - } - - void setK( double k ) { - assert( !std::isnan( k ) ); - if ( k >= 0.0 ) - k_ = k; - } - - void setRates( double k1, double k2 ) { - setK( k1 ); - } - - void setR1( double k1 ) { - setK( k1 ); - } - - void setR2( double k2 ) { - ; - } - - double getR1() const { - return k_; - } - - double getR2() const { - return 0.0; - } - - unsigned int getReactants( vector< unsigned int >& molIndex ) const{ - molIndex.resize( 0 ); - return 0; - } - - void rescaleVolume( short comptIndex, - const vector< short >& compartmentLookup, double ratio ) - { - return; // Nothing needs to be scaled. - } - - RateTerm* copyWithVolScaling( - double vol, double sub, double prd ) const - { - return new ZeroOrder( k_ ); - } - protected: - double k_; +public: + ZeroOrder( double k ) + : k_( k ) + { + assert( !std::isnan( k_ ) ); + } + + double operator() ( const double* S ) const + { + assert(! std::isnan( k_ ) ); + return k_; + } + + void setK( double k ) + { + assert( !std::isnan( k ) ); + if ( k >= 0.0 ) + k_ = k; + } + + void setRates( double k1, double k2 ) + { + setK( k1 ); + } + + void setR1( double k1 ) + { + setK( k1 ); + } + + void setR2( double k2 ) + { + ; + } + + double getR1() const + { + return k_; + } + + double getR2() const + { + return 0.0; + } + + unsigned int getReactants( vector< unsigned int >& molIndex ) const + { + molIndex.resize( 0 ); + return 0; + } + + void rescaleVolume( short comptIndex, + const vector< short >& compartmentLookup, double ratio ) + { + return; // Nothing needs to be scaled. + } + + RateTerm* copyWithVolScaling( + double vol, double sub, double prd ) const + { + return new ZeroOrder( k_ ); + } +protected: + double k_; }; /** @@ -319,109 +349,115 @@ class ZeroOrder: public RateTerm */ class Flux: public ZeroOrder { - public: - Flux( double k, unsigned int y ) - : ZeroOrder( k ), y_( y ) - {;} - - double operator() ( const double* S ) const { - assert( !std::isnan( S[ y_ ] ) ); - return k_ * S[ y_ ]; - } - - unsigned int getReactants( vector< unsigned int >& molIndex ) const{ - molIndex.resize( 0 ); - return 0; - } - - void rescaleVolume( short comptIndex, - const vector< short >& compartmentLookup, double ratio ) - { - return; // Nothing needs to be scaled. - } - - RateTerm* copyWithVolScaling( - double vol, double sub, double prd ) const - { - return new Flux( k_, y_ ); - } - - private: - unsigned int y_; +public: + Flux( double k, unsigned int y ) + : ZeroOrder( k ), y_( y ) + {;} + + double operator() ( const double* S ) const + { + assert(! std::isnan( S[ y_ ] ) ); + return k_ * S[ y_ ]; + } + + unsigned int getReactants( vector< unsigned int >& molIndex ) const + { + molIndex.resize( 0 ); + return 0; + } + + void rescaleVolume( short comptIndex, + const vector< short >& compartmentLookup, double ratio ) + { + return; // Nothing needs to be scaled. + } + + RateTerm* copyWithVolScaling( + double vol, double sub, double prd ) const + { + return new Flux( k_, y_ ); + } + +private: + unsigned int y_; }; class FirstOrder: public ZeroOrder { - public: - FirstOrder( double k, unsigned int y ) - : ZeroOrder( k ), y_( y ) - {;} - - double operator() ( const double* S ) const { - assert( !std::isnan( S[ y_ ] ) ); - return k_ * S[ y_ ]; - } - - unsigned int getReactants( vector< unsigned int >& molIndex ) const{ - molIndex.resize( 1 ); - molIndex[0] = y_; - return 1; - } - - void rescaleVolume( short comptIndex, - const vector< short >& compartmentLookup, double ratio ) - { - return; // Nothing needs to be scaled. - } - - RateTerm* copyWithVolScaling( - double vol, double sub, double prd ) const - { - return new FirstOrder( k_ / sub, y_ ); - } - - private: - unsigned int y_; +public: + FirstOrder( double k, unsigned int y ) + : ZeroOrder( k ), y_( y ) + {;} + + double operator() ( const double* S ) const + { + assert(! std::isnan( S[ y_ ] ) ); + return k_ * S[ y_ ]; + } + + unsigned int getReactants( vector< unsigned int >& molIndex ) const + { + molIndex.resize( 1 ); + molIndex[0] = y_; + return 1; + } + + void rescaleVolume( short comptIndex, + const vector< short >& compartmentLookup, double ratio ) + { + return; // Nothing needs to be scaled. + } + + RateTerm* copyWithVolScaling( + double vol, double sub, double prd ) const + { + return new FirstOrder( k_ / sub, y_ ); + } + +private: + unsigned int y_; }; class SecondOrder: public ZeroOrder { - public: - SecondOrder( double k, unsigned int y1, unsigned int y2 ) - : ZeroOrder( k ), y1_( y1 ), y2_( y2 ) - {;} - - double operator() ( const double* S ) const { - assert( !std::isnan( S[ y1_ ] ) ); - assert( !std::isnan( S[ y2_ ] ) ); - return k_ * S[ y1_ ] * S[ y2_ ]; - } - - unsigned int getReactants( vector< unsigned int >& molIndex ) const{ - molIndex.resize( 2 ); - molIndex[0] = y1_; - molIndex[1] = y2_; - return 2; - } - - void rescaleVolume( short comptIndex, - const vector< short >& compartmentLookup, double ratio ) - { - if ( comptIndex == compartmentLookup[ y1_ ] || - comptIndex == compartmentLookup[ y2_ ] ) - k_ /= ratio; - } - - RateTerm* copyWithVolScaling( - double vol, double sub, double prd ) const - { - double ratio = sub * vol * NA; - return new SecondOrder( k_ / ratio, y1_, y2_ ); - } - - private: - unsigned int y1_; - unsigned int y2_; +public: + SecondOrder( double k, unsigned int y1, unsigned int y2 ) + : ZeroOrder( k ), y1_( y1 ), y2_( y2 ) + {;} + + double operator() ( const double* S ) const + { + assert(! std::isnan( S[ y1_ ] ) ); + assert(! std::isnan( S[ y2_ ] ) ); + return k_ * S[ y1_ ] * S[ y2_ ]; + } + + unsigned int getReactants( vector< unsigned int >& molIndex ) const + { + molIndex.resize( 2 ); + molIndex[0] = y1_; + molIndex[1] = y2_; + return 2; + } + + void rescaleVolume( short comptIndex, + const vector< short >& compartmentLookup, double ratio ) + { + if ( comptIndex == compartmentLookup[ y1_ ] || + comptIndex == compartmentLookup[ y2_ ] ) + k_ /= ratio; + } + + RateTerm* copyWithVolScaling( + double vol, double sub, double prd ) const + { + double ratio = sub * vol * NA; + return new SecondOrder( k_ / ratio, y1_, y2_ ); + } + +private: + unsigned int y1_; + unsigned int y2_; }; /** @@ -433,83 +469,90 @@ class SecondOrder: public ZeroOrder */ class StochSecondOrderSingleSubstrate: public ZeroOrder { - public: - StochSecondOrderSingleSubstrate( double k, unsigned int y ) - : ZeroOrder( k ), y_( y ) - {;} - - double operator() ( const double* S ) const { - double y = S[ y_ ]; - assert( !std::isnan( y ) ); - return k_ * ( y - 1 ) * y; - } - - unsigned int getReactants( vector< unsigned int >& molIndex ) const{ - molIndex.resize( 2 ); - molIndex[0] = y_; - molIndex[1] = y_; - return 2; - } - - void rescaleVolume( short comptIndex, - const vector< short >& compartmentLookup, double ratio ) - { - if ( comptIndex == compartmentLookup[ y_ ] ) - k_ /= ratio; - } - - RateTerm* copyWithVolScaling( - double vol, double sub, double prd ) const - { - double ratio = sub * vol * NA; - return new StochSecondOrderSingleSubstrate( k_ / ratio, y_ ); - } - - private: - const unsigned int y_; +public: + StochSecondOrderSingleSubstrate( double k, unsigned int y ) + : ZeroOrder( k ), y_( y ) + {;} + + double operator() ( const double* S ) const + { + double y = S[ y_ ]; + auto res = k_ * ( y - 1 ) * y; + assert(! std::isnan(res) ); + return res; + } + + unsigned int getReactants( vector< unsigned int >& molIndex ) const + { + molIndex.resize( 2 ); + molIndex[0] = y_; + molIndex[1] = y_; + return 2; + } + + void rescaleVolume( short comptIndex, + const vector< short >& compartmentLookup, double ratio ) + { + if ( comptIndex == compartmentLookup[ y_ ] ) + k_ /= ratio; + } + + RateTerm* copyWithVolScaling( + double vol, double sub, double prd ) const + { + double ratio = sub * vol * NA; + return new StochSecondOrderSingleSubstrate( k_ / ratio, y_ ); + } + +private: + const unsigned int y_; }; class NOrder: public ZeroOrder { - public: - NOrder( double k, vector< unsigned int > v ) - : ZeroOrder( k ), v_( v ) - {;} - - double operator() ( const double* S ) const { - double ret = k_; - vector< unsigned int >::const_iterator i; - for ( i = v_.begin(); i != v_.end(); i++) { - assert( !std::isnan( S[ *i ] ) ); - ret *= S[ *i ]; - } - return ret; - } - - unsigned int getReactants( vector< unsigned int >& molIndex ) const{ - molIndex = v_; - return v_.size(); - } - - void rescaleVolume( short comptIndex, - const vector< short >& compartmentLookup, double ratio ) - { - for ( unsigned int i = 1; i < v_.size(); ++i ) { - if ( comptIndex == compartmentLookup[ v_[i] ] ) - k_ /= ratio; - } - } - - RateTerm* copyWithVolScaling( - double vol, double sub, double prd ) const - { - assert( v_.size() > 0 ); - double ratio = sub * pow( NA * vol, (int)( v_.size() ) - 1 ); - return new NOrder( k_ / ratio, v_ ); - } - - protected: - vector< unsigned int > v_; +public: + NOrder( double k, vector< unsigned int > v ) + : ZeroOrder( k ), v_( v ) + {;} + + double operator() ( const double* S ) const + { + double ret = k_; + vector< unsigned int >::const_iterator i; + for ( i = v_.begin(); i != v_.end(); i++) + { + assert(! std::isnan( S[ *i ] ) ); + ret *= S[ *i ]; + } + return ret; + } + + unsigned int getReactants( vector< unsigned int >& molIndex ) const + { + molIndex = v_; + return v_.size(); + } + + void rescaleVolume( short comptIndex, + const vector< short >& compartmentLookup, double ratio ) + { + for ( unsigned int i = 1; i < v_.size(); ++i ) + { + if ( comptIndex == compartmentLookup[ v_[i] ] ) + k_ /= ratio; + } + } + + RateTerm* copyWithVolScaling( + double vol, double sub, double prd ) const + { + assert( v_.size() > 0 ); + double ratio = sub * pow( NA * vol, (int)( v_.size() ) - 1 ); + return new NOrder( k_ / ratio, v_ ); + } + +protected: + vector< unsigned int > v_; }; /** @@ -521,90 +564,100 @@ class NOrder: public ZeroOrder */ class StochNOrder: public NOrder { - public: - StochNOrder( double k, vector< unsigned int > v ); - - double operator() ( const double* S ) const; - - RateTerm* copyWithVolScaling( - double vol, double sub, double prd ) const - { - assert( v_.size() > 0 ); - double ratio = sub * pow( vol * NA, (int)( v_.size() ) -1); - return new StochNOrder( k_ / ratio, v_ ); - } +public: + StochNOrder( double k, vector< unsigned int > v ); + + double operator() ( const double* S ) const; + + RateTerm* copyWithVolScaling( + double vol, double sub, double prd ) const + { + assert( v_.size() > 0 ); + double ratio = sub * pow( vol * NA, (int)( v_.size() ) -1); + return new StochNOrder( k_ / ratio, v_ ); + } }; extern class ZeroOrder* - makeHalfReaction( double k, vector< unsigned int > v ); + makeHalfReaction( double k, vector< unsigned int > v ); class BidirectionalReaction: public RateTerm { - public: - BidirectionalReaction( - ZeroOrder* forward, ZeroOrder* backward) - : forward_( forward ), backward_( backward ) - { // Here we allocate internal forward and backward terms - // with the correct number of args. - ; - } - ~BidirectionalReaction() - { - delete forward_; - delete backward_; - } - - double operator() ( const double* S ) const { - return (*forward_)( S ) - (*backward_)( S ); - } - - void setRates( double kf, double kb ) { - forward_->setK( kf ); - backward_->setK( kb ); - } - - void setR1( double kf ) { - forward_->setK( kf ); - } - - void setR2( double kb ) { - backward_->setK( kb ); - } - - double getR1() const { - return forward_->getR1(); - } - - double getR2() const { - return backward_->getR1(); - } - - unsigned int getReactants( vector< unsigned int >& molIndex ) const{ - forward_->getReactants( molIndex ); - unsigned int ret = molIndex.size(); - vector< unsigned int > temp; - backward_->getReactants( temp ); - molIndex.insert( molIndex.end(), temp.begin(), temp.end() ); - return ret; - } - - void rescaleVolume( short comptIndex, - const vector< short >& compartmentLookup, double ratio ) - { - forward_->rescaleVolume( comptIndex, compartmentLookup, ratio ); - backward_->rescaleVolume( comptIndex, compartmentLookup, ratio); - } - RateTerm* copyWithVolScaling( - double vol, double sub, double prd ) const - { - ZeroOrder* f = static_cast< ZeroOrder* >( - forward_->copyWithVolScaling( vol, sub, 1 ) ); - ZeroOrder* b = static_cast< ZeroOrder* >( - backward_->copyWithVolScaling( vol, prd, 1 ) ); - return new BidirectionalReaction( f, b ); - } - - private: - ZeroOrder* forward_; - ZeroOrder* backward_; +public: + BidirectionalReaction( + ZeroOrder* forward, ZeroOrder* backward) + : forward_( forward ), backward_( backward ) + { + // Here we allocate internal forward and backward terms + // with the correct number of args. + ; + } + ~BidirectionalReaction() + { + delete forward_; + delete backward_; + } + + double operator() ( const double* S ) const + { + auto v = (*forward_)( S ) - (*backward_)( S ); + assert(! std::isnan(v)); + return v; + } + + void setRates( double kf, double kb ) + { + forward_->setK( kf ); + backward_->setK( kb ); + } + + void setR1( double kf ) + { + forward_->setK( kf ); + } + + void setR2( double kb ) + { + backward_->setK( kb ); + } + + double getR1() const + { + return forward_->getR1(); + } + + double getR2() const + { + return backward_->getR1(); + } + + unsigned int getReactants( vector< unsigned int >& molIndex ) const + { + forward_->getReactants( molIndex ); + unsigned int ret = molIndex.size(); + vector< unsigned int > temp; + backward_->getReactants( temp ); + molIndex.insert( molIndex.end(), temp.begin(), temp.end() ); + return ret; + } + + void rescaleVolume( short comptIndex, + const vector< short >& compartmentLookup, double ratio ) + { + forward_->rescaleVolume( comptIndex, compartmentLookup, ratio ); + backward_->rescaleVolume( comptIndex, compartmentLookup, ratio); + } + RateTerm* copyWithVolScaling( + double vol, double sub, double prd ) const + { + ZeroOrder* f = static_cast< ZeroOrder* >( + forward_->copyWithVolScaling( vol, sub, 1 ) ); + ZeroOrder* b = static_cast< ZeroOrder* >( + backward_->copyWithVolScaling( vol, prd, 1 ) ); + return new BidirectionalReaction( f, b ); + } + +private: + ZeroOrder* forward_; + ZeroOrder* backward_; }; diff --git a/ksolve/Stoich.cpp b/ksolve/Stoich.cpp index 504f8ec1..04600d66 100644 --- a/ksolve/Stoich.cpp +++ b/ksolve/Stoich.cpp @@ -30,6 +30,7 @@ #include "../scheduling/Clock.h" #include "../shell/Shell.h" #include "../shell/Wildcard.h" +#include "../utility/testing_macros.hpp" const Cinfo* Stoich::initCinfo() { @@ -192,16 +193,17 @@ const Cinfo* Stoich::initCinfo() // MsgDest Definitions ////////////////////////////////////////////////////////////// static DestFinfo unzombify( "unzombify", - "Restore all zombies to their native state", - new OpFunc0< Stoich >( &Stoich::unZombifyModel ) - ); + "Restore all zombies to their native state", + new OpFunc0< Stoich >( &Stoich::unZombifyModel ) + ); + static DestFinfo scaleBufsAndRates( "scaleBufsAndRates", - "Args: voxel#, volRatio\n" - "Handles requests for runtime volume changes in the specified " - "voxel#, Used in adaptors changing spine vols.", - new OpFunc2< Stoich, unsigned int, double >( - &Stoich::scaleBufsAndRates ) - ); + "Args: voxel#, volRatio\n" + "Handles requests for runtime volume changes in the specified " + "voxel#, Used in adaptors changing spine vols.", + new OpFunc2< Stoich, unsigned int, double >( + &Stoich::scaleBufsAndRates ) + ); ////////////////////////////////////////////////////////////// // SrcFinfo Definitions @@ -276,6 +278,7 @@ Stoich::~Stoich() // Note that we cannot do the unZombify here, because it is too // prone to problems with the ordering of the delete operations // relative to the zombies. + for ( vector< RateTerm* >::iterator j = rates_.begin(); j != rates_.end(); ++j ) delete *j; @@ -283,14 +286,6 @@ Stoich::~Stoich() for ( vector< FuncTerm* >::iterator j = funcs_.begin(); j != funcs_.end(); ++j ) delete *j; - - /* - * Do NOT delete FuncTerms, they are just pointers stolen from - * the non-zombified objects. - for ( vector< FuncTerm* >::iterator i = funcs_.begin(); - i != funcs_.end(); ++i ) - delete *i; - */ } ////////////////////////////////////////////////////////////// @@ -947,8 +942,8 @@ void Stoich::resizeArrays() N_.setSize( totNumPools, totNumRates ); if ( kinterface_ ) kinterface_->setNumPools( totNumPools ); - if ( dinterface_ ) // Only set up var pools managed locally. - dinterface_->setNumPools( varPoolVec_.size() ); + if ( dinterface_ ) // Need to set both the numVar and numTot + dinterface_->setNumVarTotPools( varPoolVec_.size(), totNumPools ); } /// Calculate sizes of all arrays, and allocate them. @@ -1057,6 +1052,7 @@ void Stoich::installAndUnschedFunc( Id func, Id pool, double volScale ) static const Finfo* funcInputFinfo = varCinfo->findFinfo( "input" ); static const DestFinfo* df = dynamic_cast< const DestFinfo* >( funcInputFinfo ); assert( df ); + // Unsched Func func.element()->setTick( -2 ); // Disable with option to resurrect. @@ -1066,12 +1062,11 @@ void Stoich::installAndUnschedFunc( Id func, Id pool, double volScale ) Id ei( func.value() + 1 ); unsigned int numSrc = Field< unsigned int >::get( func, "numVars" ); + string _expr = Field::get( func, "expr" ); + vector< pair< Id, unsigned int> > srcPools; -#ifndef NDEBUG - unsigned int n = -#endif - ei.element()->getInputsWithTgtIndex( srcPools, df ); - assert( numSrc == n ); + unsigned int n = ei.element()->getInputsWithTgtIndex( srcPools, df ); + ASSERT_EQ( numSrc, n, "NumMsgVsYs Expr=" + _expr ); vector< unsigned int > poolIndex( numSrc, 0 ); for ( unsigned int i = 0; i < numSrc; ++i ) { @@ -1121,11 +1116,8 @@ void Stoich::installAndUnschedFuncRate( Id func, Id pool ) unsigned int numSrc = Field< unsigned int >::get( func, "numVars" ); vector< pair< Id, unsigned int > > srcPools; -#ifndef NDEBUG - unsigned int n = -#endif - ei.element()->getInputsWithTgtIndex( srcPools, df ); - assert( numSrc == n ); + unsigned int n = ei.element()->getInputsWithTgtIndex( srcPools, df ); + ASSERT_EQ( numSrc, n, "NumMsgXS" ); vector< unsigned int > poolIndex( numSrc, 0 ); for ( unsigned int i = 0; i < numSrc; ++i ) { @@ -2101,9 +2093,8 @@ const vector< Id >& Stoich::offSolverPoolMap( Id compt ) const // s is the array of pools, S_[meshIndex][0] void Stoich::updateFuncs( double* s, double t ) const { - for ( auto i = funcs_.cbegin(); i != funcs_.end(); ++i ) - if ( *i ) - (*i)->evalPool( s, t ); + for (auto i = funcs_.cbegin(); i != funcs_.end(); ++i) + if(*i) (*i)->evalPool( s, t ); } /** diff --git a/ksolve/Stoich.h b/ksolve/Stoich.h index 2b273613..0a0b56ef 100644 --- a/ksolve/Stoich.h +++ b/ksolve/Stoich.h @@ -46,6 +46,8 @@ * - Reinit. */ +class FuncTerm; + class Stoich { public: @@ -152,6 +154,7 @@ class Stoich * 16: Warning: No objects found on path */ int getStatus() const; + ////////////////////////////////////////////////////////////////// // Model traversal and building functions ////////////////////////////////////////////////////////////////// @@ -480,6 +483,7 @@ class Stoich ////////////////////////////////////////////////////////////////// static const unsigned int PoolIsNotOnSolver; static const Cinfo* initCinfo(); + private: /** * True if the stoich matrix is set up to handle only one-way diff --git a/ksolve/VoxelPools.cpp b/ksolve/VoxelPools.cpp index cf16e423..f28199d5 100644 --- a/ksolve/VoxelPools.cpp +++ b/ksolve/VoxelPools.cpp @@ -1,13 +1,15 @@ -/* -* This program is part of 'MOOSE', the -* Messaging Object Oriented Simulation Environment. -* Copyright (C) 2003-2010 Upinder S. Bhalla. and NCBS -* It is made available under the terms of the -* GNU Lesser General Public License version 2.1 -* See the file COPYING.LIB for the full notice. -*/ +/*** + * Description: Class VoxelPool. + * Authors: Upinder Bhalla , + * Dilawar Singh + * Organization: NCBS Bangalore + * License: GNU GPL3 + */ + +#include #include "../basecode/header.h" +#include "../basecode/SparseMatrix.h" #ifdef USE_GSL #include @@ -23,17 +25,16 @@ using namespace boost::numeric; #include "VoxelPools.h" #include "RateTerm.h" #include "FuncTerm.h" -#include "../basecode/SparseMatrix.h" #include "KinSparseMatrix.h" -#include "../mesh/VoxelJunction.h" #include "XferInfo.h" #include "ZombiePoolInterface.h" +#include "Ksolve.h" #include "Stoich.h" ////////////////////////////////////////////////////////////// // Class definitions -VoxelPools::VoxelPools() +VoxelPools::VoxelPools() : pLSODA(nullptr) { #ifdef USE_GSL driver_ = 0; @@ -62,6 +63,14 @@ void VoxelPools::reinit( double dt ) gsl_odeiv2_driver_reset( driver_ ); gsl_odeiv2_driver_reset_hstart( driver_, dt / 10.0 ); #endif + + // If method is LDODA create lSODA object and save the address of this as + // param (void*). + if( getMethod() == "lsoda" ) + { + pLSODA.reset(new LSODA()); + pLSODA->param = (void *) this; + } } void VoxelPools::setStoich( Stoich* s, const OdeSystem* ode ) @@ -82,108 +91,204 @@ void VoxelPools::setStoich( Stoich* s, const OdeSystem* ode ) gsl_odeiv2_driver_free( driver_ ); driver_ = gsl_odeiv2_driver_alloc_y_new( &sys_, ode->gslStep - , ode->initStepSize, ode->epsAbs, ode->epsRel - ); + , ode->initStepSize, ode->epsAbs, ode->epsRel); } #endif VoxelPoolsBase::reinit(); } +const string VoxelPools::getMethod( ) +{ + Ksolve* k = reinterpret_cast( stoichPtr_->getKsolve().eref().data() ); + return k->getMethod( ); +} + void VoxelPools::advance( const ProcInfo* p ) { double t = p->currTime - p->dt; + Ksolve* k = reinterpret_cast( stoichPtr_->getKsolve().eref().data() ); -#ifdef USE_GSL - int status = gsl_odeiv2_driver_apply( driver_, &t, p->currTime, varS()); - if ( status != GSL_SUCCESS ) + if( getMethod() == "lsoda" ) { - cout << "Error: VoxelPools::advance: GSL integration error at time " - << t << "\n"; - cout << "Error info: " << status << ", " << - gsl_strerror( status ) << endl; - if ( status == GSL_EMAXITER ) - cout << "Max number of steps exceeded\n"; - else if ( status == GSL_ENOPROG ) - cout << "Timestep has gotten too small\n"; - else if ( status == GSL_EBADFUNC ) - cout << "Internal error\n"; - assert( 0 ); - } + vector yout(size()+1); + pLSODA->lsoda_update( &VoxelPools::lsodaSys, size() + , Svec(), yout , &t + , p->currTime, &lsodaState, this + ); -#elif USE_BOOST_ODE + // Now update the y from yout. This is different thant normal GSL or + // BOOST based approach. + for (size_t i = 0; i < size(); i++) + varS()[i] = yout[i+1]; - /*----------------------------------------------------------------------------- - We need to call updateFuncs here (unlike in GSL solver) because there - is no way we can update const vector_type_& y in evalRatesUsingBoost - function. In gsl implmentation one could do it, because const_cast can - take away the constantness of double*. This probably makes the call bit - cleaner. - *-----------------------------------------------------------------------------*/ - stoichPtr_->updateFuncs( &Svec()[0], p->currTime ); - - /*----------------------------------------------------------------------------- - * Using integrate function works with with default stepper type. - * - * NOTICE to developer: - * If you are planning your own custom typdedef of stepper_type_ (see - * file BoostSystem.h), the you may run into troble. Have a look at this - * http://boostw.boost.org/doc/libs/1_56_0/boost/numeric/odeint/integrate/integrate.hpp - *----------------------------------------------------------------------------- - */ - - /** - * @brief Default step size for fixed size iterator. - * FIXME/TODO: I am not sure if this is a right value to pick by default. May be - * user should provide the stepping size when using fixed dt. This feature - * can be incredibly useful on large system. - */ - - // Variout stepper times are listed here: - // https://www.boost.org/doc/libs/1_68_0/libs/numeric/odeint/doc/html/boost_numeric_odeint/odeint_in_detail/steppers.html#boost_numeric_odeint.odeint_in_detail.steppers.explicit_steppers - - // Describe system to be used in boost solver calls. - auto sys = [this](const vector_type_& dy, vector_type_& dydt, const double t) - { - VoxelPools::evalRates(this, dy, dydt); - }; - - // This is usually the default method. It works well in practice. Tested - // with steady-state solver. Closest to GSL rk5 . - if( method_ == "rk5" || method_ == "gsl" || method_ == "boost" ) - odeint::integrate_adaptive( - make_dense_output( epsAbs_, epsRel_, odeint::runge_kutta_dopri5() ) - , sys, Svec(), p->currTime - p->dt, p->currTime, p->dt - ); - else if( method_ == "rk5a" || method_ == "adaptive" ) - odeint::integrate_adaptive( odeint::make_controlled( epsAbs_, epsRel_ ) - , sys, Svec(), p->currTime - p->dt, p->currTime, p->dt ); - else if( method_ == "rk2" ) - odeint::integrate_const( rk_midpoint_stepper_type_() - , sys, Svec(), p->currTime - p->dt, p->currTime, p->dt); - else if( method_ == "rk4" ) - odeint::integrate_const( rk4_stepper_type_() - , sys, Svec(), p->currTime - p->dt, p->currTime, p->dt ); - else if ("rk54" == method_ ) - odeint::integrate_const( rk_karp_stepper_type_() - , sys, Svec(), p->currTime - p->dt, p->currTime, p->dt); - else if ("rkck" == method_ ) - odeint::integrate_adaptive( odeint::make_controlled( epsAbs_, epsRel_ ) - , sys, Svec(), p->currTime - p->dt, p->currTime, p->dt); - else if( method_ == "rk8" ) - odeint::integrate_const( rk_felhberg_stepper_type_() - , sys, Svec(), p->currTime - p->dt, p->currTime, p->dt); - else if( method_ == "rk8a" ) - odeint::integrate_adaptive( rk_felhberg_stepper_type_() - , sys, Svec(), p->currTime - p->dt, p->currTime, p->dt); + if( lsodaState == 0 ) + { + cerr << "Error: VoxelPools::advance: LSODA integration error at time " + << t << "\n"; + assert(0); + } + } else { - cerr << "Ksolve: Unknow method " << method_ << ", using default!" << endl; - odeint::integrate_const( - make_dense_output( epsAbs_, epsRel_, odeint::runge_kutta_dopri5() ) - , sys, Svec(), p->currTime - p->dt, p->currTime, p->dt - ); + +#ifdef USE_GSL + int status = gsl_odeiv2_driver_apply( driver_, &t, p->currTime, varS()); + if ( status != GSL_SUCCESS ) + { + cerr << "Error: VoxelPools::advance: GSL integration error at time " + << t << "\n"; + cerr << "Error info: " << status << ", " << + gsl_strerror( status ) << endl; + if ( status == GSL_EMAXITER ) + cerr << "Max number of steps exceeded\n"; + else if ( status == GSL_ENOPROG ) + cerr << "Timestep has gotten too small\n"; + else if ( status == GSL_EBADFUNC ) + cerr << "Internal error\n"; + assert( 0 ); + } + +#elif USE_BOOST_ODE + // NOTE: Make sure to assing vp to BoostSys vp. In next call, it will be used by + // updateRates func. Unlike gsl call, we can't pass extra void* to gslFunc. + VoxelPools* vp = reinterpret_cast< VoxelPools* >( this ); + + /*----------------------------------------------------------------------------- +NOTE: 04/21/2016 11:31:42 AM + +We need to call updateFuncs here (unlike in GSL solver) because there +is no way we can update const vector_type_& y in evalRatesUsingBoost +function. In gsl implmentation one could do it, because const_cast can +take away the constantness of double*. This probably makes the call bit +cleaner. + *-----------------------------------------------------------------------------*/ + stoichPtr_->updateFuncs( &Svec()[0], p->currTime ); + + /*----------------------------------------------------------------------------- + * Using integrate function works with with default stepper type. + * + * NOTICE to developer: + * If you are planning your own custom typdedef of stepper_type_ (see + * file BoostSystem.h), the you may run into troble. Have a look at this + * http://boostw.boost.org/doc/libs/1_56_0/boost/numeric/odeint/integrate/integrate.hpp + * + * To make numerical results comparable with "gsl" solvers, + * by default, we pick adaptive step-size control. Use a suffix 'c' to + * force a constant step size. The numerical accuracy of constant step + * size solver is low. + * More details can be found here: + * https://www.boost.org/doc/libs/1_72_0/libs/numeric/odeint/doc/html/boost_numeric_odeint/odeint_in_detail/steppers.html + */ + + const double fixedDt = 0.1; + + if( method_ == "rk2" ) + odeint::integrate_const( rk_midpoint_stepper_type_() + , [this](const vector_type_& dy, vector_type_& dydt, const double t) { + VoxelPools::evalRates(this, dy, dydt ); + } + , Svec() + , p->currTime - p->dt, p->currTime, std::min( p->dt, fixedDt ) + ); + else if( method_ == "rk4c" ) + odeint::integrate_const( rk4_stepper_type_() + , [this](const vector_type_& dy, vector_type_& dydt, const double t) { + VoxelPools::evalRates(this, dy, dydt ); + } + , Svec() + , p->currTime - p->dt, p->currTime, std::min( p->dt, fixedDt ) + ); + else if( method_ == "rk5c") + odeint::integrate_const( rk_karp_stepper_type_() + , [this](const vector_type_& dy, vector_type_& dydt, const double t) { + VoxelPools::evalRates(this, dy, dydt ); + } + , Svec() + , p->currTime - p->dt, p->currTime, std::min( p->dt, fixedDt ) + ); + else if( method_ == "rk5ck" ) + odeint::integrate_adaptive( + odeint::make_controlled( epsAbs_, epsRel_ ) + , [this](const vector_type_& dy, vector_type_& dydt, const double t) { + VoxelPools::evalRates(this, dy, dydt ); + } + , Svec() + , p->currTime - p->dt + , p->currTime + , p->dt + ); + else if ("rk54c" == method_ ) + odeint::integrate_const( rk_karp_stepper_type_() + , [this](const vector_type_& dy, vector_type_& dydt, const double t) { + VoxelPools::evalRates(this, dy, dydt ); + } + , Svec() + , p->currTime - p->dt, p->currTime, std::min( p->dt, fixedDt ) + ); + else if ("rk54" == method_ ) + odeint::integrate_adaptive( + odeint::make_controlled( epsAbs_, epsRel_ ) + , [this](const vector_type_& dy, vector_type_& dydt, const double t) { + VoxelPools::evalRates(this, dy, dydt ); + } + , Svec() + , p->currTime - p->dt + , p->currTime + , p->dt + ); + else if ("rk5c" == method_ ) + odeint::integrate_const( rk_dopri_stepper_type_() + , [this](const vector_type_& dy, vector_type_& dydt, const double t) { + VoxelPools::evalRates(this, dy, dydt ); + } + , Svec() + , p->currTime - p->dt + , p->currTime + , std::min( p->dt, fixedDt ) + ); + else if ("rk5" == method_ || "gsl" == method_) + odeint::integrate_adaptive( + odeint::make_controlled( epsAbs_, epsRel_ ) + , [this](const vector_type_& dy, vector_type_& dydt, const double t) { + VoxelPools::evalRates(this, dy, dydt ); + } + , Svec() + , p->currTime - p->dt + , p->currTime + , p->dt + ); + else if( method_ == "rk8c" ) + odeint::integrate_const( rk_felhberg_stepper_type_() + , [this](const vector_type_& dy, vector_type_& dydt, const double t) { + VoxelPools::evalRates(this, dy, dydt ); + } + , Svec() + , p->currTime - p->dt, p->currTime, std::min( p->dt, fixedDt ) + ); + else if( method_ == "rk8" ) + odeint::integrate_adaptive( + odeint::make_controlled( epsAbs_, epsRel_ ) + , [this](const vector_type_& dy, vector_type_& dydt, const double t) { + VoxelPools::evalRates(this, dy, dydt ); + } + , Svec() + , p->currTime - p->dt + , p->currTime + , p->dt + ); + else + odeint::integrate_adaptive( + odeint::make_controlled( epsAbs_, epsRel_ ) + , [this](const vector_type_& dy, vector_type_& dydt, const double t) { + VoxelPools::evalRates(this, dy, dydt ); + } + , Svec() + , p->currTime - p->dt + , p->currTime + , p->dt + ); +#endif // USE_GSL } -#endif if ( !stoichPtr_->getAllowNegative() ) // clean out negatives { @@ -191,7 +296,7 @@ void VoxelPools::advance( const ProcInfo* p ) double* vs = varS(); for ( unsigned int i = 0; i < nv; ++i ) { - if ( signbit(vs[i]) ) + if ( std::signbit(vs[i]) ) vs[i] = 0.0; } } @@ -205,18 +310,14 @@ void VoxelPools::setInitDt( double dt ) } #ifdef USE_GSL -// static func. This goes into the Gsl solver. -int VoxelPools::gslFunc(double t, const double* y, double *dydt, void* params) +// static func. This is the function that goes into the Gsl solver. +int VoxelPools::gslFunc( double t, const double* y, double *dydt, void* params ) { VoxelPools* vp = reinterpret_cast< VoxelPools* >( params ); double* q = const_cast< double* >( y ); // Assign the func portion. vp->stoichPtr_->updateFuncs( q, t ); vp->updateRates( y, dydt ); -#ifdef USE_GSL return GSL_SUCCESS; -#else - return 0; -#endif } #elif USE_BOOST_ODE // NOT GSL @@ -226,7 +327,23 @@ void VoxelPools::evalRates( VoxelPools* vp, const vector_type_& y, vector_type_ vp->updateRates( &y[0], &dydt[0] ); } -#endif +#endif // USE_BOOST_ODE + +/* --------------------------------------------------------------------------*/ +/** + * @Synopsis Function to pass LSODA::lsoda_update function. Since it is + a * static function, we have to make sure void* param holds the value of + pointer * to VoxelPools. * * @Param t * @Param y * @Param dydt * @Param + params Address of VoxelPools as void*. */ +/* +----------------------------------------------------------------------------*/ +void VoxelPools::lsodaSys( double t, double* y, double* dydt, void* param) +{ + VoxelPools* vp = reinterpret_cast< VoxelPools* >( param ); + // Fill in the values. + vp->stoichPtr_->updateFuncs( y, t ); + vp->updateRates( y, dydt ); +} /////////////////////////////////////////////////////////////////////// // Here are the internal reaction rate calculation functions @@ -239,10 +356,12 @@ void VoxelPools::updateAllRateTerms( const vector< RateTerm* >& rates, for ( unsigned int i = 0; i < rates_.size(); ++i ) delete( rates_[i] ); - rates_.resize( rates.size() ); + rates_.resize(rates.size()); for ( unsigned int i = 0; i < numCoreRates; ++i ) + { rates_[i] = rates[i]->copyWithVolScaling( getVolume(), 1, 1 ); + } for ( unsigned int i = numCoreRates; i < rates.size(); ++i ) { @@ -278,22 +397,20 @@ void VoxelPools::updateRates( const double* s, double* yprime ) const vector< double > v( N.nColumns(), 0.0 ); vector< double >::iterator j = v.begin(); // totVar should include proxyPools only if this voxel uses them - unsigned int totVar = stoichPtr_->getNumVarPools() + - stoichPtr_->getNumProxyPools(); + unsigned int totVar = stoichPtr_->getNumVarPools() + stoichPtr_->getNumProxyPools(); // totVar should include proxyPools if this voxel does not use them unsigned int totInvar = stoichPtr_->getNumBufPools(); assert( N.nColumns() == 0 || N.nRows() == stoichPtr_->getNumAllPools() ); assert( N.nColumns() == rates_.size() ); - for ( vector< RateTerm* >::const_iterator - i = rates_.begin(); i != rates_.end(); i++) - { + for ( auto i = rates_.cbegin(); i != rates_.end(); i++) *j++ = (**i)( s ); - assert( !std::isnan( *( j-1 ) ) ); - } - for (unsigned int i = 0; i < totVar; ++i) - *yprime++ = N.computeRowRate( i, v ); + { + auto rate = N.computeRowRate( i, v ); + assert(! std::isnan(rate)); + *yprime++ = rate; + } for (unsigned int i = 0; i < totInvar ; ++i) *yprime++ = 0.0; } @@ -303,21 +420,21 @@ void VoxelPools::updateRates( const double* s, double* yprime ) const * This is a utility function for programs like SteadyState that need * to analyze velocity. */ -void VoxelPools::updateReacVelocities( - const double* s, vector< double >& v ) const +void VoxelPools::updateReacVelocities(const double* s, vector< double >& v) const { const KinSparseMatrix& N = stoichPtr_->getStoichiometryMatrix(); assert( N.nColumns() == rates_.size() ); - vector< RateTerm* >::const_iterator i; v.clear(); v.resize( rates_.size(), 0.0 ); + + vector< RateTerm* >::const_iterator i; vector< double >::iterator j = v.begin(); for ( i = rates_.begin(); i != rates_.end(); i++) { *j++ = (**i)( s ); - assert( !std::isnan( *( j-1 ) ) ); + assert(! std::isnan(*(j-1))); } } diff --git a/ksolve/VoxelPools.h b/ksolve/VoxelPools.h index 04c5bb8c..4c79db7f 100644 --- a/ksolve/VoxelPools.h +++ b/ksolve/VoxelPools.h @@ -12,12 +12,12 @@ #include "OdeSystem.h" #include "VoxelPoolsBase.h" +#include "external/libsoda/LSODA.h" #ifdef USE_BOOST_ODE #include "BoostSys.h" #endif - class Stoich; class ProcInfo; @@ -45,18 +45,23 @@ class VoxelPools: public VoxelPoolsBase const Stoich* getStoich( ); + const string getMethod( ); + /// Do the numerical integration. Advance the simulation. void advance( const ProcInfo* p ); /// Set initial timestep to use by the solver. void setInitDt( double dt ); -#ifdef USE_GSL /* ----- not USE_BOOST_ODE ----- */ +#ifdef USE_GSL /* ----- not USE_BOOST ----- */ static int gslFunc( double t, const double* y, double *dydt, void* params); #elif USE_BOOST_ODE static void evalRates( VoxelPools* vp, const vector_type_& y, vector_type_& dydt ); #endif /* ----- not USE_BOOST_ODE ----- */ + // System of LSODA. + static void lsodaSys( double t, double* y, double* dydt, void* params); + ////////////////////////////////////////////////////////////////// // Rate manipulation and calculation functions ////////////////////////////////////////////////////////////////// @@ -87,13 +92,17 @@ class VoxelPools: public VoxelPoolsBase * This is a utility function for programs like SteadyState that * need to analyze velocity. */ - void updateReacVelocities( - const double* s, vector< double >& v ) const; + void updateReacVelocities( const double* s, vector< double >& v ) const; /// Used for debugging. void print() const; + private: + std::shared_ptr pLSODA; + LSODA_ODE_SYSTEM_TYPE lsodaSystem; + int lsodaState = 1; + #ifdef USE_GSL gsl_odeiv2_driver* driver_; gsl_odeiv2_system sys_; diff --git a/ksolve/VoxelPoolsBase.cpp b/ksolve/VoxelPoolsBase.cpp index 6a35f477..cbcff140 100644 --- a/ksolve/VoxelPoolsBase.cpp +++ b/ksolve/VoxelPoolsBase.cpp @@ -107,8 +107,7 @@ void VoxelPoolsBase::setVolumeAndDependencies( double vol ) // a subsequent call via Ksolve or Stoich. } -void VoxelPoolsBase::scaleVolsBufsRates( - double ratio, const Stoich* stoichPtr ) +void VoxelPoolsBase::scaleVolsBufsRates(double ratio, const Stoich* stoichPtr) { volume_ *= ratio; // Scale vol for ( vector< double >::iterator @@ -132,8 +131,10 @@ void VoxelPoolsBase::scaleVolsBufsRates( unsigned int numCoreRates = stoichPtr->getNumCoreRates(); const vector< RateTerm* >& rates = stoichPtr->getRateTerms(); rates_.resize( rates.size() ); + for ( unsigned int i = 0; i < numCoreRates; ++i ) rates_[i] = rates[i]->copyWithVolScaling( getVolume(), 1, 1 ); + for ( unsigned int i = numCoreRates; i < rates.size(); ++i ) { rates_[i] = rates[i]->copyWithVolScaling( getVolume(), diff --git a/ksolve/ZombieBufPool.cpp b/ksolve/ZombieBufPool.cpp index a0fb2df5..9c4e57c5 100644 --- a/ksolve/ZombieBufPool.cpp +++ b/ksolve/ZombieBufPool.cpp @@ -19,20 +19,20 @@ // Entirely derived from ZombiePool. Only the zombification routines differ. const Cinfo* ZombieBufPool::initCinfo() { - ////////////////////////////////////////////////////////////// - // Field Definitions: use virtual functions to deal with, the - // moose definitions are inherited. - ////////////////////////////////////////////////////////////// - static Dinfo< ZombieBufPool > dinfo( true ); - static Cinfo zombieBufPoolCinfo ( - "ZombieBufPool", - ZombiePool::initCinfo(), - 0, - 0, - &dinfo - ); + ////////////////////////////////////////////////////////////// + // Field Definitions: use virtual functions to deal with, the + // moose definitions are inherited. + ////////////////////////////////////////////////////////////// + static Dinfo< ZombieBufPool > dinfo( true ); + static Cinfo zombieBufPoolCinfo ( + "ZombieBufPool", + ZombiePool::initCinfo(), + 0, + 0, + &dinfo + ); - return &zombieBufPoolCinfo; + return &zombieBufPoolCinfo; } ////////////////////////////////////////////////////////////// @@ -52,27 +52,27 @@ ZombieBufPool::~ZombieBufPool() void ZombieBufPool::vSetN( const Eref& e, double v ) { - ZombiePool::vSetN( e, v ); - ZombiePool::vSetNinit( e, v ); + ZombiePool::vSetN( e, v ); + ZombiePool::vSetNinit( e, v ); } void ZombieBufPool::vSetNinit( const Eref& e, double v ) { - vSetN( e, v ); + vSetN( e, v ); } void ZombieBufPool::vSetConc( const Eref& e, double conc ) { - double n = NA * conc * lookupVolumeFromMesh( e ); - vSetN( e, n ); + double n = NA * conc * lookupVolumeFromMesh( e ); + vSetN( e, n ); } void ZombieBufPool::vSetConcInit( const Eref& e, double conc ) { - vSetConc( e, conc ); + vSetConc( e, conc ); } bool ZombieBufPool::vGetIsBuffered( const Eref& e ) const { - return true; + return true; } diff --git a/ksolve/ZombieBufPool.h b/ksolve/ZombieBufPool.h index a00344e3..dec378f0 100644 --- a/ksolve/ZombieBufPool.h +++ b/ksolve/ZombieBufPool.h @@ -12,19 +12,19 @@ class ZombieBufPool: public ZombiePool { - public: - ZombieBufPool(); - ~ZombieBufPool(); +public: + ZombieBufPool(); + ~ZombieBufPool(); - /// The 'get' functions are simply inherited from ZombiePool - void vSetN( const Eref& e, double v ); - void vSetNinit( const Eref& e, double v ); - void vSetConc( const Eref& e, double v ); - void vSetConcInit( const Eref& e, double v ); - bool vGetIsBuffered( const Eref& e ) const; + /// The 'get' functions are simply inherited from ZombiePool + void vSetN( const Eref& e, double v ); + void vSetNinit( const Eref& e, double v ); + void vSetConc( const Eref& e, double v ); + void vSetConcInit( const Eref& e, double v ); + bool vGetIsBuffered( const Eref& e ) const; - static const Cinfo* initCinfo(); - private: + static const Cinfo* initCinfo(); +private: }; #endif // _ZOMBIE_BUF_POOL_H diff --git a/ksolve/ZombieFunction.cpp b/ksolve/ZombieFunction.cpp index e7b5e9ac..fccab992 100644 --- a/ksolve/ZombieFunction.cpp +++ b/ksolve/ZombieFunction.cpp @@ -30,72 +30,75 @@ const Cinfo* ZombieFunction::initCinfo() { - ////////////////////////////////////////////////////////////// - // Field Definitions: mostly inherited from Function - ////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////// - // MsgDest Definitions: All inherited from Function - ////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////// - // SrcFinfo Definitions: All inherited from Function - ////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////// - // SharedMsg Definitions: Override Function - ////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////// + // Field Definitions: mostly inherited from Function + ////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////// + // MsgDest Definitions: All inherited from Function + ////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////// + // SrcFinfo Definitions: All inherited from Function + ////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////// + // SharedMsg Definitions: Override Function + ////////////////////////////////////////////////////////////// + static DestFinfo process( "process", - "Handles process call, updates internal time stamp.", - new ProcOpFunc< ZombieFunction >( &ZombieFunction::process) ); + "Handles process call, updates internal time stamp.", + new ProcOpFunc< ZombieFunction >( &ZombieFunction::process) ); + static DestFinfo reinit( "reinit", - "Handles reinit call.", - new ProcOpFunc< ZombieFunction >( &ZombieFunction::reinit ) ); + "Handles reinit call.", + new ProcOpFunc< ZombieFunction >( &ZombieFunction::reinit ) ); + static Finfo* processShared[] = - { - &process, &reinit - }; + { + &process, &reinit + }; static SharedFinfo proc( "proc", - "This is a shared message to receive Process messages " - "from the scheduler objects." - "The first entry in the shared msg is a MsgDest " - "for the Process operation. It has a single argument, " - "ProcInfo, which holds lots of information about current " - "time, thread, dt and so on. The second entry is a MsgDest " - "for the Reinit operation. It also uses ProcInfo. ", - processShared, sizeof( processShared ) / sizeof( Finfo* ) - ); - - // Note that here the isOneZombie_ flag on the Dinfo constructor is - // true. This means that the duplicate and copy operations only make - // one copy, regardless of how big the array of zombie pools. - // The assumption is that each Id has a single pool, which can be - // present in many voxels. + "This is a shared message to receive Process messages " + "from the scheduler objects." + "The first entry in the shared msg is a MsgDest " + "for the Process operation. It has a single argument, " + "ProcInfo, which holds lots of information about current " + "time, thread, dt and so on. The second entry is a MsgDest " + "for the Reinit operation. It also uses ProcInfo. ", + processShared, sizeof( processShared ) / sizeof( Finfo* ) + ); + + // Note that here the isOneZombie_ flag on the Dinfo constructor is + // true. This means that the duplicate and copy operations only make + // one copy, regardless of how big the array of zombie pools. + // The assumption is that each Id has a single pool, which can be + // present in many voxels. static Finfo *functionFinfos[] = - { - &proc, - }; + { + &proc, + }; static string doc[] = - { - "Name", "ZombieFunction", - "Author", "Upi Bhalla", - "Description", - "ZombieFunction: Takes over Function, which is a general " - "purpose function calculator using real numbers." - }; - - static Dinfo< ZombieFunction > dinfo; - static Cinfo zombieFunctionCinfo ( - "ZombieFunction", - Function::initCinfo(), - functionFinfos, - sizeof(functionFinfos) / sizeof(Finfo*), - &dinfo, + { + "Name", "ZombieFunction", + "Author", "Upi Bhalla", + "Description", + "ZombieFunction: Takes over Function, which is a general " + "purpose function calculator using real numbers." + }; + + static Dinfo< ZombieFunction > dinfo; + static Cinfo zombieFunctionCinfo ( + "ZombieFunction", + Function::initCinfo(), + functionFinfos, + sizeof(functionFinfos) / sizeof(Finfo*), + &dinfo, doc, - sizeof(doc)/sizeof(string) - ); + sizeof(doc)/sizeof(string) + ); - return &zombieFunctionCinfo; + return &zombieFunctionCinfo; } @@ -117,7 +120,7 @@ ZombieFunction::~ZombieFunction() ////////////////////////////////////////////////////////////// void ZombieFunction::process(const Eref &e, ProcPtr p) { - _t = p->currTime; + t_ = p->currTime; } void ZombieFunction::reinit(const Eref &e, ProcPtr p) @@ -127,17 +130,20 @@ void ZombieFunction::reinit(const Eref &e, ProcPtr p) // Field Definitions ////////////////////////////////////////////////////////////// -void ZombieFunction::innerSetExpr( const Eref& e, string v ) +void ZombieFunction::setExpr( const Eref& e, string v ) { - Function::innerSetExpr( e, v ); - if ( _stoich ) { - Stoich* s = reinterpret_cast< Stoich* >( _stoich ); - s->setFunctionExpr( e, v ); - } else { - // I had this warning here but it is triggered needlessly when we - // do an assignment of the Zombie function. So removed. - // cout << "Warning: ZombieFunction::setExpr: Stoich not set.\n"; - } + // Function::setExpr( e, v ); + if ( stoich_ ) + { + Stoich* s = reinterpret_cast< Stoich* >( stoich_ ); + s->setFunctionExpr( e, v ); + } + else + { + // I had this warning here but it is triggered needlessly when we + // do an assignment of the Zombie function. So removed. + // cout << "Warning: ZombieFunction::setExpr: Stoich not set.\n"; + } } ////////////////////////////////////////////////////////////// @@ -146,73 +152,80 @@ void ZombieFunction::innerSetExpr( const Eref& e, string v ) void ZombieFunction::setSolver( Id ksolve, Id dsolve ) { - if ( ksolve.element()->cinfo()->isA( "Ksolve" ) || - ksolve.element()->cinfo()->isA( "Gsolve" ) ) { - Id sid = Field< Id >::get( ksolve, "stoich" ); - _stoich = ObjId( sid, 0 ).data(); - if ( _stoich == 0 ) - cout << "Warning:ZombieFunction::setSolver: Empty Stoich on Ksolve" << ksolve.path() << endl; - } else if ( ksolve == Id() ) { - _stoich = 0; - } else { - cout << "Warning:ZombieFunction::setSolver: solver class " << - ksolve.element()->cinfo()->name() << - " not known.\nShould be Ksolve or Gsolve\n"; - _stoich = 0; - } - - /* - if ( dsolve.element()->cinfo()->isA( "Dsolve" ) ) { - dsolve_= ObjId( dsolve, 0 ).data(); - } else if ( dsolve == Id() ) { - dsolve_ = 0; - } else { - cout << "Warning:ZombieFunction::vSetSolver: solver class " << - dsolve.element()->cinfo()->name() << - " not known.\nShould be Dsolve\n"; - dsolve_ = 0; - } - */ + if ( ksolve.element()->cinfo()->isA( "Ksolve" ) || + ksolve.element()->cinfo()->isA( "Gsolve" ) ) + { + Id sid = Field< Id >::get( ksolve, "stoich" ); + stoich_ = ObjId( sid, 0 ).data(); + if ( stoich_ == 0 ) + cout << "Warning:ZombieFunction::setSolver: Empty Stoich on Ksolve" << ksolve.path() << endl; + } + else if ( ksolve == Id() ) + { + stoich_ = 0; + } + else + { + cout << "Warning:ZombieFunction::setSolver: solver class " << + ksolve.element()->cinfo()->name() << + " not known.\nShould be Ksolve or Gsolve\n"; + stoich_ = 0; + } + + /* + if ( dsolve.element()->cinfo()->isA( "Dsolve" ) ) { + dsolve_= ObjId( dsolve, 0 ).data(); + } else if ( dsolve == Id() ) { + dsolve_ = 0; + } else { + cout << "Warning:ZombieFunction::vSetSolver: solver class " << + dsolve.element()->cinfo()->name() << + " not known.\nShould be Dsolve\n"; + dsolve_ = 0; + } + */ } void ZombieFunction::zombify( Element* orig, const Cinfo* zClass, - Id ksolve, Id dsolve ) + Id ksolve, Id dsolve ) { - //cout << "ZombieFunction::zombify: " << orig->id().path() << endl; - if ( orig->cinfo() == zClass ) - return; - // unsigned int start = orig->localDataStart(); - unsigned int num = orig->numLocalData(); - if ( num == 0 ) - return; - if ( num > 1 ) - cout << "ZombieFunction::zombify: Warning: ZombieFunction doesn't\n" - "handle volumes yet. Proceeding without this.\n"; - - Function* f = reinterpret_cast< Function *>( Eref( orig, 0 ).data() ); - Function temp = *f; - orig->zombieSwap( zClass ); - if ( zClass == ZombieFunction::initCinfo() ) { // call SetSolver - ZombieFunction* zf = reinterpret_cast< ZombieFunction *>( - Eref( orig, 0 ).data() ); - *zf = *static_cast< ZombieFunction* >(&temp); - zf->setSolver( ksolve, dsolve ); - } else { - Function* nf = - reinterpret_cast< Function *>(Eref( orig, 0 ).data()); - *nf = temp; - } - - /* - // We can swap the class because the class data is identical, just - // the moose expr and process handlers are different. - if ( orig->cinfo() == ZombieFunction::initCinfo() ) { // unzombify - orig->replaceCinfo( Function::initCinfo() ); - } else { // zombify - orig->replaceCinfo( ZombieFunction::initCinfo() ); - ZombieFunction* zf = reinterpret_cast< ZombieFunction *>( - Eref( orig, 0 ).data() ); - zf->setSolver( ksolve, dsolve ); - } - */ + //cout << "ZombieFunction::zombify: " << orig->id().path() << endl; + if ( orig->cinfo() == zClass ) + return; + // unsigned int start = orig->localDataStart(); + unsigned int num = orig->numLocalData(); + if ( num == 0 ) + return; + if ( num > 1 ) + cout << "ZombieFunction::zombify: Warning: ZombieFunction doesn't\n" + "handle volumes yet. Proceeding without this.\n"; + + Function* f = reinterpret_cast< Function *>( Eref( orig, 0 ).data() ); + Function temp = *f; + orig->zombieSwap( zClass ); + if ( zClass == ZombieFunction::initCinfo() ) // call SetSolver + { + ZombieFunction* zf = reinterpret_cast(Eref( orig, 0 ).data() ); + *zf = *static_cast< ZombieFunction* >(&temp); + zf->setSolver( ksolve, dsolve ); + } + else + { + Function* nf = + reinterpret_cast< Function *>(Eref( orig, 0 ).data()); + *nf = temp; + } + + /* + // We can swap the class because the class data is identical, just + // the moose expr and process handlers are different. + if ( orig->cinfo() == ZombieFunction::initCinfo() ) { // unzombify + orig->replaceCinfo( Function::initCinfo() ); + } else { // zombify + orig->replaceCinfo( ZombieFunction::initCinfo() ); + ZombieFunction* zf = reinterpret_cast< ZombieFunction *>( + Eref( orig, 0 ).data() ); + zf->setSolver( ksolve, dsolve ); + } + */ } diff --git a/ksolve/ZombieFunction.h b/ksolve/ZombieFunction.h index bd1546a5..53a83640 100644 --- a/ksolve/ZombieFunction.h +++ b/ksolve/ZombieFunction.h @@ -7,37 +7,39 @@ ** See the file COPYING.LIB for the full notice. **********************************************************************/ -#ifndef _ZOMBIE_FUNCTION_H -#define _ZOMBIE_FUNCTION_H +#ifndef ZOMBIE_FUNCTION_H_ +#define ZOMBIE_FUNCTION_H_ class ZombieFunction: public Function { - public: - ZombieFunction(); - ~ZombieFunction(); +public: + ZombieFunction(); + ~ZombieFunction(); - ////////////////////////////////////////////////////////////////// - // Field assignment stuff - ////////////////////////////////////////////////////////////////// - void innerSetExpr( const Eref& e, string val ); + ////////////////////////////////////////////////////////////////// + // Field assignment stuff + ////////////////////////////////////////////////////////////////// + void setExpr( const Eref& e, string val ); - ////////////////////////////////////////////////////////////////// - // Dest funcs - ////////////////////////////////////////////////////////////////// - void process(const Eref &e, ProcPtr p); - void reinit(const Eref &e, ProcPtr p); + ////////////////////////////////////////////////////////////////// + // Dest funcs + ////////////////////////////////////////////////////////////////// + void process(const Eref &e, ProcPtr p); + void reinit(const Eref &e, ProcPtr p); - ////////////////////////////////////////////////////////////////// - // utility funcs - ////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////// + // utility funcs + ////////////////////////////////////////////////////////////////// - void setSolver( Id solver, Id orig ); + void setSolver( Id solver, Id orig ); - static void zombify( Element* orig, const Cinfo* zClass, - Id ksolve, Id dsolve ); + static void zombify( Element* orig, const Cinfo* zClass, + Id ksolve, Id dsolve ); + + static const Cinfo* initCinfo(); + +private: - static const Cinfo* initCinfo(); - private: }; -#endif // _ZOMBIE_FUNCTION_H +#endif // ZOMBIE_FUNCTION_H_ diff --git a/ksolve/ZombiePool.cpp b/ksolve/ZombiePool.cpp index b1e3af86..c2ce8aec 100644 --- a/ksolve/ZombiePool.cpp +++ b/ksolve/ZombiePool.cpp @@ -20,34 +20,34 @@ const Cinfo* ZombiePool::initCinfo() { - ////////////////////////////////////////////////////////////// - // Field Definitions: All inherited from PoolBase - ////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////// - // MsgDest Definitions: All inherited from PoolBase - ////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////// - // SrcFinfo Definitions: All inherited from PoolBase - ////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////// - // SharedMsg Definitions: All inherited from PoolBase - ////////////////////////////////////////////////////////////// - - // Note that here the isOneZombie_ flag on the Dinfo constructor is - // true. This means that the duplicate and copy operations only make - // one copy, regardless of how big the array of zombie pools. - // The assumption is that each Id has a single pool, which can be - // present in many voxels. - static Dinfo< ZombiePool > dinfo( true ); - static Cinfo zombiePoolCinfo ( - "ZombiePool", - PoolBase::initCinfo(), - 0, - 0, - &dinfo - ); - - return &zombiePoolCinfo; + ////////////////////////////////////////////////////////////// + // Field Definitions: All inherited from PoolBase + ////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////// + // MsgDest Definitions: All inherited from PoolBase + ////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////// + // SrcFinfo Definitions: All inherited from PoolBase + ////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////// + // SharedMsg Definitions: All inherited from PoolBase + ////////////////////////////////////////////////////////////// + + // Note that here the isOneZombie_ flag on the Dinfo constructor is + // true. This means that the duplicate and copy operations only make + // one copy, regardless of how big the array of zombie pools. + // The assumption is that each Id has a single pool, which can be + // present in many voxels. + static Dinfo< ZombiePool > dinfo( true ); + static Cinfo zombiePoolCinfo ( + "ZombiePool", + PoolBase::initCinfo(), + 0, + 0, + &dinfo + ); + + return &zombiePoolCinfo; } @@ -59,7 +59,7 @@ const Cinfo* ZombiePool::initCinfo() static const Cinfo* zombiePoolCinfo = ZombiePool::initCinfo(); ZombiePool::ZombiePool() - : dsolve_( 0 ), ksolve_( 0 ), diffConst_( 1e-12 ), motorConst_( 0.0 ) + : dsolve_(nullptr), ksolve_(nullptr), diffConst_(1e-12), motorConst_(0.0) {;} ZombiePool::~ZombiePool() @@ -75,55 +75,55 @@ ZombiePool::~ZombiePool() void ZombiePool::vSetN( const Eref& e, double v ) { - if ( ksolve_ ) - ksolve_->setN( e, v ); - if ( dsolve_ ) - dsolve_->setN( e, v ); - // S_[ e.index().value() ][ convertIdToPoolIndex( e.id() ) ] = v; + if(ksolve_) + ksolve_->setN(e, v); + if(dsolve_) + dsolve_->setN(e, v); + // S_[ e.index().value() ][ convertIdToPoolIndex( e.id() ) ] = v; } double ZombiePool::vGetN( const Eref& e ) const { - if ( ksolve_ != 0 ) - return ksolve_->getN( e ); - else if ( dsolve_ != 0 ) - return dsolve_->getN( e ); - return 0.0; + if(ksolve_) + return ksolve_->getN( e ); + else if(dsolve_) + return dsolve_->getN( e ); + return 0.0; } void ZombiePool::vSetNinit( const Eref& e, double v ) { - if ( ksolve_ ) - ksolve_->setNinit( e, v ); - if ( dsolve_ ) - dsolve_->setNinit( e, v ); + if (ksolve_) + ksolve_->setNinit( e, v ); + if (dsolve_) + dsolve_->setNinit( e, v ); } double ZombiePool::vGetNinit( const Eref& e ) const { - if ( ksolve_ != 0 ) - return ksolve_->getNinit( e ); - else if ( dsolve_ != 0 ) - return dsolve_->getNinit( e ); - return 0.0; + if ( ksolve_ ) + return ksolve_->getNinit( e ); + else if ( dsolve_ ) + return dsolve_->getNinit( e ); + return 0.0; } void ZombiePool::vSetConc( const Eref& e, double conc ) { - // unsigned int pool = convertIdToPoolIndex( e.id() ); - double n = NA * conc * lookupVolumeFromMesh( e ); - vSetN( e, n ); + // unsigned int pool = convertIdToPoolIndex( e.id() ); + double n = NA * conc * lookupVolumeFromMesh( e ); + vSetN( e, n ); } double ZombiePool::vGetConc( const Eref& e ) const { - return vGetN( e ) / ( NA * lookupVolumeFromMesh( e ) ); + return vGetN( e ) / ( NA * lookupVolumeFromMesh( e ) ); } void ZombiePool::vSetConcInit( const Eref& e, double conc ) { - double n = NA * conc * lookupVolumeFromMesh( e ); - vSetNinit( e, n ); + double n = NA * conc * lookupVolumeFromMesh( e ); + vSetNinit( e, n ); } // Do not get concInit from ZombiePool, the PoolBase handles it. @@ -132,56 +132,56 @@ void ZombiePool::vSetConcInit( const Eref& e, double conc ) // the same. Here is a reimplementation. double ZombiePool::vGetConcInit( const Eref& e ) const { - return vGetNinit( e ) / (NA * lookupVolumeFromMesh( e ) ); + return vGetNinit( e ) / (NA * lookupVolumeFromMesh( e ) ); } void ZombiePool::vSetDiffConst( const Eref& e, double v ) { - diffConst_ = v; - if ( dsolve_ ) - dsolve_->setDiffConst( e, v ); + diffConst_ = v; + if ( dsolve_ ) + dsolve_->setDiffConst( e, v ); } double ZombiePool::vGetDiffConst( const Eref& e ) const { - return diffConst_; + return diffConst_; } double ZombiePool::vGetMotorConst( const Eref& e ) const { - return motorConst_; + return motorConst_; } void ZombiePool::vSetMotorConst( const Eref& e, double v ) { - motorConst_ = v; - if ( dsolve_ ) - dsolve_->setMotorConst( e, v ); + motorConst_ = v; + if ( dsolve_ ) + dsolve_->setMotorConst( e, v ); } void ZombiePool::vSetSpecies( const Eref& e, unsigned int v ) { - ; + ; } unsigned int ZombiePool::vGetSpecies( const Eref& e ) const { - return 0; + return 0; } void ZombiePool::vSetVolume( const Eref& e, double v ) { - assert( 0 ); // Illegal op, but should handle more gracefully. + assert( 0 ); // Illegal op, but should handle more gracefully. } double ZombiePool::vGetVolume( const Eref& e ) const { - return lookupVolumeFromMesh( e ); + return lookupVolumeFromMesh( e ); } bool ZombiePool::vGetIsBuffered( const Eref& e ) const { - return false; + return false; } ////////////////////////////////////////////////////////////// @@ -190,31 +190,41 @@ bool ZombiePool::vGetIsBuffered( const Eref& e ) const void ZombiePool::vSetSolver( Id ksolve, Id dsolve ) { - // Nasty unsafe typecast. I would have preferred to pass in a - // safely typed pointer but that would have exposed a low-level - // class for the ZombiePoolInterface. - if ( ksolve.element()->cinfo()->isA( "Ksolve" ) || - ksolve.element()->cinfo()->isA( "Gsolve" ) ) { - ksolve_= reinterpret_cast< ZombiePoolInterface *>( - ObjId( ksolve, 0 ).data() ); - } else if ( ksolve == Id() ) { - ksolve_ = 0; - } else { - cout << "Warning:ZombiePool::vSetSolver: solver class " << - ksolve.element()->cinfo()->name() << - " not known.\nShould be Ksolve or Gsolve\n"; - ksolve_ = 0; - } - - if ( dsolve.element()->cinfo()->isA( "Dsolve" ) ) { - dsolve_= reinterpret_cast< ZombiePoolInterface *>( - ObjId( dsolve, 0 ).data() ); - } else if ( dsolve == Id() ) { - dsolve_ = 0; - } else { - cout << "Warning:ZombiePool::vSetSolver: solver class " << - dsolve.element()->cinfo()->name() << - " not known.\nShould be Dsolve\n"; - dsolve_ = 0; - } + // Nasty unsafe typecast. I would have preferred to pass in a + // safely typed pointer but that would have exposed a low-level + // class for the ZombiePoolInterface. + if ( ksolve.element()->cinfo()->isA( "Ksolve" ) || + ksolve.element()->cinfo()->isA( "Gsolve" ) ) + { + ksolve_= reinterpret_cast< ZombiePoolInterface *>( + ObjId( ksolve, 0 ).data() ); + } + else if ( ksolve == Id() ) + { + ksolve_ = nullptr; + } + else + { + cout << "Warning:ZombiePool::vSetSolver: solver class " << + ksolve.element()->cinfo()->name() << + " not known.\nShould be Ksolve or Gsolve\n"; + ksolve_ = nullptr; + } + + if ( dsolve.element()->cinfo()->isA( "Dsolve" ) ) + { + dsolve_= reinterpret_cast< ZombiePoolInterface *>( + ObjId( dsolve, 0 ).data() ); + } + else if ( dsolve == Id() ) + { + dsolve_ = nullptr; + } + else + { + cout << "Warning:ZombiePool::vSetSolver: solver class " << + dsolve.element()->cinfo()->name() << + " not known.\nShould be Dsolve\n"; + dsolve_ = nullptr; + } } diff --git a/ksolve/ZombiePool.h b/ksolve/ZombiePool.h index 147823fc..5dd3b1c4 100644 --- a/ksolve/ZombiePool.h +++ b/ksolve/ZombiePool.h @@ -16,61 +16,61 @@ */ class ZombiePool: public PoolBase { - public: - ZombiePool(); - ~ZombiePool(); +public: + ZombiePool(); + ~ZombiePool(); - ////////////////////////////////////////////////////////////////// - // Field assignment stuff - ////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////// + // Field assignment stuff + ////////////////////////////////////////////////////////////////// - void vSetN( const Eref& e, double v ); - double vGetN( const Eref& e ) const; - void vSetNinit( const Eref& e, double v ); - double vGetNinit( const Eref& e ) const; - void vSetDiffConst( const Eref& e, double v ); - double vGetDiffConst( const Eref& e ) const; + void vSetN( const Eref& e, double v ); + double vGetN( const Eref& e ) const; + void vSetNinit( const Eref& e, double v ); + double vGetNinit( const Eref& e ) const; + void vSetDiffConst( const Eref& e, double v ); + double vGetDiffConst( const Eref& e ) const; - void vSetConc( const Eref& e, double v ); - double vGetConc( const Eref& e ) const; - void vSetConcInit( const Eref& e, double v ); - double vGetConcInit( const Eref& e ) const; + void vSetConc( const Eref& e, double v ); + double vGetConc( const Eref& e ) const; + void vSetConcInit( const Eref& e, double v ); + double vGetConcInit( const Eref& e ) const; - void vSetVolume( const Eref& e, double v ); - double vGetVolume( const Eref& e ) const; + void vSetVolume( const Eref& e, double v ); + double vGetVolume( const Eref& e ) const; - void vSetSpecies( const Eref& e, unsigned int v ); - unsigned int vGetSpecies( const Eref& e ) const; + void vSetSpecies( const Eref& e, unsigned int v ); + unsigned int vGetSpecies( const Eref& e ) const; - void vSetSolver( Id ksolve, Id dsolve ); + void vSetSolver( Id ksolve, Id dsolve ); - void vSetMotorConst( const Eref& e, double v ); - double vGetMotorConst( const Eref& e ) const; - bool vGetIsBuffered( const Eref& e ) const; - ////////////////////////////////////////////////////////////////// - // Dest funcs - ////////////////////////////////////////////////////////////////// + void vSetMotorConst( const Eref& e, double v ); + double vGetMotorConst( const Eref& e ) const; + bool vGetIsBuffered( const Eref& e ) const; + ////////////////////////////////////////////////////////////////// + // Dest funcs + ////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////// - // utility funcs - ////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////// + // utility funcs + ////////////////////////////////////////////////////////////////// - static const Cinfo* initCinfo(); - protected: - /** - * The ZombiePoolInterface pointers hold the solvers for the - * ZombiePool. At least one must be assigned. Field assignments - * propagate from the pool to whichever is assigned. Field - * lookups first check the dsolve, then the ksolve. - * The ZombiePool may be managed by the diffusion solver without - * the involvement of the Stoich class at all. So instead of - * routing the zombie operations through the Stoich, we have - * pointers directly into the Dsolve and Ksolve. - */ - ZombiePoolInterface* dsolve_; - ZombiePoolInterface* ksolve_; - double diffConst_; - double motorConst_; + static const Cinfo* initCinfo(); +protected: + /** + * The ZombiePoolInterface pointers hold the solvers for the + * ZombiePool. At least one must be assigned. Field assignments + * propagate from the pool to whichever is assigned. Field + * lookups first check the dsolve, then the ksolve. + * The ZombiePool may be managed by the diffusion solver without + * the involvement of the Stoich class at all. So instead of + * routing the zombie operations through the Stoich, we have + * pointers directly into the Dsolve and Ksolve. + */ + ZombiePoolInterface* dsolve_; + ZombiePoolInterface* ksolve_; + double diffConst_; + double motorConst_; }; #endif // _ZOMBIE_POOL_H diff --git a/ksolve/ZombiePoolInterface.h b/ksolve/ZombiePoolInterface.h index 70d49954..8cae5d56 100644 --- a/ksolve/ZombiePoolInterface.h +++ b/ksolve/ZombiePoolInterface.h @@ -46,6 +46,9 @@ class ZombiePoolInterface /// gets number of pools (species) handled by system. virtual unsigned int getNumPools() const = 0; + /// Specifies number of var pools and total pools including buffered . + virtual void setNumVarTotPools( unsigned int var, unsigned int tot )=0; + /// Assign number of voxels (size of pools_ vector ) virtual void setNumAllVoxels( unsigned int numVoxels ) = 0; /// Number of voxels here. pools_.size() == getNumLocalVoxels diff --git a/ksolve/helper.h b/ksolve/helper.h new file mode 100644 index 00000000..4535e002 --- /dev/null +++ b/ksolve/helper.h @@ -0,0 +1,18 @@ +#ifndef HELPER_H +#define HELPER_H + +template +bool areEqual(T a, T b) +{ + return std::fabs(a - b) < 1e-6; +} + +template +void print_vec( const vector& v, const string prefix="" ) +{ + cout << prefix << " SIZE=" << v.size() << " : "; + for( auto x : v ) cout << x << ','; + cout << endl; +} + +#endif /* end of include guard: HELPER_H */ diff --git a/ksolve/testKsolve.cpp b/ksolve/testKsolve.cpp index 12c0eb88..167ff308 100644 --- a/ksolve/testKsolve.cpp +++ b/ksolve/testKsolve.cpp @@ -8,17 +8,21 @@ **********************************************************************/ #include "../basecode/header.h" #include "../shell/Shell.h" + #include "RateTerm.h" #include "FuncTerm.h" #include "../basecode/SparseMatrix.h" #include "KinSparseMatrix.h" #include "VoxelPoolsBase.h" #include "../mesh/VoxelJunction.h" +#include "../builtins/MooseParser.h" #include "XferInfo.h" #include "ZombiePoolInterface.h" #include "Stoich.h" +#include "../mesh/VoxelJunction.h" -#include "../external/muparser/include/muParser.h" +#include "../builtins/MooseParser.h" +#include "../utility/testing_macros.hpp" /** * Tab controlled by table @@ -102,17 +106,16 @@ Id makeReacTest() Field< double >::set( e2, "kcat", 1 ); vector< double > stim( 100, 0.0 ); double vol = Field< double >::get( kin, "volume" ); - for ( unsigned int i = 0; i< 100; ++i ) - { - stim[i] = vol * NA * (1.0 + sin( i * 2.0 * PI / 100.0 ) ); - } + + for(unsigned int i = 0; i < 100; ++i) + stim[i] = vol*NA*(1.0+sin(i*2.0*PI/100.0)); + Field< vector< double > >::set( tab, "vector", stim ); Field< double >::set( tab, "stepSize", 0.0 ); Field< double >::set( tab, "stopTime", 10.0 ); Field< double >::set( tab, "loopTime", 10.0 ); Field< bool >::set( tab, "doLoop", true ); - // Connect outputs for ( unsigned int i = 0; i < 7; ++i ) s->doAddMsg( "Single", ObjId( plots,i), @@ -262,6 +265,39 @@ void testRunKsolve() cout << "." << flush; } +void testRunKsolveWithLSODA() +{ + double simDt = 0.1; + // double plotDt = 0.1; + Shell* s = reinterpret_cast< Shell* >( Id().eref().data() ); + Id kin = makeReacTest(); + + Id ksolve = s->doCreate( "Ksolve", kin, "ksolve", 1 ); + Field< string >::set( ksolve, "method", "lsoda" ); + + Id stoich = s->doCreate( "Stoich", ksolve, "stoich", 1 ); + Field< Id >::set( stoich, "compartment", kin ); + Field< Id >::set( stoich, "ksolve", ksolve ); + Field< string >::set( stoich, "path", "/kinetics/##" ); + s->doUseClock( "/kinetics/ksolve", "process", 4 ); + s->doSetClock( 4, simDt ); + + s->doReinit(); + s->doStart( 20.0 ); + Id plots( "/kinetics/plots" ); + for ( unsigned int i = 0; i < 7; ++i ) + { + stringstream ss; + ss << "plot." << i; + SetGet2< string, string >::set( ObjId( plots, i ) + , "xplot", "tsr2lsoda.plot", ss.str() + ); + } + s->doDelete( kin ); + cout << "." << flush; +} + + void testRunGsolve() { double simDt = 0.1; @@ -310,24 +346,24 @@ void testRunGsolve() void testFuncTerm() { FuncTerm ft; - ft.setExpr( "x0 + x1 * t" ); - double args[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + double args[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // First check that it doesn't die even if we forget to set up anything. - double ans = ft( args, 2.0 ); - - vector< unsigned int > mol( 2, 0 ); + double ans = ft(args, 2.0); + vector< unsigned int > mol(2, 0); mol[0] = 2; mol[1] = 0; - ft.setReactantIndex( mol ); + ft.setReactantIndex(mol); + + ft.setExpr("x0+x1*t"); + ans = ft(args, 10.0); + assert(doubleEq(ans, 13.0)); - ans = ft( args, 10.0 ); - assert( doubleEq( ans, 13.0 ) ); mol[0] = 0; mol[1] = 9; - ft.setReactantIndex( mol ); - ans = ft( args, 2.0 ); - assert( doubleEq( ans, 21.0 ) ); + ft.setReactantIndex(mol); + ans = ft(args, 2.0); + ASSERT_EQ(21.0, ans, "testFuncTerm"); cout << "." << flush; } diff --git a/mesh/CylMesh.cpp b/mesh/CylMesh.cpp index 3f467d94..2267610b 100644 --- a/mesh/CylMesh.cpp +++ b/mesh/CylMesh.cpp @@ -289,20 +289,25 @@ double CylMesh::getR0( const Eref& e ) const void CylMesh::setX1( const Eref& e, double v ) { + size_t numVoxels = (v - x0_) / diffLength_; x1_ = v; - size_t numVoxels = (x1_ - x0_) / diffLength_; - if( numVoxels >= SM_MAX_COLUMNS) + if( numVoxels >= SM_MAX_COLUMNS ) { - diffLength_ = (x1_-x0_)/(SM_MAX_COLUMNS-1); - MOOSE_WARN( "Too many voxels (" << numVoxels << ") would be created" - << " for current length " << (x1_ - x0_) << " and diffLength " - << diffLength_ << " (maximum " << SM_MAX_COLUMNS << " voxels allowed)." - << " Rescaling diffLength of compartment to " << diffLength_ << ". " + x1_ = diffLength_ * (SM_MAX_COLUMNS-1); + MOOSE_WARN("setX1: Too many voxels (" << numVoxels << ") would be created " + << "with current diffLength of " << diffLength_ + << "m (maximum voxels allowed=" << SM_MAX_COLUMNS << "). " + << " Changing length of the compartment: " + << "x0=" << x0_ << ", x1=" << x1_ + << ". You should change `diffLength` before setting `x1`." ); } - vector< double > childConcs; - getChildConcs( e, childConcs ); - updateCoords( e, childConcs ); + if(numVoxels > 0) + { + vector< double > childConcs; + getChildConcs( e, childConcs ); + updateCoords( e, childConcs ); + } } double CylMesh::getX1( const Eref& e ) const @@ -404,15 +409,21 @@ void CylMesh::setDiffLength( const Eref& e, double v ) size_t numVoxels = (size_t) ((x1_-x0_)/diffLength_); if( numVoxels >= SM_MAX_COLUMNS ) { + stringstream ss; + ss << "setDiffLength: Too many voxels (" << numVoxels << ") would be created " + << "for current value of x1=" << x1_ << "m, and x0=" << x0_ + << "m (max " << SM_MAX_COLUMNS << " allowed). "; x1_ = x0_ + diffLength_ * (SM_MAX_COLUMNS - 1); - MOOSE_WARN( "Too many voxels (" << numVoxels << ") would be created " - << "for diffLength of " << diffLength_ - << " (maximum " << SM_MAX_COLUMNS << " allowed). " - << " Changing compartment length to " << (x1_ - x0_) << "."); + ss << " Changing the length of the compartment: " + << "x0= " << x0_ << ", x1= " << x1_; + MOOSE_WARN(ss.str()); + } + if(numVoxels > 0) + { + vector< double > childConcs; + getChildConcs( e, childConcs ); + updateCoords( e, childConcs ); } - vector< double > childConcs; - getChildConcs( e, childConcs ); - updateCoords( e, childConcs ); } double CylMesh::getDiffLength( const Eref& e ) const diff --git a/pymoose/CMakeLists.txt b/pymoose/CMakeLists.txt index 22f4613e..7d35bd12 100644 --- a/pymoose/CMakeLists.txt +++ b/pymoose/CMakeLists.txt @@ -1,29 +1,24 @@ -cmake_minimum_required(VERSION 2.8) -include( ${CMAKE_CURRENT_SOURCE_DIR}/../CheckCXXCompiler.cmake) +include(${CMAKE_CURRENT_SOURCE_DIR}/../CheckCXXCompiler.cmake) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../cmake_modules/") -find_package(PythonInterp REQUIRED) +execute_process(COMMAND + ${PYTHON_EXECUTABLE} -c "import numpy;print(numpy.get_include())" + OUTPUT_VARIABLE NUMPY_INCLUDE_DIRS + OUTPUT_STRIP_TRAILING_WHITESPACE) + +if("${NUMPY_INCLUDE_DIRS}" STREQUAL "") + message(FATAL_ERROR "Could not find numpy: ${NUMPY_INCLUDE_DIRS}") +else() + message(STATUS "Numpy is found at ${NUMPY_INCLUDE_DIRS}") +endif() -# Find Numpy -find_package(NumPy REQUIRED) include_directories(${NUMPY_INCLUDE_DIRS}) -add_definitions( -std=c++11 ) +add_definitions(-std=c++11) add_definitions(-DUSE_NUMPY) add_definitions(-DNPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION) -# set module extensiton. default is .so. Also check ../python/setup.cmake.py -execute_process( COMMAND - ${PYTHON_EXECUTABLE} -c -"import importlib.machinery -print(importlib.machinery.EXTENSION_SUFFIXES[-1])" - OUTPUT_VARIABLE PYTHON_SO_EXTENSION - OUTPUT_STRIP_TRAILING_WHITESPACE - ) -if(NOT PYTHON_SO_EXTENSION) - message(STATUS "Python so ext could not be determined. Using default .so") - set(PYTHON_SO_EXTENSION ".so") -endif() +set(PYTHON_SO_EXTENSION ".so") message(STATUS "Python so extension ${PYTHON_SO_EXTENSION}" ) # TARGET @@ -44,29 +39,29 @@ set(PYMOOSE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../python/moose") message(STATUS "Python module will be saved to ${PYMOOSE_OUTPUT_DIRECTORY}" ) # make sure the Python.h is found. -find_package( PythonLibs) -if(PYTHON_INCLUDE_DIRS) - include_directories( ${PYTHON_INCLUDE_DIRS} ) -else() - # Use python executable to find include paths. For building wheel, we are - # stuck with cmake-2.8 with which PythonLibs module might fail. - message( STATUS "Using ${PYTHON_EXECUTABLE}-config to find Python.h" ) - execute_process( COMMAND ${PYTHON_EXECUTABLE}-config --includes +# Use python executable to find include paths. +# FIXME: cmake > 3.12 has great support for python but it is not available +# everywhere YET. When it is available on centos, we can use FindPython. +message(STATUS "Using ${PYTHON_EXECUTABLE}-config to find Python.h" ) +execute_process( COMMAND ${PYTHON_EXECUTABLE}-config --includes OUTPUT_VARIABLE PYTHON_INCLUDE_FLAGS - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - execute_process( COMMAND ${PYTHON_EXECUTABLE}-config --libs - OUTPUT_VARIABLE PYTHON_LIBRARIES - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - message( STATUS "Python include flags: ${PYTHON_INCLUDE_FLAGS}" ) - set_target_properties(_moose PROPERTIES - COMPILE_DEFINITIONS "PYMOOSE" - COMPILE_FLAGS "${PYTHON_INCLUDE_FLAGS}" - ) + OUTPUT_STRIP_TRAILING_WHITESPACE) +if("${PYTHON_INCLUDE_FLAGS}" STREQUAL "") + message(FATAL_ERROR "Could not determine path of Python.h.") +else() + message(STATUS "Python.h is found at ${PYTHON_INCLUDE_FLAGS}") endif() +execute_process( COMMAND ${PYTHON_EXECUTABLE}-config --libs + OUTPUT_VARIABLE PYTHON_LIBRARIES + OUTPUT_STRIP_TRAILING_WHITESPACE) + +set_target_properties(_moose PROPERTIES + COMPILE_DEFINITIONS "PYMOOSE" + COMPILE_FLAGS "${COMPILE_FLAGS} ${PYTHON_INCLUDE_FLAGS}" + ) + # Remove prefix lib from python module. if(NOT(PYTHON_SO_EXTENSION STREQUAL "")) set_target_properties(_moose PROPERTIES SUFFIX ${PYTHON_SO_EXTENSION}) @@ -74,8 +69,7 @@ endif() set_target_properties(_moose PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PYMOOSE_OUTPUT_DIRECTORY} PREFIX "" - SUFFIX ${PYTHON_SO_EXTENSION} - ) + SUFFIX ${PYTHON_SO_EXTENSION}) # see issue #80 if(HDF5_FOUND AND WITH_NSDF) @@ -85,10 +79,7 @@ endif() if(APPLE) set(CMAKE_MODULE_LINKER_FLAGS "-undefined dynamic_lookup") message(STATUS "ADDING some linker flags ${CMAKE_EXE_LINKER_FLAGS}") -endif(APPLE) - -# cmake --help-policy CMP0042 -if(APPLE) + # cmake --help-policy CMP0042 set_target_properties( _moose PROPERTIES MACOSX_RPATH OFF) endif(APPLE) @@ -107,15 +98,45 @@ else(APPLE) ${MOOSE_LIBRARIES} ${STATIC_LIBRARIES} "-Wl,--no-whole-archive" - ${SYSTEM_SHARED_LIBS} - ) -endif(APPLE) -add_custom_command(TARGET _moose POST_BUILD - COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --cyan - "MOOSE python extention is successfully built. Now " - " Run 'sudo make install' to install it. " - " " - "NOTE: Run 'pip uninstall moose' to uninstall moose." - VERBATIM - ) + ${SYSTEM_SHARED_LIBS}) +endif() + +# PYMOOSE DISTRIBUTION. +#find_python_module(wheel REQUIRED) +#if(NOT PY_WHEEL) +# message(STATUS "Python module wheel is not found. Please wait while I install it..") +# execute_process(COMMAND ${PYTHON_EXECUTABLE} -m pip install wheel --user) +#endif(NOT PY_WHEEL) + +# Create a binary distribution inside a directory. Installation is copying that +# directory to ${CMAKE_INSTALL_PREFIX} +set(_platform "CMAKE") +set(PYMOOSE_BDIST_FILE ${CMAKE_BINARY_DIR}/pymoose-${VERSION_MOOSE}.${_platform}.tar.gz) +set(PYMOOSE_INSTALL_DIR ${CMAKE_BINARY_DIR}/_pymoose_temp_install) +file(MAKE_DIRECTORY ${PYMOOSE_INSTALL_DIR}) + +add_custom_target(pymoose_sdist ALL + DEPENDS ${PYMOOSE_BDIST_FILE} _moose + COMMENT "Building pymoose sdist") + +add_custom_command(OUTPUT ${PYMOOSE_BDIST_FILE} + COMMAND ${PYTHON_EXECUTABLE} setup.py build_py + COMMAND ${PYTHON_EXECUTABLE} setup.py bdist_dumb + --skip-build -p "${_platform}" -d ${CMAKE_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E chdir ${PYMOOSE_INSTALL_DIR} tar xf ${PYMOOSE_BDIST_FILE} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMENT "python's binary distribution is saved to ${CMAKE_BINARY_DIR}" + VERBATIM) + +# Copy python tree to BUILD directory. User can set PYTHONPATH to +# ${CMAKE_BINARY_DIR}/python. +add_custom_target(copy_python_tree ALL + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_SOURCE_DIR}/python ${CMAKE_BINARY_DIR}/python + COMMENT "Copying python source tree: ${CMAKE_SOURCE_DIR}/python -> ${CMAKE_BINARY_DIR}/python" + DEPENDS _moose VERBATIM) + +install(DIRECTORY ${PYMOOSE_INSTALL_DIR}/usr/local/ + DESTINATION ${CMAKE_INSTALL_PREFIX} + CONFIGURATIONS Debug Release) diff --git a/pymoose/PyRun.cpp b/pymoose/PyRun.cpp index 53e33c6b..733ef0a2 100644 --- a/pymoose/PyRun.cpp +++ b/pymoose/PyRun.cpp @@ -16,10 +16,10 @@ const int PyRun::RUNBOTH = 0; static SrcFinfo1< double >* outputOut() { static SrcFinfo1< double > outputOut( "output", - "Sends out the value of local variable called `output`. Thus, you can" - " have Python statements which compute some value and assign it to the" - " variable called `output` (which is defined at `reinit` call). This" - " will be sent out to any target connected to the `output` field."); + "Sends out the value of local variable called `output`. Thus, you can" + " have Python statements which compute some value and assign it to the" + " variable called `output` (which is defined at `reinit` call). This" + " will be sent out to any target connected to the `output` field."); return &outputOut; } @@ -58,18 +58,6 @@ const Cinfo * PyRun::initCinfo() &PyRun::setMode, &PyRun::getMode); - // static ValueFinfo< PyRun, PyObject* > globals( - // "globals", - // "Global environment dict", - // &PyRun::setGlobals, - // &PyRun::getGlobals); - - // static ValueFinfo< PyRun, PyObject* > locals( - // "locals", - // "Local environment dict", - // &PyRun::setLocals, - // &PyRun::getLocals); - static DestFinfo trigger( "trigger", "Executes the current runString whenever a message arrives. It stores" @@ -116,8 +104,6 @@ const Cinfo * PyRun::initCinfo() &outputvar, &trigger, outputOut(), - // &locals, - // &globals, &run, &proc, }; diff --git a/pymoose/melement.cpp b/pymoose/melement.cpp index 47ce0e40..047788da 100644 --- a/pymoose/melement.cpp +++ b/pymoose/melement.cpp @@ -1,50 +1,6 @@ // melement.cpp --- -// -// Filename: melement.cpp -// Description: -// Author: -// Maintainer: +// Author: Subhasis Ray // Created: Mon Jul 22 16:50:41 2013 (+0530) -// Version: -// Last-Updated: Fri Sep 25 23:02:53 2015 (-0400) -// By: subha -// Update #: 76 -// URL: -// Keywords: -// Compatibility: -// -// - -// Commentary: -// -// Mon Jul 22 16:50:47 IST 2013 - Taking out ObjId stuff from -// moosemodule.cpp -// -// - -// Change log: -// -// -// -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; see the file COPYING. If not, write to -// the Free Software Foundation, Inc., 51 Franklin Street, Fifth -// Floor, Boston, MA 02110-1301, USA. -// -// - -// Code: #include #include @@ -66,9 +22,11 @@ #include "../basecode/header.h" #include "../basecode/Id.h" #include "../basecode/ObjId.h" +#include "../shell/Shell.h" + #include "../utility/utility.h" +#include "../utility/strutil.h" #include "../utility/print_function.hpp" -#include "../shell/Shell.h" #include "moosemodule.h" diff --git a/pymoose/moosemodule.cpp b/pymoose/moosemodule.cpp index 96e37d66..d2cded75 100644 --- a/pymoose/moosemodule.cpp +++ b/pymoose/moosemodule.cpp @@ -6,25 +6,21 @@ #include #include -#ifdef USE_NUMPY +// Numpy is now default. #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION #include -#endif #include #include #include #include #include +#include #include #include #include #include -#if USE_BOOST_ODE -#include -#endif - #ifdef USE_MPI #include #endif @@ -34,60 +30,20 @@ #include "../basecode/global.h" #include "../basecode/Id.h" #include "../basecode/ObjId.h" -#include "../utility/utility.h" #include "../shell/Shell.h" #include "../shell/Wildcard.h" #include "../basecode/global.h" +#include "../utility/utility.h" +#include "../utility/strutil.h" + #include "moosemodule.h" using namespace std; -#ifdef DO_UNIT_TESTS - -extern void testSync(); -extern void testAsync(); - -extern void testSyncArray( - unsigned int size, - unsigned int numThreads, - unsigned int method - ); - -extern void testShell(); -extern void testScheduling(); -extern void testSchedulingProcess(); -extern void testBuiltins(); -extern void testBuiltinsProcess(); - -extern void testMpiScheduling(); -extern void testMpiBuiltins(); -extern void testMpiShell(); -extern void testMsg(); -extern void testMpiMsg(); -extern void testKinetics(); - -#endif - -extern void mpiTests(); -extern void processTests( Shell* ); -extern void nonMpiTests(Shell *); -extern void test_moosemodule(); - - -extern Id init( - int argc, char ** argv, bool& doUnitTests - , bool& doRegressionTests, unsigned int& benchmark - ); +extern Id init( int argc, char ** argv, bool& doUnitTests); extern void initMsgManagers(); -extern void destroyMsgManagers(); - -extern void speedTestMultiNodeIntFireNetwork( - unsigned int size, unsigned int runsteps - ); - -extern void mooseBenchmarks( unsigned int option ); /*----------------------------------------------------------------------------- * Random number generator for this module. @@ -182,18 +138,11 @@ extern PyTypeObject moose_DestField; extern PyTypeObject moose_LookupField; extern PyTypeObject moose_ElementField; -///////////////////////////////////////////////////////////////// // Module globals -///////////////////////////////////////////////////////////////// -int verbosity = 1; -// static int isSingleThreaded = 0; +int verbosity = 0; static int isInfinite = 0; static unsigned int numNodes = 1; -// static unsigned int numCores = 1; -// static unsigned int myNode = 0; -// static unsigned int numProcessThreads = 0; static int doUnitTests = 0; -static int doRegressionTests = 0; static int quitFlag = 0; /** @@ -298,6 +247,7 @@ void * to_cpp(PyObject * object, char typecode) } case 's': { + assert(object); char* tmp = PyString_AsString(object); if (tmp == NULL) { @@ -908,13 +858,7 @@ vector setup_runtime_env() vector args; args.push_back("moose"); map::const_iterator it; - // it = argmap.find("SINGLETHREADED"); - // if (it != argmap.end()){ - // istringstream(it->second) >> isSingleThreaded; - // if (isSingleThreaded){ - // args.push_back("-s"); - // } - // } + it = argmap.find("INFINITE"); if (it != argmap.end()) { @@ -924,26 +868,7 @@ vector setup_runtime_env() args.push_back("-i"); } } -#if 0 - it = argmap.find("NUMNODES"); - if (it != argmap.end()) - { - istringstream(it->second) >> numNodes; - args.push_back("-n"); - args.push_back(it->second); - } - it = argmap.find("NUMCORES"); - if (it != argmap.end()) - { - istringstream(it->second) >> numCores; - } - // it = argmap.find("NUMPTHREADS"); - // if (it != argmap.end()){ - // istringstream(it->second) >> numProcessThreads; - // args.push_back("-t"); - // args.push_back(it->second); - // } -#endif + it = argmap.find("QUIT"); if (it != argmap.end()) { @@ -963,11 +888,6 @@ vector setup_runtime_env() { istringstream(it->second) >> doUnitTests; } - it = argmap.find("DOREGRESSIONTESTS"); - if (it != argmap.end()) - { - istringstream(it->second) >> doRegressionTests; - } if (verbosity > 0) { @@ -979,7 +899,6 @@ vector setup_runtime_env() // << " NUMPTHREADS = " << numProcessThreads << endl << " VERBOSITY = " << verbosity << endl << " DOUNITTESTS = " << doUnitTests << endl - << " DOREGRESSIONTESTS = " << doRegressionTests << endl << "========================================" << endl; } return args; @@ -995,20 +914,12 @@ Id getShell(int argc, char ** argv) { static int inited = 0; if (inited) - { return Id(0); - } - bool dounit = doUnitTests != 0; - bool doregress = doRegressionTests != 0; - unsigned int doBenchmark = 0; - // Utilize the main::init function which has friend access to Id - Id shellId = init(argc, argv, dounit, doregress, doBenchmark ); + + bool dounit = false; + Id shellId = init(argc, argv, dounit); inited = 1; Shell * shellPtr = reinterpret_cast(shellId.eref().data()); - if (dounit) - { - nonMpiTests( shellPtr ); // These tests do not need the process loop. - } if ( shellPtr->myNode() == 0 ) { if ( Shell::numNodes() > 1 ) @@ -1019,24 +930,9 @@ Id getShell(int argc, char ** argv) shellPtr->doUseClock( "/postmaster", "process", 9 ); shellPtr->doSetClock( 9, 1.0 ); // Use a sensible default. } -#ifdef DO_UNIT_TESTS - if ( dounit ) - { - mpiTests(); - processTests( shellPtr ); - } - // if ( doRegressionTests ) regressionTests(); -#endif - // These are outside unit tests because they happen in optimized - // mode, using a command-line argument. As soon as they are done - // the system quits, in order to estimate timing. - if ( doBenchmark != 0 ) - { - mooseBenchmarks( doBenchmark ); - } } return shellId; -} //! create_shell() +} /** Clean up after yourself. @@ -1389,30 +1285,30 @@ PyObject * moose_getFieldNames(PyObject * dummy, PyObject * args) } PyDoc_STRVAR(moose_copy_documentation, - "copy(src, dest, name, n, toGlobal, copyExtMsg) -> bool\n" - "\n" - "Make copies of a moose object.\n" - "\n" - "Parameters\n" - "----------\n" - "src : vec, element or str\n" - " source object.\n" - "dest : vec, element or str\n" - " Destination object to copy into.\n" - "name : str\n" - " Name of the new object. If omitted, name of the original will be used.\n" - "n : int\n" - " Number of copies to make.\n" - "toGlobal : int\n" - " Relevant for parallel environments only. If false, the copies will\n" - " reside on local node, otherwise all nodes get the copies.\n" - "copyExtMsg : int\n" - " If true, messages to/from external objects are also copied.\n" - "\n" - "Returns\n" - "-------\n" - "vec\n" - " newly copied vec\n" + "copy(src, dest, name, n, toGlobal, copyExtMsg) -> bool\n" + "\n" + "Make copies of a moose object.\n" + "\n" + "Parameters\n" + "----------\n" + "src : vec, element or str\n" + " source object.\n" + "dest : vec, element or str\n" + " Destination object to copy into.\n" + "name : str\n" + " Name of the new object. If omitted, name of the original will be used.\n" + "n : int\n" + " Number of copies to make.\n" + "toGlobal : int\n" + " Relevant for parallel environments only. If false, the copies will\n" + " reside on local node, otherwise all nodes get the copies.\n" + "copyExtMsg : int\n" + " If true, messages to/from external objects are also copied.\n" + "\n" + "Returns\n" + "-------\n" + "vec\n" + " newly copied vec\n" ); PyObject * moose_copy(PyObject * dummy, PyObject * args, PyObject * kwargs) @@ -1961,52 +1857,52 @@ PyObject * moose_getCwe(PyObject * dummy, PyObject * args) } PyDoc_STRVAR(moose_connect_documentation, - "connect(src, srcfield, destobj, destfield[,msgtype]) -> bool\n" - "\n" - "Create a message between `src_field` on `src` object to `dest_field` on `dest` object.\n" - "This function is used mainly, to say, connect two entities, and to denote what kind of give-and-take relationship they share." - "It enables the 'destfield' (of the 'destobj') to acquire the data, from 'srcfield'(of the 'src')." - "\n" - "Parameters\n" - "----------\n" - "src : element/vec/string\n" - " the source object (or its path) \n" - " (the one that provides information)\n" - "srcfield : str\n" - " source field on self.(type of the information)\n" - "destobj : element\n" - " Destination object to connect to.\n" - " (The one that need to get information)\n" - "destfield : str\n" - " field to connect to on `destobj`.\n" - "msgtype : str\n" - " type of the message. Can be \n" - " `Single` - \n" - " `OneToAll` - \n" - " `AllToOne` - \n" - " `OneToOne` - \n" - " `Reduce` - \n" - " `Sparse` - \n" - " Default: `Single`.\n" - "\n" - "Returns\n" - "-------\n" - "msgmanager: melement\n" - " message-manager for the newly created message.\n" - "\n" - "Examples\n" - "--------\n" - "Connect the output of a pulse generator to the input of a spike\n" - "generator::\n" - "\n" - " >>> pulsegen = moose.PulseGen('pulsegen')\n" - " >>> spikegen = moose.SpikeGen('spikegen')\n" - " >>> pulsegen.connect('output', spikegen, 'Vm')\n" - "\n" - "See also\n" - "--------\n" - "moose.connect\n" - ); + "connect(src, srcfield, destobj, destfield[,msgtype]) -> bool\n" + "\n" + "Create a message between `src_field` on `src` object to `dest_field` on `dest` object.\n" + "This function is used mainly, to say, connect two entities, and to denote what kind of give-and-take relationship they share." + "It enables the 'destfield' (of the 'destobj') to acquire the data, from 'srcfield'(of the 'src')." + "\n" + "Parameters\n" + "----------\n" + "src : element/vec/string\n" + " the source object (or its path) \n" + " (the one that provides information)\n" + "srcfield : str\n" + " source field on self.(type of the information)\n" + "destobj : element\n" + " Destination object to connect to.\n" + " (The one that need to get information)\n" + "destfield : str\n" + " field to connect to on `destobj`.\n" + "msgtype : str\n" + " type of the message. Can be \n" + " `Single` - \n" + " `OneToAll` - \n" + " `AllToOne` - \n" + " `OneToOne` - \n" + " `Reduce` - \n" + " `Sparse` - \n" + " Default: `Single`.\n" + "\n" + "Returns\n" + "-------\n" + "msgmanager: melement\n" + " message-manager for the newly created message.\n" + "\n" + "Examples\n" + "--------\n" + "Connect the output of a pulse generator to the input of a spike\n" + "generator::\n" + "\n" + " >>> pulsegen = moose.PulseGen('pulsegen')\n" + " >>> spikegen = moose.SpikeGen('spikegen')\n" + " >>> pulsegen.connect('output', spikegen, 'Vm')\n" + "\n" + "See also\n" + "--------\n" + "moose.connect\n" + ); PyObject * moose_connect(PyObject * dummy, PyObject * args) { @@ -2565,7 +2461,6 @@ int defineLookupFinfos(const Cinfo * cinfo) return 1; } - int defineClass(PyObject * module_dict, const Cinfo * cinfo) { const string& className = cinfo->name(); @@ -2774,14 +2669,26 @@ int defineDestFinfos(const Cinfo * cinfo) // if (name.find("get") == 0 || name.find("set") == 0){ // continue; // } - PyGetSetDef destFieldGetSet; + PyGetSetDef destFieldGetSet = {.name = (char*) name.c_str() + , .get=nullptr, .set=nullptr + , .doc= (char*) "Destination field" + , .closure=nullptr + }; vec.push_back(destFieldGetSet); - vec[currIndex].name = strdup(name.c_str()); - vec[currIndex].doc = (char*) "Destination field"; + // Dilawar: + // strncpy can not write to const char* especially with clang++. + // Ref: https://docs.python.org/3/c-api/structures.html#c.PyGetSetDef + //vec[currIndex].name = (char*)calloc(name.size() + 1, sizeof(char)); + //strncpy(vec[currIndex].name, + // const_cast(name.c_str()), + // name.size()); + // vec[currIndex].doc = (char*) "Destination field"; + vec[currIndex].get = (getter)moose_ObjId_get_destField_attr; PyObject *args = PyTuple_New(1); - if (!args || !vec[currIndex].name) { + if (!args || !vec[currIndex].name) + { cerr << "moosemodule.cpp: defineDestFinfos: allocation failed\n"; return 0; } @@ -2974,8 +2881,8 @@ PyObject * moose_element(PyObject* dummy, PyObject * args) if ( oid.bad() ) { PyErr_SetString(PyExc_ValueError - , (std::string("moose_element: '") + std::string(path) + std::string("' does not exist!")).c_str() - ); + , (std::string("moose_element: '") + std::string(path) + std::string("' does not exist!")).c_str() + ); return NULL; } PyObject * new_obj = oid_to_element(oid); @@ -3125,26 +3032,6 @@ PyMODINIT_FUNC MODINIT(_moose) { clock_t modinit_start = clock(); - //PyGILState_STATE gstate; - //gstate = PyGILState_Ensure(); - - // First of all create the Shell. We convert the environment - // variables into c-like argv array - vector args = setup_runtime_env(); - int argc = args.size(); - char ** argv = (char**)calloc(args.size(), sizeof(char*)); - for (int ii = 0; ii < argc; ++ii) - { - argv[ii] = (char*)(calloc(args[ii].length()+1, sizeof(char))); - strncpy(argv[ii], args[ii].c_str(), args[ii].length()+1); - } - - // Should not call. No pthreads now. PyEval_InitThreads(); - Id shellId = getShell(argc, argv); - for (int ii = 1; ii < argc; ++ii) - { - free(argv[ii]); - } // Now initialize the module #ifdef PY3K PyObject * moose_module = PyModule_Create(&MooseModuleDef); @@ -3251,18 +3138,16 @@ PyMODINIT_FUNC MODINIT(_moose) clock_t defclasses_end = clock(); LOG( moose::debug, "`Time to define moose classes:" - << (defclasses_end - defclasses_start) * 1.0 /CLOCKS_PER_SEC + << (defclasses_end - defclasses_start) * 1.0 /CLOCKS_PER_SEC ); //PyGILState_Release(gstate); clock_t modinit_end = clock(); LOG( moose::debug, "`Time to initialize module:" - << (modinit_end - modinit_start) * 1.0 /CLOCKS_PER_SEC + << (modinit_end - modinit_start) * 1.0 /CLOCKS_PER_SEC ); - if (doUnitTests) - test_moosemodule(); #ifdef PY3K return moose_module; #endif diff --git a/pymoose/moosemodule.h b/pymoose/moosemodule.h index 470b17f1..97e01705 100644 --- a/pymoose/moosemodule.h +++ b/pymoose/moosemodule.h @@ -1,20 +1,13 @@ // moosemodule.h --- -// -// Filename: moosemodule.h -// Description: + // Author: Subhasis Ray // Maintainer: Dilawar Singh // Copyright (C) 2010 Subhasis Ray, all rights reserved. // Created: Thu Mar 10 17:11:06 2011 (+0530) -// Last-Updated: Mon 25 Apr 2016 11:09:02 AM IST -// By: Dilawar -// URL: #ifndef _MOOSEMODULE_H #define _MOOSEMODULE_H -#include - extern char shortType(string); // declared in utility.h, defined in utility/types.cpp @@ -27,23 +20,6 @@ struct module_state }; -// The endianness check is from: -// http://stackoverflow.com/questions/2100331/c-macro-definition-to-determine-big-endian-or-little-endian-machine -enum -{ - O32_LITTLE_ENDIAN = 0x03020100ul, - O32_BIG_ENDIAN = 0x00010203ul, - O32_PDP_ENDIAN = 0x01000302ul -}; - -const union -{ - unsigned char bytes[4]; - uint32_t value; -} o32_host_order = { { 0, 1, 2, 3 } }; - -#define O32_HOST_ORDER (o32_host_order.value) - #if PY_MAJOR_VERSION >= 3 #define PY3K PyMODINIT_FUNC PyInit_moose(); @@ -486,6 +462,7 @@ template int set_lookup_value(const ObjId& oid, string fname, char value_type_code, char key_type_code, PyObject * key, PyObject * value_obj) { bool success = false; + assert(key); KeyType *cpp_key = (KeyType*)to_cpp(key, key_type_code); if (cpp_key == NULL) { diff --git a/pymoose/pymooseinit.cpp b/pymoose/pymooseinit.cpp index add0fee1..e2257dde 100644 --- a/pymoose/pymooseinit.cpp +++ b/pymoose/pymooseinit.cpp @@ -11,7 +11,6 @@ #include #include #include -#include // for getopt #include "../scheduling/Clock.h" #include "../msg/DiagonalMsg.h" #include "../basecode/SparseMatrix.h" @@ -43,36 +42,12 @@ extern void testMpiBuiltins(); extern void testMpiShell(); extern void testMsg(); extern void testMpiMsg(); -// extern void testKinetics(); -// extern void testKineticSolvers(); -// extern void testKineticSolversProcess(); extern void testBiophysics(); extern void testBiophysicsProcess(); -// extern void testHSolve(); -// extern void testKineticsProcess(); -// extern void testGeom(); -// extern void testMesh(); -// extern void testSimManager(); -// extern void testSigNeur(); -// extern void testSigNeurProcess(); - extern unsigned int initMsgManagers(); extern void destroyMsgManagers(); -// void regressionTests(); -#endif -extern void speedTestMultiNodeIntFireNetwork( - unsigned int size, unsigned int runsteps ); - -#ifdef USE_SMOLDYN -extern void testSmoldyn(); -#endif -// bool benchmarkTests( int argc, char** argv ); - -extern void mooseBenchmarks( unsigned int option ); - -////////////////////////////////////////////////////////////////// -// System-dependent function here -////////////////////////////////////////////////////////////////// +#endif // DO_UNIT_TESTS +extern void speedTestMultiNodeIntFireNetwork(unsigned int size, unsigned int runsteps ); unsigned int getNumCores() { @@ -133,77 +108,20 @@ void checkChildren( Id parent, const string& info ) } } -Id init( int argc, char** argv, bool& doUnitTests, bool& doRegressionTests, - unsigned int& benchmark ) +Id init( int argc, char** argv, bool& doUnitTests) { unsigned int numCores = getNumCores(); int numNodes = 1; int myNode = 0; bool isInfinite = 0; int opt; - benchmark = 0; // Default, means don't do any benchmarks. Cinfo::rebuildOpIndex(); + #ifdef USE_MPI - /* - // OpenMPI does not use argc or argv. - // unsigned int temp_argc = 1; - int provided; - MPI_Init_thread( &argc, &argv, MPI_THREAD_SERIALIZED, &provided ); - */ MPI_Init( &argc, &argv ); - MPI_Comm_size( MPI_COMM_WORLD, &numNodes ); MPI_Comm_rank( MPI_COMM_WORLD, &myNode ); - /* - if ( provided < MPI_THREAD_SERIALIZED && myNode == 0 ) { - cout << "Warning: This MPI implementation does not like multithreading: " << provided << "\n"; - } - */ - // myNode = MPI::COMM_WORLD.Get_rank(); -#endif - /** - * Here we allow the user to override the automatic identification - * of processor configuration - */ - while ( ( opt = getopt( argc, argv, "hiqurn:b:B:" ) ) != -1 ) - { - switch ( opt ) - { - case 'i' : // infinite loop, used for multinode debugging, to give gdb something to attach to. - isInfinite = 1; - break; - case 'n': // Multiple nodes - numNodes = (unsigned int)atoi( optarg ); - break; - case 'b': // Benchmark: - benchmark = atoi( optarg ); - break; - case 'B': // Benchmark plus dump data: handle later. - break; - case 'u': // Do unit tests, pass back. - doUnitTests = 1; - break; - case 'r': // Do regression tests: pass back - doRegressionTests = 1; - break; - case 'q': // quit immediately after completion. - quitFlag = 1; - break; - case 'h': // help - default: - cout << "Usage: moose -help -infiniteLoop -unit_tests -regression_tests -quit -n numNodes -benchmark [ksolve intFire hhNet msg__]\n"; - - exit( 1 ); - } - } - if ( myNode == 0 ) - { - -#if 0 - cout << "on node " << myNode << ", numNodes = " - << numNodes << ", numCores = " << numCores << endl; #endif - } Id shellId; Element* shelle = @@ -231,8 +149,6 @@ Id init( int argc, char** argv, bool& doUnitTests, bool& doRegressionTests, assert( classMasterId == Id( 2 ) ); assert( postMasterId == Id( 3 ) ); - - // s->connectMasterMsg(); Shell::adopt( shellId, clockId, numMsg++ ); diff --git a/pymoose/test_moosemodule.cpp b/pymoose/test_moosemodule.cpp index 06a03215..175de0eb 100644 --- a/pymoose/test_moosemodule.cpp +++ b/pymoose/test_moosemodule.cpp @@ -1,49 +1,9 @@ // test_moosemodule.cpp --- // -// Filename: test_moosemodule.cpp // Description: -// Author: -// Maintainer: +// Author: Subha +// Maintainer: Dilawar Singh // Created: Tue Jul 23 11:37:57 2013 (+0530) -// Version: -// Last-Updated: Thu Jul 25 21:54:10 2013 (+0530) -// By: subha -// Update #: 85 -// URL: -// Keywords: -// Compatibility: -// -// - -// Commentary: -// -// -// -// - -// Change log: -// -// -// -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; see the file COPYING. If not, write to -// the Free Software Foundation, Inc., 51 Franklin Street, Fifth -// Floor, Boston, MA 02110-1301, USA. -// -// - -// Code: #include "Python.h" #include @@ -139,6 +99,3 @@ void test_moosemodule() { test_to_py(); } - -// -// test_moosemodule.cpp ends here diff --git a/pymoose/vec.cpp b/pymoose/vec.cpp index fc57831c..8a3f5b4a 100644 --- a/pymoose/vec.cpp +++ b/pymoose/vec.cpp @@ -1,54 +1,11 @@ // vec.cpp --- -// // Filename: vec.cpp // Description: -// Author: -// Maintainer: +// Author: Subhasis Ray // Created: Mon Jul 22 16:46:37 2013 (+0530) -// Version: -// Last-Updated: Fri Sep 25 23:00:48 2015 (-0400) -// By: subha -// Update #: 80 -// URL: -// Keywords: -// Compatibility: -// -// - -// Commentary: -// -// -// -// - -// Change log: -// -// Mon Jul 22 16:47:10 IST 2013 - Splitting contents of -// moosemodule.cpp into speparate files. -// -//c -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; see the file COPYING. If not, write to -// the Free Software Foundation, Inc., 51 Franklin Street, Fifth -// Floor, Boston, MA 02110-1301, USA. -// -// - -// Code: #include #include // This defines the type id macros like T_STRING -#include "../utility/simple_logger.hpp" #include #include @@ -64,10 +21,13 @@ #include "../basecode/global.h" #include "../basecode/Id.h" #include "../basecode/ObjId.h" -#include "../utility/utility.h" + #include "../shell/Shell.h" #include "../shell/Wildcard.h" +#include "../utility/utility.h" +#include "../utility/strutil.h" + #include "moosemodule.h" using namespace std; @@ -510,13 +470,9 @@ long moose_Id_hash(_Id * self) } -// 2011-03-23 15:14:11 (+0530) -// 2011-03-26 17:02:19 (+0530) -// -// 2011-03-26 19:14:34 (+0530) - This IS UGLY! Destroying one +// This IS UGLY! Destroying one // ObjId will destroy the containing element and invalidate all // the other ObjId with the same Id. -// 2011-03-28 13:44:49 (+0530) PyObject * deleteObjId(ObjId oid) { #ifndef NDEBUG diff --git a/python/InstallPyMoose.cmake b/python/InstallPyMoose.cmake deleted file mode 100644 index 0c6a7ebf..00000000 --- a/python/InstallPyMoose.cmake +++ /dev/null @@ -1,25 +0,0 @@ -# CMake script to install python. -if(CPACK_TEMPORARY_INSTALL_DIRECTORY) - MESSAGE("++ Using CPACK to build") - set(CMAKE_INSTALL_PREFIX ${CPACK_TEMPORARY_INSTALL_DIRECTORY}) -else() - message("CPACK_TEMPORARY_INSTALL_DIRECTORY ${CPACK_TEMPORARY_INSTALL_DIRECTORY}") -endif() -execute_process(COMMAND - python -c "from distutils.sysconfig import get_python_lib; print get_python_lib(prefix=\"${CMAKE_INSTALL_PREFIX}\")" - OUTPUT_VARIABLE PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE - ) -MESSAGE("++ Installing python scripts: ${CMAKE_INSTALL_PREFIX}") -MESSAGE("+++ Updating PYTHONPATH: ${PYTHON_SITE_PACKAGES}") -MESSAGE("+++ Creating directory ${PYTHON_SITE_PACKAGES}") -execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${PYTHON_SITE_PACKAGES}) -set(ENV{PYTHONPATH} ${PYTHON_SITE_PACKAGES}) -set(PYTHON_DIR ${CMAKE_CURRENT_LIST_DIR}) -execute_process(COMMAND - python setup.py build_py build install - --skip-build - --prefix=${CMAKE_INSTALL_PREFIX} - -O2 --force - WORKING_DIRECTORY ${PYTHON_DIR} - ) -FILE(REMOVE_RECURSE ${PYTHON_DIR}/build) diff --git a/python/moose/OrderedDict.py b/python/moose/OrderedDict.py deleted file mode 100644 index 3f217842..00000000 --- a/python/moose/OrderedDict.py +++ /dev/null @@ -1,260 +0,0 @@ -# -*- coding: utf-8 -*- -# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy. -# Passes Python2.7's test suite and incorporates all the latest updates. - -import sys - -if sys.version_info > (3, 0 ): - from _thread import get_ident as _get_ident -else: - from thread import get_ident as _get_ident - -try: - from _abcoll import KeysView, ValuesView, ItemsView -except ImportError: - pass - -class OrderedDict(dict): - 'Dictionary that remembers insertion order' - # An inherited dict maps keys to values. - # The inherited dict provides __getitem__, __len__, __contains__, and get. - # The remaining methods are order-aware. - # Big-O running times for all methods are the same as for regular dictionaries. - - # The internal self.__map dictionary maps keys to links in a doubly linked list. - # The circular doubly linked list starts and ends with a sentinel element. - # The sentinel element never gets deleted (this simplifies the algorithm). - # Each link is stored as a list of length three: [PREV, NEXT, KEY]. - - def __init__(self, *args, **kwds): - '''Initialize an ordered dictionary. Signature is the same as for - regular dictionaries, but keyword arguments are not recommended - because their insertion order is arbitrary. - - ''' - if len(args) > 1: - raise TypeError('expected at most 1 arguments, got %d' % len(args)) - try: - self.__root - except AttributeError: - self.__root = root = [] # sentinel node - root[:] = [root, root, None] - self.__map = {} - self.__update(*args, **kwds) - - def __setitem__(self, key, value, dict_setitem=dict.__setitem__): - 'od.__setitem__(i, y) <==> od[i]=y' - # Setting a new item creates a new link which goes at the end of the linked - # list, and the inherited dictionary is updated with the new key/value pair. - if key not in self: - root = self.__root - last = root[0] - last[1] = root[0] = self.__map[key] = [last, root, key] - dict_setitem(self, key, value) - - def __delitem__(self, key, dict_delitem=dict.__delitem__): - 'od.__delitem__(y) <==> del od[y]' - # Deleting an existing item uses self.__map to find the link which is - # then removed by updating the links in the predecessor and successor nodes. - dict_delitem(self, key) - link_prev, link_next, key = self.__map.pop(key) - link_prev[1] = link_next - link_next[0] = link_prev - - def __iter__(self): - 'od.__iter__() <==> iter(od)' - root = self.__root - curr = root[1] - while curr is not root: - yield curr[2] - curr = curr[1] - - def __reversed__(self): - 'od.__reversed__() <==> reversed(od)' - root = self.__root - curr = root[0] - while curr is not root: - yield curr[2] - curr = curr[0] - - def clear(self): - 'od.clear() -> None. Remove all items from od.' - try: - for node in self.__map.itervalues(): - del node[:] - root = self.__root - root[:] = [root, root, None] - self.__map.clear() - except AttributeError: - pass - dict.clear(self) - - def popitem(self, last=True): - '''od.popitem() -> (k, v), return and remove a (key, value) pair. - Pairs are returned in LIFO order if last is true or FIFO order if false. - - ''' - if not self: - raise KeyError('dictionary is empty') - root = self.__root - if last: - link = root[0] - link_prev = link[0] - link_prev[1] = root - root[0] = link_prev - else: - link = root[1] - link_next = link[1] - root[1] = link_next - link_next[0] = root - key = link[2] - del self.__map[key] - value = dict.pop(self, key) - return key, value - - # -- the following methods do not depend on the internal structure -- - - def keys(self): - 'od.keys() -> list of keys in od' - return list(self) - - def values(self): - 'od.values() -> list of values in od' - return [self[key] for key in self] - - def items(self): - 'od.items() -> list of (key, value) pairs in od' - return [(key, self[key]) for key in self] - - def iterkeys(self): - 'od.iterkeys() -> an iterator over the keys in od' - return iter(self) - - def itervalues(self): - 'od.itervalues -> an iterator over the values in od' - for k in self: - yield self[k] - - def iteritems(self): - 'od.iteritems -> an iterator over the (key, value) items in od' - for k in self: - yield (k, self[k]) - - def update(*args, **kwds): - '''od.update(E, **F) -> None. Update od from dict/iterable E and F. - - If E is a dict instance, does: for k in E: od[k] = E[k] - If E has a .keys() method, does: for k in E.keys(): od[k] = E[k] - Or if E is an iterable of items, does: for k, v in E: od[k] = v - In either case, this is followed by: for k, v in F.items(): od[k] = v - - ''' - if len(args) > 2: - raise TypeError('update() takes at most 2 positional ' - 'arguments (%d given)' % (len(args),)) - elif not args: - raise TypeError('update() takes at least 1 argument (0 given)') - self = args[0] - # Make progressively weaker assumptions about "other" - other = () - if len(args) == 2: - other = args[1] - if isinstance(other, dict): - for key in other: - self[key] = other[key] - elif hasattr(other, 'keys'): - for key in other.keys(): - self[key] = other[key] - else: - for key, value in other: - self[key] = value - for key, value in kwds.items(): - self[key] = value - - __update = update # let subclasses override update without breaking __init__ - - __marker = object() - - def pop(self, key, default=__marker): - '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value. - If key is not found, d is returned if given, otherwise KeyError is raised. - - ''' - if key in self: - result = self[key] - del self[key] - return result - if default is self.__marker: - raise KeyError(key) - return default - - def setdefault(self, key, default=None): - 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od' - if key in self: - return self[key] - self[key] = default - return default - - def __repr__(self, _repr_running={}): - 'od.__repr__() <==> repr(od)' - call_key = id(self), _get_ident() - if call_key in _repr_running: - return '...' - _repr_running[call_key] = 1 - try: - if not self: - return '%s()' % (self.__class__.__name__,) - return '%s(%r)' % (self.__class__.__name__, self.items()) - finally: - del _repr_running[call_key] - - def __reduce__(self): - 'Return state information for pickling' - items = [[k, self[k]] for k in self] - inst_dict = vars(self).copy() - for k in vars(OrderedDict()): - inst_dict.pop(k, None) - if inst_dict: - return (self.__class__, (items,), inst_dict) - return self.__class__, (items,) - - def copy(self): - 'od.copy() -> a shallow copy of od' - return self.__class__(self) - - @classmethod - def fromkeys(cls, iterable, value=None): - '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S - and values equal to v (which defaults to None). - - ''' - d = cls() - for key in iterable: - d[key] = value - return d - - def __eq__(self, other): - '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive - while comparison to a regular mapping is order-insensitive. - - ''' - if isinstance(other, OrderedDict): - return len(self)==len(other) and self.items() == other.items() - return dict.__eq__(self, other) - - def __ne__(self, other): - return not self == other - - # -- the following methods are only used in Python 2.7 -- - - def viewkeys(self): - "od.viewkeys() -> a set-like object providing a view on od's keys" - return KeysView(self) - - def viewvalues(self): - "od.viewvalues() -> an object providing a view on od's values" - return ValuesView(self) - - def viewitems(self): - "od.viewitems() -> a set-like object providing a view on od's items" - return ItemsView(self) diff --git a/python/moose/SBML/readSBML.py b/python/moose/SBML/readSBML.py index 093f2085..ceaf4c86 100644 --- a/python/moose/SBML/readSBML.py +++ b/python/moose/SBML/readSBML.py @@ -13,10 +13,12 @@ ** copyright (C) 2003-2017 Upinder S. Bhalla. and NCBS Created : Thu May 13 10:19:00 2016(+0530) Version -Last-Updated: Sat Jan 19 10:30:00 2019(+0530) +Last-Updated: Mon Jun 16 10:30:00 2019(+0530) By:HarshaRani **********************************************************************/ 2019: +Jun 06: - both compartment name and Id is mapped to the values in comptSbmlidMooseIdMap +May 23: - checking for integer in Assignment expr Jan 19: - validator flag is set 'on' from True - groupname if missing in the sbml file then groupid is taken, if both are missing then its not a valide sbml file @@ -76,6 +78,7 @@ import moose from moose.chemUtil.chemConnectUtil import * from moose.SBML.validation import validateModel +import moose.print_utils as pu import re import os @@ -91,18 +94,16 @@ def mooseReadSBML(filepath, loadpath, solver="ee",validate="on"): """ global foundLibSBML_ if not foundLibSBML_: - print('No python-libsbml found.' - '\nThis module can be installed by following command in terminal:' - '\n\t easy_install python-libsbml' - '\n\t apt-get install python-libsbml' + print('[WARN] No python-libsbml found.' + '\nThis module can be installed by using `pip` in terminal:' + '\n\t $ pip install python-libsbml --user' ) return moose.element('/') if not os.path.isfile(filepath): - print('%s is not found ' % filepath) + pu.warn('%s is not found ' % filepath) return moose.element('/') - with open(filepath, "r") as filep: loadpath = loadpath[loadpath.find('/')+1:] loaderror = None @@ -118,11 +119,11 @@ def mooseReadSBML(filepath, loadpath, solver="ee",validate="on"): if tobecontinue: level = document.getLevel() version = document.getVersion() - print(("\n" + "File: " + filepath + " (Level " + - str(level) + ", version " + str(version) + ")")) + pu.info("File: " + filepath + " (Level " + + str(level) + ", version " + str(version) + ")") model = document.getModel() - if (model is None): - print("No model present.") + if model is None: + pu.error("No model present.") return moose.element('/') else: @@ -149,7 +150,8 @@ def mooseReadSBML(filepath, loadpath, solver="ee",validate="on"): groupInfo = {} funcDef = {} modelAnnotaInfo = {} - comptSbmlidMooseIdMap = {} + #comptSbmlidMooseIdMap = {} + comptSbmlidMooseIdMap = dict() globparameterIdValue = {} mapParameter(model, globparameterIdValue) @@ -180,45 +182,45 @@ def mooseReadSBML(filepath, loadpath, solver="ee",validate="on"): # as while reading in GUI the model will show up untill # built which is not correct print "Deleted rest of the # model" - print((" model: " + str(model))) - print(("functionDefinitions: " + - str(model.getNumFunctionDefinitions()))) - print((" unitDefinitions: " + - str(model.getNumUnitDefinitions()))) - print((" compartmentTypes: " + - str(model.getNumCompartmentTypes()))) - print((" specieTypes: " + - str(model.getNumSpeciesTypes()))) - print((" compartments: " + - str(model.getNumCompartments()))) - print((" species: " + - str(model.getNumSpecies()))) - print((" parameters: " + - str(model.getNumParameters()))) - print((" initialAssignments: " + - str(model.getNumInitialAssignments()))) - print((" rules: " + - str(model.getNumRules()))) - print((" constraints: " + - str(model.getNumConstraints()))) - print((" reactions: " + - str(model.getNumReactions()))) - print((" events: " + - str(model.getNumEvents()))) + print(" model: " + str(model)) + print("functionDefinitions: " + + str(model.getNumFunctionDefinitions())) + print(" unitDefinitions: " + + str(model.getNumUnitDefinitions())) + print(" compartmentTypes: " + + str(model.getNumCompartmentTypes())) + print(" specieTypes: " + + str(model.getNumSpeciesTypes())) + print(" compartments: " + + str(model.getNumCompartments())) + print(" species: " + + str(model.getNumSpecies())) + print(" parameters: " + + str(model.getNumParameters())) + print(" initialAssignments: " + + str(model.getNumInitialAssignments())) + print(" rules: " + + str(model.getNumRules())) + print(" constraints: " + + str(model.getNumConstraints())) + print(" reactions: " + + str(model.getNumReactions())) + print(" events: " + + str(model.getNumEvents())) print("\n") moose.delete(basePath) loadpath = moose.Shell('/') - #return basePath, "" + loaderror = msgCmpt+str(msgRule)+msgReac+noRE if loaderror != "": loaderror = loaderror return moose.element(loadpath), loaderror else: - print("Validation failed while reading the model."+"\n"+errorFlag) + print("Validation failed while reading the model.\n"+errorFlag) if errorFlag != "": - return moose.element('/'),errorFlag + return moose.element('/'), errorFlag else: - return moose.element('/'), "This document is not valid SBML" + return moose.element('/'), "This document is not a valid SBML" def checkFuncDef(model): funcDef = {} @@ -277,7 +279,7 @@ def checkGroup(basePath,model,comptSbmlidMooseIdMap): moosegrpinfo = moose.Annotator(moosegrp.path+'/info') moosegrpinfo.color = groupAnnoInfo["bgColor"] else: - print ("Compartment not found") + print ("Group's compartment not found in xml file") if p.getKind() == 2: if p.getId() not in groupInfo: memlists = [] @@ -932,23 +934,17 @@ def unitsforRates(model): def getMembers(node, ruleMemlist): msg = "" found = True + if node == None: pass + elif node.getType() == libsbml.AST_POWER: pass elif node.getType() == libsbml.AST_FUNCTION: - #print " function" - #funcName = node.getName() - #funcValue = [] - #functionfound = False for i in range(0,node.getNumChildren()): - #functionfound = True - #print " $$ ",node.getChild(i).getName() - #funcValue.append(node.getChild(i).getName()) getMembers(node.getChild(i),ruleMemlist) - #funcKL[node.getName()] = funcValue - + elif node.getType() == libsbml.AST_PLUS: #print " plus ", node.getNumChildren() if node.getNumChildren() == 0: @@ -992,7 +988,6 @@ def getMembers(node, ruleMemlist): for i in range(1, node.getNumChildren()): # Multiplication getMembers(node.getChild(i), ruleMemlist) - elif node.getType() == libsbml.AST_LAMBDA: #In lambda get Bvar values and getRighChild which will be kineticLaw if node.getNumChildren() == 0: @@ -1009,9 +1004,15 @@ def getMembers(node, ruleMemlist): for i in range (0,node.getNumBvars()): ruleMemlist.append(node.getChild(i).getName()) #funcD[funcName] = {"bvar" : bvar, "MathML":node.getRightChild()} + elif node.getType() == libsbml.AST_INTEGER: + #value is constant + #ruleMemlist.append(node.getValue()) + pass + elif node.getType() == libsbml.AST_FUNCTION_POWER: msg = msg + "\n moose is yet to handle \""+node.getName() + "\" operator" found = False + elif node.getType() == libsbml.AST_FUNCTION_PIECEWISE: #print " piecewise ", libsbml.formulaToL3String(node) msg = msg + "\n moose is yet to handle \""+node.getName() + "\" operator" @@ -1027,7 +1028,6 @@ def getMembers(node, ruleMemlist): getMembers(rchild, ruleMemlist) ''' else: - #print(" this case need to be handled", node.getName()) msg = msg + "\n moose is yet to handle \""+node.getName() + "\" operator" found = False # if len(ruleMemlist) > 2: @@ -1104,7 +1104,7 @@ def createRules(model, specInfoMap, globparameterIdValue): funcId.numVars = numVars + 1 elif not(i in globparameterIdValue): - msg = msg + "check the variable name in mathML, this object neither pool or a constant \"" + i+"\" in assignmentRule " +rule.getVariable() + msg = msg + "check the variable name in mathML, this object neither pool or a constant \"" + str(i)+"\" in assignmentRule " +rule.getVariable() exp = rule.getFormula() exprOK = True @@ -1112,7 +1112,6 @@ def createRules(model, specInfoMap, globparameterIdValue): for mem in ruleMemlist: if (mem in specInfoMap): #exp1 = exp.replace(mem, str(speFunXterm[mem])) - #print " mem ",mem, "$ ", speFunXterm[mem], "$$ ",exp exp1 = re.sub(r'\b%s\b'% (mem), speFunXterm[mem], exp) exp = exp1 elif(mem in globparameterIdValue): @@ -1437,10 +1436,10 @@ def createCompartment(basePath, model, comptSbmlidMooseIdMap): mooseCmptId = moose.CubeMesh(basePath.path+'/'+name) mooseCmptId.volume = (msize * unitfactor) - - comptSbmlidMooseIdMap[sbmlCmptId] = { - "MooseId": mooseCmptId, "spatialDim": dimension, "size": msize} - + #both compartment name and Id is mapped to the values + comptSbmlidMooseIdMap.update(dict.fromkeys([sbmlCmptId,name], {"MooseId": mooseCmptId, "spatialDim": dimension, "size": msize})) + #comptSbmlidMooseIdMap[sbmlCmptId] = { + # "MooseId": mooseCmptId, "spatialDim": dimension, "size": msize} for key,value in endo_surr.items(): if value in comptSbmlidMooseIdMap: endomesh = comptSbmlidMooseIdMap[key]["MooseId"] diff --git a/python/moose/SBML/writeSBML.py b/python/moose/SBML/writeSBML.py index 0f021c67..9f25ca34 100644 --- a/python/moose/SBML/writeSBML.py +++ b/python/moose/SBML/writeSBML.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -''' +r''' ******************************************************************* * File: writeSBML.py * Description: @@ -13,11 +13,17 @@ ** copyright (C) 2003-2017 Upinder S. Bhalla. and NCBS Created : Friday May 27 12:19:00 2016(+0530) Version -Last-Updated: Tue 29 Jan 15:15:10 2019(+0530) +Last-Updated: Wed 8 Jan 14:15:10 2020(+0530) By: HarshaRani **********************************************************************/ /**************************** +2020 +Jan 08: added function to write Concchannel in form of MMenz + Km in the kinetic law for MMenz is written to the power based on the number of substrate 2019 +July 18: added a call for autolayout, this was required for cspace model while trying to write from cmd line + while writting file, the filepath is checked + now even for cplxpool's x and y co-ordinates,diff and motor constant are added Jan 29: getColor are taken from chemConnectUtil, group's width and height are written 2018 Dec 07: using fixXreac's restoreXreacs function to remove xfer @@ -25,7 +31,7 @@ Nov 30: group id is changed from name to moose_id and group.name is added along with annotation for group listing Nov 22: searched for _xfer_ instead of xfer Nov 12: xfer cross compartment molecules are not written to SBML instead written the original molecule also for connecting Reaction and Enzyme -Nov 06: All the Mesh Cyl,Cube,Neuro,Endo Mesh's can be written into SBML format with annotation field where Meshtype\ +Nov 06: All the Mesh Cyl,Cube,Neuro,Endo Mesh's can be written into SBML format with annotation field where Meshtype numDiffCompts,isMembraneBound and surround are written out. For EndoMesh check made to see surround is specified Oct 20: EndoMesh added to SBML @@ -42,14 +48,14 @@ convertSpecialChar for setId and convertSpecialCharshot for setName. specialChar like /,\,[,],space are not allowed as moose doesn't take Aug 3 : Added recalculatecoordinates,cleanup in groupName - ''' + import sys import re import os import moose from moose.SBML.validation import validateModel -from moose.chemUtil.chemConnectUtil import xyPosition,mooseIsInstance,findCompartment,getColor,setupItem +from moose.chemUtil.chemConnectUtil import xyPosition,mooseIsInstance,findCompartment,getColor,setupItem,setupMeshObj from moose.chemUtil.graphUtils import * from moose.fixXreacs import restoreXreacs import numpy as np @@ -61,6 +67,21 @@ except Exception as e: pass +def checkPath( dirName): + path = dirName + if (dirName == "~" or not dirName ): + if dirName: + dirName = os.path.expanduser(dirName) + else: + dirName = os.getcwd() + + if os.access(dirName, os.W_OK) is not True: + dirName = os.getcwd() + print(path +" not writable, writting to "+dirName+ " directory") + return dirName + else: + return dirName + def mooseWriteSBML(modelpath, filename, sceneitems={}): global foundLibSBML_ msg = " " @@ -74,10 +95,12 @@ def mooseWriteSBML(modelpath, filename, sceneitems={}): #sbmlDoc = SBMLDocument(3, 1) filepath, filenameExt = os.path.split(filename) + filepath = checkPath(filepath) if filenameExt.find('.') != -1: filename = filenameExt[:filenameExt.find('.')] else: filename = filenameExt + # validatemodel sbmlOk = False global spe_constTrue @@ -144,6 +167,7 @@ def mooseWriteSBML(modelpath, filename, sceneitems={}): if modelAnno: cremodel_.setAnnotation(modelAnno) groupInfo = {} + reacGroup = {} compterrors ="" compartexist, groupInfo,compterrors = writeCompt(modelpath, cremodel_) @@ -151,8 +175,9 @@ def mooseWriteSBML(modelpath, filename, sceneitems={}): species = writeSpecies( modelpath,cremodel_,sbmlDoc,sceneitems,groupInfo) if species: writeFunc(modelpath, cremodel_) - reacGroup = {} + writeChannel(modelpath,cremodel_,sceneitems,groupInfo) + writeReac(modelpath, cremodel_, sceneitems,groupInfo) writeEnz(modelpath, cremodel_, sceneitems,groupInfo) @@ -188,13 +213,14 @@ def mooseWriteSBML(modelpath, filename, sceneitems={}): if moose.exists(key.path+'/info'): ginfo = moose.element(key.path+'/info') + textColor,color = getColor(ginfo) if ginfo.height and ginfo.width: grpAnno = grpAnno + "" + str(ginfo.x) + "\n" grpAnno = grpAnno + "" + str(ginfo.y) + "\n" grpAnno = grpAnno + "" + str(ginfo.width) + "\n" grpAnno = grpAnno + "" + str(ginfo.height) + "\n" if ginfo.color: - grpAnno = grpAnno + "" + ginfo.color + "\n" + grpAnno = grpAnno + "" + color + "\n" if ginfo.notes: grpAnno = grpAnno + "" + ginfo.notes + "\n" grpAnno = grpAnno + "" @@ -207,11 +233,15 @@ def mooseWriteSBML(modelpath, filename, sceneitems={}): consistencyMessages = "" SBMLok = validateModel(sbmlDoc) if (SBMLok): - writeTofile = filepath + "/" + filename + '.xml' + if filepath != [r" ", r"\/", r"/"]: + writeTofile = filepath + "/" + filename + '.xml' + else: + writeTofile = filename+'.xml' + #writeTofile = filepath + "/" + filename + '.xml' writeSBMLToFile(sbmlDoc, writeTofile) return True, consistencyMessages, writeTofile - if (not SBMLok): + else: #cerr << "Errors encountered " << endl consistencyMessages = "Errors encountered" return -1, consistencyMessages @@ -220,7 +250,102 @@ def mooseWriteSBML(modelpath, filename, sceneitems={}): return False, compterrors else: return False,"Atleast one compartment should exist to write SBML" - + +def writeChannel(modelpath, cremodel_, sceneitems,groupInfo): + for chan in moose.wildcardFind(modelpath + '/##[0][ISA=ConcChan]'): + chanannoexist = False + chanGpnCorCol = " " + cleanChanname = convertSpecialChar(chan.name) + compt = "" + notesE = "" + groupName = moose.element("/") + + if moose.exists(chan.path + '/info'): + Anno = moose.Annotator(chan.path + '/info') + notesE = Anno.notes + element = moose.element(chan) + ele = getGroupinfo(element) + ele = findGroup_compt(element) + chanAnno = " " + if ele.className == "Neutral" or sceneitems or Anno.x or Anno.y: + chanannoexist = True + if chanannoexist: + chanAnno = "\n" + if ele.className == "Neutral": + groupName = ele + if sceneitems: + #Saved from GUI, then scene co-ordinates are passed + chanGpnCorCol = chanGpnCorCol + "" + \ + str(sceneitems[chan]['x']) + "\n" + \ + "" + \ + str(sceneitems[chan]['y'])+ "\n" + else: + #Saved from cmdline,genesis coordinates are kept as its + # SBML, cspace, python, then auto-coordinates are done + #and coordinates are updated in moose Annotation field + chanGpnCorCol = chanGpnCorCol + "" + \ + str(Anno.x) + "\n" + \ + "" + \ + str(Anno.y)+ "\n" + chanGpnCorCol = chanGpnCorCol+""+str(chan.permeability)+"\n" + chanSub = chan.neighbors["in"] + chanPrd = chan.neighbors["out"] + if (len(chanSub) != 0 and len(chanPrd) != 0): + chanCompt = findCompartment(chan) + if not isinstance(moose.element(chanCompt), moose.ChemCompt): + return -2 + else: + compt = chanCompt.name + "_" + \ + str(chanCompt.getId().value) + "_" + \ + str(chanCompt.getDataIndex()) + "_" + + channel = cremodel_.createReaction() + if notesE != "": + cleanNotesE = convertNotesSpecialChar(notesE) + notesStringE = "\n \t \t" + \ + cleanNotesE + "\n\t " + channel.setNotes(notesStringE) + + chansetId = str(idBeginWith(cleanChanname + + "_" + + str(chan.getId().value) + + "_" + + str(chan.getDataIndex()) + + "_")) + channel.setId(chansetId) + + if groupName != moose.element('/'): + if groupName not in groupInfo: + groupInfo[groupName]=[chansetId] + else: + groupInfo[groupName].append(chansetId) + + channel.setName(str(idBeginWith(convertSpecialCharshot(chan.name)))) + channel.setReversible(True) + channel.setFast(False) + if chanannoexist: + canAnno = chanAnno + chanGpnCorCol + chanAnno = "\n" + \ + chanGpnCorCol + "" + channel.setAnnotation(chanAnno) + noofSub, sRateLawS = getSubprd(cremodel_, False, "sub", chanSub) + # Modifier + chanMod = chan.neighbors["setNumChan"] + noofMod, sRateLawM = getSubprd(cremodel_, False, "enz", chanMod) + + noofPrd, sRateLawP = getSubprd(cremodel_, False, "prd", chanPrd) + + kl = channel.createKineticLaw() + + fRate_law = compt + " * ( Permeability) * " + sRateLawM + " * (" + sRateLawS+ " - " + sRateLawP +")" + kl.setFormula(fRate_law) + kl.setNotes( + "\n\t\t" + + fRate_law + + "\n \t ") + + channelUnit = permeablUnit(cremodel_) + printParameters(kl, "Permeability", chan.permeability, channelUnit) def writeEnz(modelpath, cremodel_, sceneitems,groupInfo): for enz in moose.wildcardFind(modelpath + '/##[0][ISA=EnzBase]'): enzannoexist = False @@ -510,8 +635,14 @@ def writeEnz(modelpath, cremodel_, sceneitems,groupInfo): enzPrd = enz.neighbors["prd"] noofPrd, sRateLawP = getSubprd(cremodel_, False, "prd", enzPrd) kl = enzyme.createKineticLaw() - fRate_law = compt + " * ( kcat * " + sRateLawS + " * " + sRateLawM + \ - " / ( Km" + " + " + sRateLawS + "))" + #rate_law = clean_name + "^" + str(count) + fRate_law = compt + " * ( kcat * " + sRateLawS + " * " + sRateLawM + "/(Km" + + if len(enzSub) > 1: + fRate_law = fRate_law +"^" +str(len(enzSub)) + print("enzyme ",enzyme.name, "number of substrate is greater than 1, kinetics Law Km is written to the power of substrate assumed that km value is factored") + fRate_law = fRate_law +" + " + sRateLawS + "))" + kl.setFormula(fRate_law) kl.setNotes( "\n\t\t" + @@ -529,6 +660,38 @@ def printParameters(kl, k, kvalue, unit): para.setValue(kvalue) para.setUnits(unit) +def permeablUnit(cremodel_): + unit_stream = "litre_per_mmole_per_second" + lud = cremodel_.getListOfUnitDefinitions() + flag = False + for i in range(0, len(lud)): + ud = lud.get(i) + if (ud.getId() == unit_stream): + flag = True + break + if (not flag): + unitdef = cremodel_.createUnitDefinition() + unitdef.setId(unit_stream) + + unit = unitdef.createUnit() + unit.setKind(UNIT_KIND_LITRE) + unit.setExponent(1) + unit.setMultiplier(1) + unit.setScale(0) + + unit = unitdef.createUnit() + unit.setKind(UNIT_KIND_MOLE) + unit.setExponent(-1) + unit.setMultiplier(1) + unit.setScale(-3) + + unit = unitdef.createUnit() + unit.setKind(UNIT_KIND_SECOND) + unit.setExponent(-1) + unit.setMultiplier(1) + unit.setScale(0) + return unit_stream + def KmUnit(cremodel_): unit_stream = "mmole_per_litre" lud = cremodel_.getListOfUnitDefinitions() @@ -622,7 +785,7 @@ def getSubprd(cremodel_, mobjEnz, type, neighborslist): rate_law = processRateLaw( reacPrdCou, cremodel_, noofPrd, "prd", mobjEnz) return len(reacPrd), rate_law - elif type == "enz": + elif type == "enz" or type == "chan": enzModifier = neighborslist enzModCou = Counter(enzModifier) noofMod = len(enzModCou) @@ -952,6 +1115,14 @@ def writeSpecies(modelpath, cremodel_, sbmlDoc, sceneitems,speGroup): if spename.find( "cplx") != -1 and isinstance(moose.element(spe.parent), moose.EnzBase): enz = spe.parent + if not moose.exists(spe.path+'/info'): + cplxinfo = moose.Annotator(spe.path+'/info') + enzpath = moose.element(spe.parent.path+'/info') + + cplxinfo.x = moose.element(moose.element(spe.parent.path+'/info').x) + + cplxinfo.y = int((moose.element(spe.parent.path+'/info').y))+10 + if (moose.element(enz.parent), moose.PoolBase): # print " found a cplx name ",spe.parent, # moose.element(spe.parent).parent @@ -994,6 +1165,7 @@ def writeSpecies(modelpath, cremodel_, sbmlDoc, sceneitems,speGroup): s1.setConstant(False) s1.setUnits("substance") s1.setHasOnlySubstanceUnits(False) + if moose.exists(spe.path + '/info'): Anno = moose.Annotator(spe.path + '/info') if Anno.notes != "": @@ -1034,10 +1206,18 @@ def writeSpecies(modelpath, cremodel_, sbmlDoc, sceneitems,speGroup): if Anno.textColor: speciAnno = speciAnno + "" + \ Anno.textColor + "\n" + speciAnno = speciAnno + "" + str(spe.diffConst) + "\n" speciAnno = speciAnno + "" + str(spe.motorConst)+ "\n" speciAnno = speciAnno + "" s1.setAnnotation(speciAnno) + else: + #E.g cplx doesn't have info field but findsim layout expecting diffConstant and motorConstant. + speciAnno = "\n" + speciAnno = speciAnno + "" + str(0.0) + "\n" + speciAnno = speciAnno + "" + str(0.0)+ "\n" + speciAnno = speciAnno + "" + s1.setAnnotation(speciAnno) return True @@ -1205,13 +1385,19 @@ def recalculatecoordinates(modelpath, mObjlist,xcord,ycord): else: srcdesConnection = {} setupItem(modelpath,srcdesConnection) + meshEntry,xmin,xmax,ymin,ymax,positionInfoExist,sceneitems = setupMeshObj(modelpath) + if not positionInfoExist: + + sceneitems = autoCoordinates(meshEntry,srcdesConnection) + sceneitems = autoCoordinates(meshEntry,srcdesConnection) + #print srcdesConnection ''' #meshEntry,xmin,xmax,ymin,ymax,positionInfoExist,sceneitems = setupMeshObj(modelpath) #if not positionInfoExist: #cmin,cmax,sceneitems = autoCoordinates(meshEntry,srcdesConnection) sceneitems = autoCoordinates(meshEntry,srcdesConnection) - ''' + ''' def writeUnits(cremodel_): unitVol = cremodel_.createUnitDefinition() unitVol.setId("volume") diff --git a/python/moose/__init__.py b/python/moose/__init__.py index 3c398033..8749afda 100644 --- a/python/moose/__init__.py +++ b/python/moose/__init__.py @@ -1,18 +1,23 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import, division, print_function -# Use this format in all logger inside logger. Define it before any moose -# related module is imported. -LOGGING_FORMAT = '%(asctime)s %(message)s' - -# Bring everything from c++ module to global namespace. Not everything is -# imported by the pervios import statement. +# Bring everything from c++ module to global namespace. from moose._moose import * # Bring everything from moose.py to global namespace. -# IMP: It will overwrite any c++ function with the same name. +# IMP: It will overwrite any c++ function with the same name. We can override +# some C++ here. from moose.moose import * from moose.server import * +# SBML and NML2 support. +from moose.model_utils import * + # create a shorthand for version() call here. __version__ = version() + +# C++ core override +from moose.wrapper import * + +# Import moose test. +from moose.moose_test import test diff --git a/python/moose/alternate.py b/python/moose/alternate.py deleted file mode 100644 index a03f97a6..00000000 --- a/python/moose/alternate.py +++ /dev/null @@ -1,1037 +0,0 @@ -# -*- coding: utf-8 -*- -# moose.py --- -# -# Filename: moose.py -# Description: THIS IS OUTDATED CODE AND KEPT FOR HISTORICAL REFERENCE -# moose.py in this directory is the replacement for this -# script. -# -# Author: Subhasis Ray -# Maintainer: -# Copyright (C) 2010 Subhasis Ray, all rights reserved. -# Created: Sat Mar 12 14:02:40 2011 (+0530) -# Version: -# Last-Updated: Mon Apr 9 03:32:28 2012 (+0530) -# By: Subhasis Ray -# Update #: 1672 -# URL: -# Keywords: -# Compatibility: -# -# - -# Commentary: -# -# THIS IS OUTDATED CODE AND KEPT FOR HISTORICAL REFERENCE -# -# - -# Change log: -# -# -# - -# Code: - -""" -MOOSE = Multiscale Object Oriented Simulation Environment. - -Classes: - -Id:pf[key] - -this is the unique identifier of a MOOSE object. Note that you -can create multiple references to the same MOOSE object in Python, but -as long as they have the same Id, they all point to the same entity in -MOOSE. - -Methods: - -getValue() -- unsigned integer representation of id - -getPath() -- string representing the path corresponding this id - -getShape -- tuple containing the dimensions of this id - -Id also implements part of the sequence protocol: - -len(id) -- the first dimension of id. - -id[n] -- the n-th ObjId in id. - -id[n1:n2] -- a tuple containing n1 to n2-th (exclusive) ObjId in id. - -objid in id -- True if objid is contained in id. - - - -ObjId: - -Unique identifier of an element in a MOOSE object. It has three components: - -Id id - the Id containing this element - -unsigned integer dataIndex - index of this element in the container - -unsigned integer fieldIndex - if this is a tertiary object, i.e. acts -as a field in another element (like synapse[0] in IntFire[1]), then -the index of this field in the containing element. - -Methods: - -getId -- Id object containing this ObjId. - -getDataIndex() -- unsigned integer representing the index of this -element in containing MOOSE object. - -getFieldIndex() -- unsigned integer representing the index of this -element as a field in the containing Element. - -getFieldType(field) -- human readable datatype information of field - -getField(field) -- get value of field - -setField(field, value) -- assign value to field - -getFieldNames(fieldType) -- tuple containing names of all the fields -of type fieldType. fieldType can be valueFinfo, lookupFinfo, srcFinfo, -destFinfo and sharedFinfo. If nothing is passed, a union of all of the -above is used and all the fields are returned. - -connect(srcField, destObj, destField, msgType) -- connect srcField of -this element to destField of destObj. - -getMsgSrc(fieldName) -- return a tuple containing the ObjIds of all -the elements from which a message is entering the field specified by -fieldName. - -getMsgDesr(fieldName) -- return a tuple containing list of ObjIds of -elements that recieve messages from the fieldName of this element. - - -NeutralArray: - -The base class. Each NeutralArray object has an unique Id (field _id) and -that is the only data directly visible under Python. All operation are -done on the objects by calling functions on the Id. - -A NeutralArray object is actually an array. The individual elements in a -NeutralArray are of class Neutral. To access these individual -elements, you can index the NeutralArray object. - -A NeutralArray object can be constructed in many ways. The most basic one -being: - -neutral = moose.NeutralArray('my_neutral_object', [3]) - -This will create a NeutralArray object with name 'my_neutral_object' -containing 3 elements. The object will be created as a child of the -current working entity. Any class derived from NeutralArray can also be -created using the same constructor. Actually it takes keyword -parameters to do that: - -intfire = moose.NeutralArray(path='/my_neutral_object', dims=[3], type='IntFire') - -will create an IntFire object of size 3 as a child of the root entity. - -If the above code is already executed, - -duplicate = moose.NeutralArray(intfire) - -will create a duplicate reference to the existing intfire object. They -will share the same Id and any changes made via the MOOSE API to one -will be effective on the other. - -Neutral -- The base class for all elements in object of class -NeutralArray or derivatives of NeutralArray. A Neutral will always point -to an index in an existing entity. The underlying data is ObjId (field -oid_) - a triplet of id, dataIndex and fieldIndex. Here id is the Id -of the NeutralArray object containing this element. dataIndex is the index -of this element in the container. FieldIndex is a tertiary index and -used only when this element acts as a field of another -element. Otherwise fieldIndex is 0. - -Indexing a NeutralArray object returns a Neutral. - -i_f = intfire[0] will return a reference to the first element in the -IntFire object we created earlier. All field-wise operations are done -on Neutrals. - -A neutral object (and its derivatives) can also be created in the -older way by specifying a path to the constructor. This path may -contain an index. If there is a pre-existing NeutralArray object with -the given path, then the index-th item of that array is returned. If -the target object does not exist, but all the objects above it exist, -then a new Array object is created and its first element is -returned. If an index > 0 is specified in this case, that results in -an IndexOutOfBounds exception. If any of the objects higher in the -hierarchy do not exist (thus the path up to the parent is invalid), a -NameError is raised. - -a = Neutral('a') # creates /a -b = IntFire(a/b') # Creates /a/b -c = IntFire(c/b') # Raises NameError. -d = NeutralArray('c', 10) -e = Neutral('c[9]') # Last element in d - -Fields: - -childList - a list containing the children of this object. - -className - class of the underlying MOOSE object. The corresponding -field in MOOSE is 'class', but in Python that is a keyword, so we use -className instead. This is same as Neutral.getField('class') - - -dataIndex - data index of this object. This should not be needed for -normal use. - -dimensions - a tuple representation dimensions of the object. If it is -empty, this is a singleton object. - -fieldIndex - fieldIndex for this object. Should not be needed for -ordinary use. - -fieldNames - list fields available in the underlying MOOSE object. - - - -Methods: - -children() - return the list of Ids of the children - -connect(srcField, destObj, destField) - a short hand and backward -compatibility function for moose.connect(). It creates a message -connecting the srcField on the calling object to destField on the dest -object. - -getField(fieldName) - return the value of the specified field. - -getFieldNames() - return a list of the available field names on this object - -getFieldType(fieldName) - return the data type of the specified field. - -getSources(fieldName) - return a list of (source_element, source_field) for all -messages coming in to fieldName of this object. - -getDestinations(fieldName) - return a list of (destination_elemnt, destination_field) -for all messages going out of fieldName. - - -More generally, Neutral and all its derivatives will have a bunch of methods that are -for calling functions via destFinfos. help() for these functions -should show something like: - - lambda self, arg_0_{type}, arg_1_{type} unbound moose.{ClassName} method - -These are dynamically defined methods, and calling them with the right -parameters will cause the corresponding moose function to be -called. Note that all parameters are converted to strings, so you may -loose some precision here. - -[Comment - subha: This explanation is no less convoluted than the -implementation itself. Hopefully I'll have the documentation -dynamically dragged out of Finfo documentation in future.] - -module functions: - -element(path) - returns a reference to an existing object converted to -the right class. Raises NameError if path does not exist. - -arrayelement(path) - returns a reference to an existing object -converted to the corresponding Array class. Raises NameError if path -does not exist. - -copy(src=, dest=, name=, n=, -copyMsg= of every object that -matches on clock no. . - -setClock(tick, dt) -- set dt of clock no . - -start(runtime) -- start simulation of time. - -reinit() -- reinitialize simulation. - -stop() -- stop simulation - -isRunning() -- true if simulation is in progress, false otherwise. - -exists(path) -- true if there is a pre-existing object with the specified path. - -loadModel(filepath, modelpath) -- load file in into node - of the moose model-tree. - -setCwe(obj) -- set the current working element to - which can be -either a string representing the path of the object in the moose -model-tree, or an Id. -cwe(obj) -- an alias for setCwe. - -getCwe() -- returns Id of the current working element. -pwe() -- an alias for getCwe. - -showfields(obj) -- print the fields in object in human readable format - -le(obj) -- list element under object, if no parameter specified, list -elements under current working element - -""" -from __future__ import print_function -from functools import partial -import warnings -from collections import defaultdict -from . import _moose -from ._moose import __version__, VERSION, SVN_REVISION, useClock, setClock, start, reinit, stop, isRunning, loadModel, getFieldDict, getField, Id, ObjId, exists, seed -from ._moose import wildcardFind as _wildcardFind # We override the original -import __main__ as main - -sequence_types = [ 'vector', - 'vector', - 'vector', - 'vector', - 'vector', - 'vector', - 'vector', - 'vector', - 'vector' ] -known_types = ['void', - 'char', - 'short', - 'int', - 'unsigned int', - 'double', - 'float', - 'long', - 'unsigned long', - 'string', - 'Id', - 'ObjId'] + sequence_types - -# Dict of available MOOSE class names. This is faster for look-up -_moose_classes = dict([(child[0].name, True) for child in Id('/classes')[0].getField('children')]) - -# class _MooseDescriptor(object): -# """Descriptor to give access to MOOSE class' ValueFinfo attributes""" -# def __init__(self, name): -# self.name = name - -# def __get__(self, obj, objtype=None): -# return obj.oid_.getField(self.name) - -# def __set__(self, obj, value): -# obj.oid_.setField(self.name, value) - -# def __delete__(self, obj): -# raise AttributeError('ValueFinfos cannot be deleted.') - -class _LFDescriptor(object): - def __init__(self, name): - self.name = name - def __get__(self, obj, objtype=None): - return _LookupField(obj.oid_, self.name) - -class _LookupField(object): - def __init__(self, obj, name): - self.name = name - self.obj = obj - def __getitem__(self, key): - if isinstance(self.obj, ObjId): - return self.obj.getLookupField(self.name, key) - elif isinstance(self.obj, Neutral): - return self.obj.oid_.getLookupField(self.name, key) - else: - raise TypeError('obj is neither an ObjId nor a Neutral or subclass instance.') - def __setitem__(self, key, value): - if isinstance(self.obj, ObjId): - self.obj.setLookupField(self.name, key, value) - elif isinstance(self.obj, Neutral): - self.obj.oid_.setLookupField(self.name, key, value) - else: - raise TypeError('obj is neither an ObjId nor a Neutral or subclass instance.') - -class NeutralArray(object): - """ - The base class. Each NeutralArray object has an unique Id (field - id_) and that is the only data directly visible under Python. All - operation are done on the objects by calling functions on the Id. - - A NeutralArray object is actually an array. The individual - elements in a NeutralArray are of class Neutral. To access these - individual elements, you can index the NeutralArray object. - - """ - def __init__(self, *args, **kwargs): - """ - A NeutralArray object can be constructed in many ways. The - most basic one being: - - neutral = moose.NeutralArray('my_neutral_object', [3]) - - This will create a NeutralArray object with name - 'my_neutral_object' containing 3 elements. The object will be - created as a child of the current working entity. Any class - derived from NeutralArray can also be created using the same - constructor. Actually it takes keyword parameters to do that: - - intfire = moose.NeutralArray(path='/my_neutral_object', dims=[3], type='IntFire') - - will create an IntFire object of size 3 as a child of the root entity. - - If the above code is already executed, - - duplicate = moose.NeutralArray(intfire) - - will create a duplicate reference to the existing intfire - object. They will share the same Id and any changes made via - the MOOSE API to one will be effective on the other. - - """ - path = None - dims = None - self.id_ = None - try: - className = kwargs['type'] - self.className = className - except KeyError: - # This code is messy and depends on the class name. I - # could not find a way to pass the element data type to - # the class definition dynamically - if not hasattr(self, 'className'): - self.className = 'Neutral' - try: - dims = kwargs['dims'] - except KeyError: - pass - try: - path = kwargs['path'] - except KeyError: - pass - if len(args) > 0: - if isinstance(args[0], str): - path = args[0] - elif isinstance(args[0], Id): - self.id_ = args[0] - elif isinstance(args[0], int): - self.id_ = Id(args[0]) - if len(args) > 1: - dims = args[1] - if len(args) > 2: - self.className = args[2] - # No existing Array element ot Id specified, create new - # ArrayElement - if self.id_ is None: - if path is None: - raise TypeError('A string path or an existing Id or an int value for existing Id must be the first argument to __init__') - if exists(path): - self.id_ = _moose.Id(path=path) - # Check if specified dimensions match the existing - # object's dimensions - if dims is not None: - shape = self.id_.getShape() - if isinstance(dims, int): - if shape[0] != dims: - raise ValueError('Specified dimensions do not match that of existing array object') - else: - if len(shape) != len(dims): - raise ValueError('Specified dimensions do not match that of existing array object') - for ii in range(len(shape)): - if shape[ii] != dims[ii]: - raise ValueError('Specified dimensions do not match that of existing array object') - else: - dims = (1) - # Create a new ArrayElement - _base_class = self.__class__ - _class_name = self.__class__.__name__ - if _class_name.endswith('Array'): - _class_name = _class_name[:-len('Array')] - # For classes extended in Python get to the first MOOSE base class - while _class_name not in _moose_classes: - _base_class = self.__base__ - if _base_class == object: - raise TypeError('Class %s does not inherit any MOOSE class.' % (self.__class__.__name__)) - _class_name = _base_class.__name__ - if _class_name.endswith('Array'): - _class_name = _class_name[:-len('Array')] - self.id_ = _moose.Id(path=path, dims=dims, type=_class_name) - # Check for conversion from instance of incompatible MOOSE - # class. - orig_classname = self.id_[0].getField('class') + 'Array' - if self.__class__.__name__ != orig_classname: - orig_class = eval(orig_classname) - self_class = self.__class__ - while self_class != object and self_class not in orig_class.mro(): - self_class = self_class.__base__ - if self_class == object: - self.id_ = None - raise TypeError('Cannot convert %s to %s' % (orig_class, self.__class__)) - - def getFieldNames(self, ftype=''): - """Return a list of fields available in this object. - - Parameters: - - str ftype -- (default '') category of field, valid values are: - valueFinfo, lookupFinfo, srcFinfo, destFinfo or sharedFinfo. - - If empty string or not specified, returns names of fields from - all categories. - """ - - return self.id_[0].getFieldNames(ftype) - - def getFieldType(self, field, ftype=''): - """Return the data type of the field as a string.""" - return self.id_[0].getFieldType(field, ftype) - - def __getitem__(self, index): - objid = self.id_[index] - retclass = eval(self.id_[0].getField('class')) - ret = retclass(objid) - return ret - - def __len__(self): - return len(self.id_) - - def __contains__(self, other): - if isinstance(other, Neutral): - return other.oid_ in self.id_ - elif isinstance(other, ObjId): - return other in self.id_ - else: - return False - - def __repr__(self): - return self.id_.getPath() - - path = property(lambda self: self.id_.getPath()) - fieldNames = property(lambda self: self.id_[0].getFieldNames('valueFinfo')) - name = property(lambda self: self.id_[0].name) - shape = property(lambda self: self.id_.getShape()) - - - -class Neutral(object): - """Corresponds to a single entry in a NeutralArray. Base class for - all other MOOSE classes for single entries in Array elements. - - A Neutral object wraps an ObjId (field oid_) - a triplet of id, - dataIndex and fieldIndex. Here id is the Id of the NeutralArray object - containing this element. dataIndex is the index of this element in the - container. FieldIndex is a tertiary index and used only when this - element acts as a field of another element. Otherwise fieldIndex is 0. - - Indexing a NeutralArray object returns a Neutral. - - A neutral object (and its derivatives) can also be created in the - older way by specifying a path to the constructor. This path may - contain an index. If there is a pre-existing NeutralArray object - with the given path, then the index-th item of that array is - returned. If the target object does not exist, but all the objects - above it exist, then a new Array object is created and its first - element is returned. If an index > 0 is specified in this case, - that results in an IndexOutOfBounds exception. If any of the - objects higher in the hierarchy do not exist (thus the path up to - the parent is invalid), a NameError is raised. - - a = Neutral('a') # creates /a - b = IntFire(a/b') # Creates /a/b - c = IntFire(c/b') # Raises NameError. - d = NeutralArray('c', 10) - e = Neutral('c[9]') # Last element in d - """ - def __init__(self, *args, **kwargs): - """Initialize a Neutral object. - - Arguments: - - arg1 : A path or an existing ObjId or an Id or a NeutralArray - or another Neutral object. - - path -- a string specifying the path for the Neutral - object. If there is already a Neutral object with the given - path, a reference to that object is created. Otherwise, a new - NeutralArray is created with the given path. In the latter - case, the path must be valid up to the last '/'. For example, - if you specify '/a/b/c', then for correct operation, there - must be an element named 'a' at the top level and a child - element of 'a' named 'b'. This works like 'mkdir' or 'md' - command in some operating systems. - - ObjId -- if the first argument is an ObjId, then the Neutral - object refers to the existing object with the specified ObjId. - - Id -- if the first argument is an Id then the Neutral object - will refer to some entry in the ArrayElement with this Id. The - exact index pointed to will be determined by the second - argument, or the first entry if no second argument is - specified. - - NeutralArray -- Same as Id (as if the Id of the NeutralArray - was passed). - - Neutral -- create a new reference to the existing Neutral - object. - - arg2 : if there is a second argument, then this is taken as - the dataindex into an existing array element. - - arg3: if there is a third argument, this is taken as the - fieldindex into an existing array field. - """ - id_ = None - self.oid_ = None - dindex = None - findex = None - numFieldBits = None - if len(args) >= 1: - if isinstance(args[0], ObjId): - self.oid_ = args[0] - elif isinstance(args[0], Id): - id_ = args[0].getValue() - elif isinstance(args[0], Neutral): - self.oid_ = args[0].oid_ - elif isinstance(args[0], NeutralArray): - id_ = args[0].id_ - elif isinstance(args[0], str): - try: - self.oid_ = _moose.ObjId(args[0]) - except ValueError: - # A non-existing path has been provided. Try to - # construct a singleton array element and create - # reference to the first element. - self_class = self.__class__ - while (self_class.__name__ not in _moose_classes) and (self_class != object): # Handle class extension in Python. - self_class = self_class.__base__ - if self_class == object: - raise TypeError('Class %s does not inherit any MOOSE class.' % (self.__class__.__name__)) - id_ = Id(path=args[0], dims=(1,), type=self_class.__name__) - else: - raise TypeError('First non-keyword argument must be a number or an existing Id/ObjId/Neutral/NeutralArray object or a path.') - if len(args) >= 2: - dindex = args[1] - if len(args) >= 3: - findex = args[2] - if len(args) >= 4: - numFieldBits = args[3] - if (kwargs): - try: - id_ = kwargs['id'] - except KeyError: - pass - try: - dindex = kwargs['dataIndex'] - except KeyError: - pass - try: - findex = kwargs['fieldIndex'] - except KeyError: - pass - try: - numFieldBits = kwargs['numFieldBits'] - except KeyError: - pass - if self.oid_ is None: - if id_ is not None: - if dindex is None: - self.oid_ = _moose.ObjId(id_) - elif findex is None: - self.oid_ = _moose.ObjId(id_, dindex) - elif numFieldBits is None: - self.oid_ = _moose.ObjId(id_, dindex, findex) - else: - self.oid_ = _moose.ObjId(id_, dindex, findex, numFieldBits) - # Check for conversion from instance of incompatible MOOSE - # class. - orig_classname = self.oid_.getField('class') - if self.__class__.__name__ != orig_classname: - orig_class = eval(orig_classname) - self_class = self.__class__ - while self_class != object and self_class not in orig_class.mro(): - self_class = self_class.__base__ - if self_class == object: - self.oid_ = None - raise TypeError('Cannot convert %s to %s' % (orig_class, self.__class__)) - - def getField(self, field): - """Return the field value""" - return self.oid_.getField(field) - - def getFieldType(self, field, ftype=''): - """Return the type of the specified field in human readable format""" - return self.oid_.getFieldType(field, ftype) - - def getFieldNames(self, ftype=''): - """Return a list of the fields of specified fieldType.""" - return self.oid_.getFieldNames(ftype) - - def getNeighbors(self, fieldName): - if fieldName in getFieldDict(self.className): - return [eval('%s("%s")' % (id_[0].getField('class'), id_.getPath())) for id_ in self.oid_.getNeighbors(fieldName)] - raise ValueError('%s: no such field on %s' % (fieldName, self.path)) - - def connect(self, srcField, dest, destField, msgType='Single'): - return self.oid_.connect(srcField, dest.oid_, destField, msgType) - - def getInMessageDict(self): - """Returns a dictionary mapping fields with incoming messages - to lists containing (source_element, source_field) - pairs.""" - msg_dict = defaultdict(list) - for msg in self.msgIn: - e1 = msg.getField('e1') - e2 = msg.getField('e2') - for (f1, f2) in zip(msg.getField('srcFieldsOnE2'), msg.getField('destFieldsOnE1')): - msg_dict[f1].append((element(e2), f2)) - return msg_dict - - def getOutMessageDict(self): - """Returns a dictionary mapping fields with outgoing messages - to lists containing (destination_element, destination_field) - pairs.""" - msg_dict = defaultdict(list) - for msg in self.msgOut: - e1 = msg.getField('e1') - e2 = msg.getField('e2') - for (f1, f2) in zip(msg.getField('srcFieldsOnE1'), msg.getField('destFieldsOnE2')): - msg_dict.append((element(e2), f2)) - return msg_dict - - def inMessages(self): - msg_list = [] - for msg in self.msgIn: - e1 = msg.getField('e1') - e2 = msg.getField('e2') - for (f1, f2) in zip(msg.getField('srcFieldsOnE2'), msg.getField('destFieldsOnE1')): - msg_str = '[%s].%s <- [%s].%s' % (e1.getPath(), f1, e2.getPath(), f2) - msg_list.append(msg_str) - return msg_list - - def outMessages(self): - msg_list = [] - for msg in self.msgOut: - e1 = msg.getField('e1') - e2 = msg.getField('e2') - for (f1, f2) in zip(msg.getField('srcFieldsOnE1'), msg.getField('destFieldsOnE2')): - msg_str = '[%s].%s -> [%s].%s' % (e1.getPath(), f1, e2.getPath(), f2) - msg_list.append(msg_str) - return msg_list - - - - className = property(lambda self: self.oid_.getField('class')) - fieldNames = property(lambda self: self.oid_.getFieldNames()) - name = property(lambda self: self.oid_.getField('name')) - path = property(lambda self: '%s[%d]' % (self.oid_.getField('path'), self.oid_.getDataIndex())) - id_ = property(lambda self: self.oid_.getId()) - fieldIndex = property(lambda self: self.oid_.getFieldIndex()) - dataIndex = property(lambda self: self.oid_.getDataIndex()) - # We have a lookup field called neighbors already, this should override that - @property - def neighborDict(self): - """defaultdict whose keys are field names and values are list - of objects that are connected to that field""" - neighbors = defaultdict(list) - for finfotype in ['srcFinfo', 'destFinfo', 'sharedFinfo']: - for field in self.oid_.getFieldNames(finfotype): - tmp = self.oid_.getNeighbors(field) - neighbors[field] += [eval('%s("%s")' % (nid[0].getField('class'), nid.getPath())) for nid in tmp] - return neighbors - - - childList = property(lambda self: [eval('%s("%s")' % (ch[0].getField('class'), ch.getPath())) for ch in self.oid_.getField('children')]) - -################################################################ -# Special function to generate objects of the right class from -# a given path. -################################################################ - -def element(path): - """Return a reference to an existing object as an instance of the - right class. If path does not exist, raises NameError. - - Id or ObjId can be provided in stead of path""" - if isinstance(path, Id): - oid = path[0] - path = path.getPath() - elif isinstance(path, ObjId): - oid = path - path = oid.getField('path') - elif isinstance(path, str): - if not _moose.exists(path): - raise NameError('Object %s not defined' % (path)) - oid = _moose.ObjId(path) - else: - raise TypeError('expected argument: Id/ObjId/str') - className = oid.getField('class') - return eval('%s("%s")' % (className, path)) - -def arrayelement(path, className='Neutral'): - """Return a reference to an existing object as an instance of the - right class. If path does not exist, className is used for - creating an instance of that class with the given path""" - if not _moose.exists(path): - raise NameError('Object %s not defined' % (path)) - oid = _moose.ObjId(path) - className = oid.getField('class') - return eval('%sArray("%s")' % (className, path)) - - -################################################################ -# Wrappers for global functions -################################################################ - -def copy(src, dest, name, n=1, toGlobal=False, copyExtMsg=False): - if isinstance(src, NeutralArray): - src = src.id_ - if isinstance(dest, NeutralArray): - dest = dest.id_ - new_id = _moose.copy(src, dest, name, n=n, toGlobal=toGlobal, copyExtMsg=copyExtMsg) - return new_id - -def move(src, dest): - if isinstance(src, NeutralArray): - src = src.id_ - if isinstance(dest, NeutralArray): - dest = dest.id_ - _moose.move(src, dest) - -def delete(target): - """Explicitly delete a MOOSE object. This will invalidate all - existing references. They will all point to the default root - object.""" - if isinstance(target, NeutralArray): - target = target.id_ - if not isinstance(target, Id): - raise TypeError('Only Id or Array objects can be deleted: received %s' % (target.__class__.__name__)) - _moose.delete(target) - -def setCwe(element): - """Set present working element""" - if isinstance(element, NeutralArray): - _moose.setCwe(element.id_) - elif isinstance(element, Neutral): - _moose.setCwe(element.oid_) - else: - _moose.setCwe(element) - -def getCwe(): - _id = _moose.getCwe() - obj = NeutralArray(_id) - return obj - -def pwe(): - """Print present working element. Convenience function for GENESIS - users.""" - print(_moose.getCwe().getPath()) - -def connect(src, srcMsg, dest, destMsg, msgType='Single'): - """Connect src object's source field specified by srcMsg to - destMsg field of target object.""" - if isinstance(src, Neutral): - src = src.oid_ - if isinstance(dest, Neutral): - dest = dest.oid_ - return src.connect(srcMsg, dest, destMsg, msgType) - -def le(element=None): - """List elements. """ - if element is None: - element = getCwe()[0] - elif isinstance(element, str): - element = Neutral(element) - print('Elements under', element.path) - for ch in element.children: - print(ch) - -ce = setCwe - -def syncDataHandler(target): - """Synchronize data handlers for target. - - Parameter: - target -- target element or path or Id. - """ - raise NotImplementedError('The implementation is not working for IntFire - goes to invalid objects. First fix that issue with SynBase or something in that line.') - if isinstance(target, str): - if not _moose.exists(target): - raise ValueError('%s: element does not exist.' % (target)) - target = Id(target) - _moose.syncDataHandler(target) - -def showfield(element, field='*', showtype=False): - """Show the fields of the element, their data types and values in - human readable format. Convenience function for GENESIS users. - - Parameters: - - element -- Element or path of an existing element or ObjId of an element. - - field -- Field to be displayed. If '*', all fields are displayed. - - showtype -- If True show the data type of each field. - - """ - if isinstance(element, str): - if not _moose.exists(element): - raise ValueError('%s -- no such moose object exists.' % (element)) - element = Neutral(element) - if not isinstance(element, Neutral): - if not isinstance(element, ObjId): - raise TypeError('Expected argument of type ObjId or Neutral or a path to an existing object. Found %s' % (type(element))) - element = Neutral(element) - if field == '*': - value_field_dict = getFieldDict(element.className, 'valueFinfo') - max_type_len = max(len(dtype) for dtype in value_field_dict.values()) - max_field_len = max(len(dtype) for dtype in value_field_dict.keys()) - print() - print('[', element.path, ']') - for key, dtype in list(value_field_dict.items()): - if dtype == 'bad' or key == 'this' or key == 'dummy' or key == 'me' or dtype.startswith('vector') or 'ObjId' in dtype: - continue - value = element.oid_.getField(key) - if showtype: - print(dtype.ljust(max_type_len + 4), end=' ') - print(key.ljust(max_field_len + 4), '=', value) - else: - try: - print(field, '=', element.getField(field)) - except AttributeError: - pass # Genesis silently ignores non existent fields - -def showfields(element, showtype=False): - """Convenience function. Should be deprecated if nobody uses it.""" - warnings.warn('Deprecated. Use showfield(element, field="*", showtype=True) instead.', DeprecationWarning) - showfield(element, field='*', showtype=showtype) - -def wildcardFind(cond): - """Search for objects that match condition cond.""" - return [eval('%s("%s")' % (id_[0].getField('class'), id_.getPath())) for id_ in _wildcardFind(cond)] - -####################################################### -# This is to generate class definitions automatically -####################################################### - -def update_class(cls, class_id): - class_name = class_id[0].name - num_valueFinfo = getField(class_id[0], 'num_valueFinfo', 'unsigned') - num_destFinfo = getField(class_id[0], 'num_destFinfo', 'unsigned') - num_lookupFinfo = getField(class_id[0], 'num_lookupFinfo', 'unsigned') - valueFinfo = Id('/classes/%s/valueFinfo' % (class_name)) - destFinfo = Id('/classes/%s/destFinfo' % (class_name)) - lookupFinfo = Id('/classes/%s/lookupFinfo' % (class_name)) - destFinfoNames = set([ObjId(destFinfo, 0, ii, 0).name for ii in range(num_destFinfo)]) - for ii in range(num_valueFinfo): - field = ObjId(valueFinfo, 0, ii, 0) - fieldName = field.name - fget = partial(ObjId.getField, fieldName) - fset = None - if 'get_%s' % (fieldName) in destFinfoNames: - fset = partial(ObjId.setField, fieldName) - doc = None - # The following is to avoid duplicating the documentation - # in non-interactive mode. __main__.__file__ is not - # defined in interactive mode and that is when we create - # the documentation. - if not hasattr(main, '__file__'): - doc = field.docs - setattr(cls, fieldName, property(fget=fget, fset=fset, doc=doc)) - - for ii in range(num_lookupFinfo): - field = ObjId(lookupFinfo, 0, ii, 0) - fieldName = field.name - fget = partial(_LookupField, fieldName) - # The following is to avoid duplicating the documentation - # in non-interactive mode. __main__.__file__ is not - # defined in interactive mode and that is when we create - # the documentation. - doc = None - if not hasattr(main, '__file__'): - doc = field.docs - setattr(cls, fieldName, property(fget=fget, doc=doc)) - - # Go through the destFinfos and make them look like methods - for ii in range(num_destFinfo): - field = ObjId(destFinfo, 0, ii, 0) - fieldName = field.name - # get_ and set_ are internal - # destFinfos generated for each valueFinfo (the latter - # created for writable ones). They are not to be accessed - # by users. - if fieldName.startswith('get_') or fieldName.startswith('set_'): - continue - # Can we handle the arguments required for this destFinfo? - # Start optimistically. - manageable = True - # We keep gathering the function signature in fnsig - # This will be a lambda function, lambda x, y, ...: expr - # where expr is evaluated and the result returned. - fnsig = 'lambda self' - # We gather the formal arguments in fnargs. field name - # must be the first argument passed to the - # ObjId.setField function. - fnargs = '"%s"' % (fieldName) - # 'type' is a string field in Finfos specifying the type - # (retrieved from the template parameters specified in the - # C++ definition). for DestFinfo with OpFuncN will have a type string: - # "type1,type2,...,typeN". We split this string to find - # out the formal arguments of the lambda - argtypes = field.type.split(',') - for index in range(len(argtypes)): - # Check if we know how to handle this argument type - if argtypes[index] not in known_types: - manageable = False - break - elif argtypes[index] != 'void': - # The replacements are for types with space (like - # unsigned int) and templated types (like - # vector) - arg = 'arg_%d_%s' % (index, argtypes[index].replace(' ', '_').replace('<', '_').replace('>', '_')) - fnsig += ', %s' % (arg) - fnargs += ', %s' % (arg) - if manageable: - # The final function will be: - # lambda self, arg_1_type1, arg_2_type2, ..., arg_N_typeN: - # self.oid_.setField(fieldName, arg_1_type1, arg_2_type2, ..., arg_N_typeN) - function_string = '%s: self.oid_.setDestField(%s)' % (fnsig, fnargs) - setattr(cls, fieldName, eval(function_string)) - -def define_class(class_id): - """Define a class based on Cinfo element with Id=class_id.""" - class_name = class_id[0].getField('name') - if class_name in globals(): - return - base = class_id[0].getField('baseClass') - if base != 'none': - try: - base_class = globals()[base] - except KeyError: - define_class(Id('/classes/'+base)) - base_class = globals()[base] - else: - base_class = object - class_obj = type(class_name, (base_class,), {}) - update_class(class_obj, class_id) - # Add this class to globals dict - globals()[class_name] = class_obj - array_class_name = class_name + 'Array' - if base != 'none': - base_class = globals()[base + 'Array'] - else: - base_class = object - array_class_obj = type(array_class_name, (base_class,), {}) - globals()[array_class_name] = array_class_obj - -classes_Id = Id('/classes') - -for child in classes_Id[0].children: - define_class(child) - - -# -# moose.py ends here diff --git a/python/moose/chemUtil/add_Delete_ChemicalSolver.py b/python/moose/chemUtil/add_Delete_ChemicalSolver.py index 9b11a5c1..ac693675 100644 --- a/python/moose/chemUtil/add_Delete_ChemicalSolver.py +++ b/python/moose/chemUtil/add_Delete_ChemicalSolver.py @@ -113,9 +113,9 @@ def setCompartmentSolver(modelRoot, solver): for compt in compts: if solver != 'ee': - if (solver == 'gsl'): + if solver.lower() in [ 'gsl', 'runge kutta', 'lsoda' ]: ksolve = moose.Ksolve(compt.path + '/ksolve') - if (solver == 'gssa') : + elif solver.lower() in ['gssa', 'gillespie']: ksolve = moose.Gsolve(compt.path + '/gsolve') if (len(compts) > 1): diff --git a/python/moose/chemUtil/chemConnectUtil.py b/python/moose/chemUtil/chemConnectUtil.py index f15708be..1330ffdc 100644 --- a/python/moose/chemUtil/chemConnectUtil.py +++ b/python/moose/chemUtil/chemConnectUtil.py @@ -17,7 +17,7 @@ import matplotlib import os import random - +import re direct = os.path.dirname(__file__) colormap_file = open(os.path.join(direct, "rainbow2.pkl"), "r") @@ -69,7 +69,7 @@ def colorCheck(fc_bgcolor): if isinstance(fc_bgcolor,str): if fc_bgcolor.startswith("#"): fc_bgcolor = fc_bgcolor - elif fc_bgcolor.isdigit(): + elif (fc_bgcolor.isdigit()): """ color is int a map from int to r,g,b triplets from pickled color map file """ tc = (int(fc_bgcolor))*2 if tc < len(colorMap): @@ -89,7 +89,7 @@ def colorCheck(fc_bgcolor): hexlist ="#" for n in fc_bgcolor: if c < 3: - hexlist = hexlist+str("%02x" % int(n)) + #hexlist = hexlist+str("%02x" % int(n)) c = c+1; fc_bgcolor = hexlist return(fc_bgcolor) diff --git a/python/moose/fixXreacs.py b/python/moose/fixXreacs.py index 7009390f..3047ce3d 100644 --- a/python/moose/fixXreacs.py +++ b/python/moose/fixXreacs.py @@ -4,7 +4,7 @@ #################################################################### # fixXreacs.py # The program is meant to take a model and reconfigure any cross-compartment -# reactions so that they are split into portions on either side coupled +# reactions so that they are split into portions on either side coupled # either by diffusion, or by a reaction-driven translocation process. # # Copyright (C) Upinder S. Bhalla 2018 @@ -13,30 +13,31 @@ # This program carries no warranty whatsoever. #################################################################### -import sys import moose._moose as _moose msgSeparator = "_xMsg_" -def findCompt( elm ): - elm = _moose.element( elm ) +def findCompt(elm): + elm = _moose.element(elm) pa = elm.parent while pa.path != '/': - if _moose.Neutral(pa).isA[ 'ChemCompt' ]: + if _moose.Neutral(pa).isA['ChemCompt']: return pa.path pa = pa.parent - print( 'Error: No compartment parent found for ' + elm.path ) + print('Error: No compartment parent found for ' + elm.path) return '/' + # http://stackoverflow.com/q/3844948/ def checkEqual(lst): return not lst or lst.count(lst[0]) == len(lst) -def findXreacs( basepath, reacType ): - reacs = _moose.wildcardFind( basepath + '/##[ISA=' + reacType + 'Base]' ) + +def findXreacs(basepath, reacType): + reacs = _moose.wildcardFind(basepath + '/##[ISA=' + reacType + 'Base]') ret = [] for i in reacs: - reacc = findCompt( i ) + reacc = findCompt(i) subs = i.neighbors['subOut'] prds = i.neighbors['prdOut'] subc = [findCompt(j) for j in subs] @@ -45,73 +46,79 @@ def findXreacs( basepath, reacType ): enzc = [] if reacType == 'Enz': enzc = [reacc] - if not checkEqual( subc + prdc + enzc ): - ret.append( [i, reacc, subs, subc, prds, prdc ]) + if not checkEqual(subc + prdc + enzc): + ret.append([i, reacc, subs, subc, prds, prdc]) return ret -def removeEnzFromPool( pool ): - kids = _moose.wildcardFind( pool.path + "/#" ) + +def removeEnzFromPool(pool): + kids = _moose.wildcardFind(pool.path + "/#") for i in kids: - if i.isA[ 'EnzBase' ]: - _moose.delete( i ) - elif i.isA[ 'Function' ]: - _moose.delete( i ) + if i.isA['EnzBase']: + _moose.delete(i) + elif i.isA['Function']: + _moose.delete(i) + -# If a pool is not in the same compt as reac, make a proxy in the reac +# If a pool is not in the same compt as reac, make a proxy in the reac # compt, connect it up, and disconnect the one in the old compt. -def proxify( reac, reacc, direction, pool, poolc ): - reacc_elm = _moose.element( reacc ) - reac_elm = _moose.element( reac ) +def proxify(reac, reacc, direction, pool, poolc): + reacc_elm = _moose.element(reacc) + reac_elm = _moose.element(reac) # Preserve the rates which were set up for the x-compt reacn #_moose.showfield( reac ) dupname = pool.name + '_xfer_' + _moose.element(poolc).name #print "#############", pool, dupname, poolc - if _moose.exists( reacc + '/' + dupname ): - duppool = _moose.element( reacc + '/' + dupname ) + if _moose.exists(reacc + '/' + dupname): + duppool = _moose.element(reacc + '/' + dupname) else: # This also deals with cases where the duppool is buffered. - duppool = _moose.copy(pool, reacc_elm, dupname ) - duppool.diffConst = 0 # diffusion only happens in original compt - removeEnzFromPool( duppool ) - disconnectReactant( reac, pool, duppool ) - _moose.connect( reac, direction, duppool, 'reac' ) + duppool = _moose.copy(pool, reacc_elm, dupname) + duppool.diffConst = 0 # diffusion only happens in original compt + removeEnzFromPool(duppool) + disconnectReactant(reac, pool, duppool) + _moose.connect(reac, direction, duppool, 'reac') #_moose.showfield( reac ) #_moose.showmsg( reac ) -def enzProxify( enz, enzc, direction, pool, poolc ): + +def enzProxify(enz, enzc, direction, pool, poolc): if enzc == poolc: return - enze = _moose.element( enz ) + enze = _moose.element(enz) # kcat and k2 are indept of volume, just time^-1 km = enze.numKm - proxify( enz, enzc, direction, pool, poolc ) + proxify(enz, enzc, direction, pool, poolc) enze.numKm = km -def reacProxify( reac, reacc, direction, pool, poolc ): + +def reacProxify(reac, reacc, direction, pool, poolc): if reacc == poolc: return - reac_elm = _moose.element( reac ) + reac_elm = _moose.element(reac) kf = reac_elm.numKf kb = reac_elm.numKb - proxify( reac, reacc, direction, pool, poolc ) + proxify(reac, reacc, direction, pool, poolc) reac_elm.numKf = kf reac_elm.numKb = kb -def identifyMsg( src, srcOut, dest ): - if src.isA[ 'ReacBase' ] or src.isA[ 'EnzBase' ]: + +def identifyMsg(src, srcOut, dest): + if src.isA['ReacBase'] or src.isA['EnzBase']: if srcOut == 'subOut': return msgSeparator + src.path + ' sub ' + dest.path + ' reac' if srcOut == 'prdOut': return msgSeparator + src.path + ' prd ' + dest.path + ' reac' return '' -def disconnectReactant( reacOrEnz, reactant, duppool ): + +def disconnectReactant(reacOrEnz, reactant, duppool): outMsgs = reacOrEnz.msgOut infoPath = duppool.path + '/info' - if _moose.exists( infoPath ): - info = _moose.element( infoPath ) + if _moose.exists(infoPath): + info = _moose.element(infoPath) else: - info = _moose.Annotator( infoPath ) + info = _moose.Annotator(infoPath) #_moose.le( reactant ) notes = "" @@ -119,77 +126,86 @@ def disconnectReactant( reacOrEnz, reactant, duppool ): for i in outMsgs: #print "killing msg from {} to {}\nfor {} and {}".format( reacOrEnz.path, reactant.path, i.srcFieldsOnE1[0], i.srcFieldsOnE2[0] ) if i.e1 == reactant: - msgStr = identifyMsg( i.e2, i.e2.srcFieldsOnE2[0], i.e1 ) - if len( msgStr ) > 0: + msgStr = identifyMsg(i.e2, i.e2.srcFieldsOnE2[0], i.e1) + if len(msgStr) > 0: notes += msgStr - _moose.delete( i ) + _moose.delete(i) elif i.e2 == reactant: - msgStr = identifyMsg( i.e1[0], i.srcFieldsOnE1[0], i.e2[0] ) - if len( msgStr ) > 0: + msgStr = identifyMsg(i.e1[0], i.srcFieldsOnE1[0], i.e2[0]) + if len(msgStr) > 0: notes += msgStr - _moose.delete( i ) + _moose.delete(i) #print "MSGS to rebuild:", notes info.notes += notes -def fixXreacs( basepath ): - xr = findXreacs( basepath, 'Reac' ) - xe = findXreacs( basepath, 'Enz' ) + +def fixXreacs(basepath): + xr = findXreacs(basepath, 'Reac') + xe = findXreacs(basepath, 'Enz') for i in (xr): reac, reacc, subs, subc, prds, prdc = i - for j in range( len( subs )): - reacProxify( reac, reacc, 'sub', subs[j], subc[j] ) - for j in range( len( prds )): - reacProxify( reac, reacc, 'prd', prds[j], prdc[j] ) + for j in range(len(subs)): + reacProxify(reac, reacc, 'sub', subs[j], subc[j]) + for j in range(len(prds)): + reacProxify(reac, reacc, 'prd', prds[j], prdc[j]) for i in (xe): reac, reacc, subs, subc, prds, prdc = i - for j in range( len( subs )): - enzProxify( reac, reacc, 'sub', subs[j], subc[j] ) - for j in range( len( prds )): - enzProxify( reac, reacc, 'prd', prds[j], prdc[j] ) + for j in range(len(subs)): + enzProxify(reac, reacc, 'sub', subs[j], subc[j]) + for j in range(len(prds)): + enzProxify(reac, reacc, 'prd', prds[j], prdc[j]) + ##################################################################### -def getOldRates( msgs ): - if len( msgs ) > 1 : - m1 = msgs[1].split( msgSeparator )[0] - elm = _moose.element( m1.split( ' ' )[0] ) - if elm.isA[ 'ReacBase' ]: + +def getOldRates(msgs): + if len(msgs) > 1: + m1 = msgs[1].split(msgSeparator)[0] + elm = _moose.element(m1.split(' ')[0]) + if elm.isA['ReacBase']: return [elm.numKf, elm.numKb] - elif elm.isA[ 'EnzBase' ]: - return [elm.numKm,] - print( "Warning: getOldRates did not have any messages" ) - return [0,] + elif elm.isA['EnzBase']: + return [ + elm.numKm, + ] + print("Warning: getOldRates did not have any messages") + return [ + 0, + ] -def restoreOldRates( oldRates, msgs ): + +def restoreOldRates(oldRates, msgs): #print oldRates, msgs - if len( msgs ) > 1 : - m1 = msgs[1].split( msgSeparator )[0] - elm = _moose.element( m1.split( ' ' )[0] ) - if elm.isA[ 'ReacBase' ]: + if len(msgs) > 1: + m1 = msgs[1].split(msgSeparator)[0] + elm = _moose.element(m1.split(' ')[0]) + if elm.isA['ReacBase']: elm.numKf = oldRates[0] elm.numKb = oldRates[1] - elif elm.isA[ 'enzBase' ]: + elif elm.isA['enzBase']: elm.numKm = oldRates[0] - -def restoreXreacs( basepath ): - proxyInfo = _moose.wildcardFind( basepath + "/##/#_xfer_#/info" ) +def restoreXreacs(basepath): + proxyInfo = _moose.wildcardFind(basepath + "/##/#_xfer_#/info") for i in proxyInfo: - msgs = i.notes.split( msgSeparator ) - oldRates = getOldRates( msgs ) + msgs = i.notes.split(msgSeparator) + oldRates = getOldRates(msgs) #print( "Deleting {}".format( i.parent.path ) ) #print msgs - _moose.delete( i.parent ) + _moose.delete(i.parent) for j in msgs[1:]: - if len( j ) > 0: - args = j.split( ' ' ) - assert( len( args ) == 4 ) + if len(j) > 0: + args = j.split(' ') + assert (len(args) == 4) #_moose.showfield( args[0] ) - _moose.connect( args[0], args[1], args[2], args[3] ) + #check to see if object exist before moose.connect, cases where object is deleted but + #_xref_ annotation info field still holds the reference + if (_moose.exists(args[0]) and _moose.exists(args[2])): + _moose.connect(args[0], args[1], args[2], args[3]) #print( "Reconnecting {}".format( args ) ) #_moose.showfield( args[0] ) - restoreOldRates( oldRates, msgs ) - + restoreOldRates(oldRates, msgs) diff --git a/python/moose/genesis/writeKkit.py b/python/moose/genesis/writeKkit.py index 27eaf50d..eba27a0a 100644 --- a/python/moose/genesis/writeKkit.py +++ b/python/moose/genesis/writeKkit.py @@ -9,8 +9,10 @@ __maintainer__ = "Harsha Rani" __email__ = "hrani@ncbs.res.in" __status__ = "Development" -__updated__ = "Dec 08 2018" - +__updated__ = "Jan 08 2020" +#Jan 8: added a line to add compartment info +# permeability from moose is in uM which to be converted to mM for genesis +#2020 # 2018 # Dec 08: using restoreXreacs from fixXreacs # Nov 22: searched for _xfer_ instead of xfer @@ -274,7 +276,7 @@ def writeConcChan(modelpath,f,sceneitems): color = getRandomColor() if textcolor == "" or textcolor == " ": textcolor = getRandomColor() - f.write("simundump kchan /kinetics/" + trimPath(cChan)+ " " + str(int(1)) + " " + str(cChan.permeability)+ " " + + f.write("simundump kchan /kinetics/" + trimPath(cChan)+ " " + str(int(1)) + " " + str(cChan.permeability/1000.0 )+ " " + str(int(0)) + " " + str(int(0)) + " " + str(int(0)) + " " + @@ -446,12 +448,9 @@ def trimPath(mobj): splitpath = original.path[(original.path.find(mobj.name)):len(original.path)] else: pos = original.path.find(mobj.name) - #ss = re.compile(r'\b%s\b' %mobj.name) - #a = re.search(ss, original.path) - #pos = a.start() slash = original.path.find('/',pos+1) splitpath = original.path[slash+1:len(original.path)] - splitpath = re.sub("\[[0-9]+\]", "", splitpath) + splitpath = re.sub(r"\[[0-9]+\]", "", splitpath) s = splitpath.replace("_dash_",'-') s = splitpath.replace("_space_","_") return s @@ -540,7 +539,7 @@ def storePlotMsgs( tgraphs,f): bgPath = (poolEle.path+'/info') bg = moose.Annotator(bgPath).color bg = getColorCheck(bg,GENESIS_COLOR_SEQUENCE) - tabPath = re.sub("\[[0-9]+\]", "", tabPath) + tabPath = re.sub(r"\[[0-9]+\]", "", tabPath) s = s+"addmsg /kinetics/" + trimPath( poolEle ) + " " + tabPath + \ " PLOT Co *" + poolName + " *" + str(bg) +"\n"; f.write(s) @@ -572,7 +571,7 @@ def writeplot( tgraphs,f ): poolAnno = (poolEle.path+'/info') fg = moose.Annotator(poolAnno).textColor fg = getColorCheck(fg,GENESIS_COLOR_SEQUENCE) - tabPath = re.sub("\[[0-9]+\]", "", tabPath) + tabPath = re.sub(r"\[[0-9]+\]", "", tabPath) if tabPath.find("conc1") >= 0 or tabPath.find("conc2") >= 0: first = first + "simundump xplot " + tabPath + " 3 524288 \\\n" + "\"delete_plot.w ; edit_plot.D \" " + str(fg) + " 0 0 1\n" if tabPath.find("conc3") >= 0 or tabPath.find("conc4") >= 0: @@ -665,6 +664,7 @@ def getColorCheck(color,GENESIS_COLOR_SEQUENCE): return index elif isinstance(color, tuple): color = [int(x) for x in color[0:3]] + #color = map(int,color) index = nearestColorIndex(color, GENESIS_COLOR_SEQUENCE) return index elif isinstance(color, int): @@ -802,12 +802,19 @@ def writeNotes(modelpath,f): moose.wildcardFind(modelpath+"/##[0][ISA=Function]") +\ moose.wildcardFind(modelpath+"/##[0][ISA=StimulusTable]") for item in items: - if not re.search("xfer",item.name): - if moose.exists(item.path+'/info'): - info = item.path+'/info' - notes = moose.Annotator(info).getField('notes') - if (notes): - f.write("call /kinetics/"+ trimPath(item)+"/notes LOAD \ \n\""+moose.Annotator(info).getField('notes')+"\"\n") + if not re.search(r"xfer",item.name): + if not moose.exists(item.path+'/info'): + continue + info = item.path+'/info' + notes = moose.Annotator(info).getField('notes') + if not notes: + continue + m = r'call /kinetics/{0}/notes LOAD \ \n"{1}"\n'.format( + trimPath(item), moose.Annotator(info).getField('notes') + ) + f.write(m) + # f.write("call /kinetics/"+trimPath(item)+"/notes LOAD \ \n\""+moose.Annotator(info).getField('notes')+"\"\n") + def writeFooter1(f): f.write("\nenddump\n // End of dump\n") @@ -816,7 +823,6 @@ def writeFooter2(f): f.write("complete_loading\n") if __name__ == "__main__": - import sys import os filename = sys.argv[1] filepath, filenameWithext = os.path.split(filename) diff --git a/python/moose/graph_utils.py b/python/moose/graph_utils.py deleted file mode 100644 index bec44a74..00000000 --- a/python/moose/graph_utils.py +++ /dev/null @@ -1,85 +0,0 @@ -# -*- coding: utf-8 -*- -"""graph_utils.py: Graph related utilties. It does not require networkx library. -It writes files to be used with graphviz. - -Last modified: Sat Jan 18, 2014 05:01PM - -""" - -__author__ = "Dilawar Singh" -__copyright__ = "Copyright 2013, NCBS Bangalore" -__credits__ = ["NCBS Bangalore", "Bhalla Lab"] -__license__ = "GPL" -__version__ = "1.0.0" -__maintainer__ = "Dilawar Singh" -__email__ = "dilawars@ncbs.res.in" -__status__ = "Development" - -import sys -from . import _moose -import inspect -from . import print_utils as debug -import re - -pathPat = re.compile(r'.+?\[\d+\]$') - -def getMoosePaths(pat, isRoot=True): - ''' Return a list of paths for a given pattern. ''' - if type(pat) != str: - pat = pat.path - assert type(pat) == str - moose_paths = [x.path for x in _moose.wildcardFind(pat)] - return moose_paths - -def writeGraphviz(filename=None, pat='/##[TYPE=Compartment]'): - '''This is a generic function. It takes the the pattern, search for paths - and write a graphviz file. - ''' - - def fix(path): - '''Fix a given path so it can be written to a graphviz file''' - # If no [0] is at end of the path then append it. - global pathPat - if not pathPat.match(path): - path = path + '[0]' - return path - - - pathList = getMoosePaths(pat) - compList = _moose.wildcardFind(pat) - if not compList: - debug.dump("WARN" - , "No compartment found" - , frame = inspect.currentframe() - ) - - dot = [] - dot.append("digraph G {") - dot.append("\tconcentrate=true;") - for c in compList: - if c.neighbors['raxial']: - for n in c.neighbors['raxial']: - lhs = fix(c.path) - rhs = fix(n.path) - dot.append('\t"{}" -> "{}";'.format(lhs, rhs)) - elif c.neighbors['axial']: - for n in c.neighbors['axial']: - lhs = fix(c.path) - rhs = fix(n.path) - dot.append('\t"{}" -> "{}" [dir=back];'.format(lhs, rhs)) - else: - p = fix(c.path) - dot.append('\t"{}"'.format(p)) - - dot.append('}') - dot = '\n'.join(dot) - if not filename: - print(dot) - else: - with open(filename, 'w') as graphviz: - debug.dump("INFO" - , "Writing compartment topology to file {}".format(filename) - ) - graphviz.write(dot) - return True - diff --git a/python/moose/graphutil.py b/python/moose/graphutil.py deleted file mode 100644 index ed9e9060..00000000 --- a/python/moose/graphutil.py +++ /dev/null @@ -1,193 +0,0 @@ -# -*- coding: utf-8 -*- -# graphutil.py --- -# -# Filename: graphutil.py -# Description: -# Author: Subhasis Ray -# Maintainer: -# Created: Sun Mar 18 13:42:28 2012 (+0530) -# Version: -# Last-Updated: Wed Mar 28 18:27:26 2012 (+0530) -# By: subha -# Update #: 103 -# URL: -# Keywords: -# Compatibility: -# -# - -# Commentary: -# -# -# -# - -# Change log: -# -# - -# Code: - -from collections import defaultdict -import re -import networkx as nx -import numpy as np -from . import moose - -def moosegraph(element, ies=['childMsg'], ied=['parentMsg'], iv=[], keep_solitary=False): - """Create a graph out of all objects under teh element - specified. Ignore edges going outside the subtree rooted at - element. - - If element is a string, it can be a wildcard path in MOOSE - - ies is a list of sourcefields to be ignored when constructing edges. - - ied is a list of destination fields to be ignored when - constructing edges. - - iv is a list of paths, possibly wildcards, to be ignored when - building vertex set. - - keep_solitary -- if True solitary nodes are not discarded - - Note that this is a temporary solution. We rely on neighbours - field to create the graph. Ideally we should use the messages - between objects. A bug in Messages does not allow us to access the - fields on both sides properly in the general case. We shall switch - to messgaes once that bug is fixed.""" - - path = None - if isinstance(element, str): - path = element - elif isinstance(element, moose.Id): - path = element.getPath() - elif isinstance(element, moose.ObjId): - path = element.getField('path') - elif isinstance(element, moose.Neutral): - path = element.path - else: - raise TypeError('Require Id, ObjId, Neutral or string object for element') - iv_re = [re.compile(pattern) for pattern in iv] - ies_re = [re.compile(pattern) for pattern in ies] - ied_re = [re.compile(pattern) for pattern in ied] - if '#' in path: - all_v = moose.wildcardFind(path) - else: - if path.endswith('/'): - path = '%s##' % (path) - else: - path = '%s/##' % (path) - all_v = moose.wildcardFind(path) - valid_v = [] - # Collect all not-to-be-ignored vertices - for vv in all_v: - include = True - for iv in iv_re: - if iv.search(vv.path): - include = False - break - if include: - valid_v.append(vv) - graph = nx.DiGraph() - graph.add_nodes_from([vv.id_ for vv in valid_v]) - for vv in graph.nodes(): - for fname in vv[0].getFieldNames('srcFinfo'): - matches = [True for regex in ies_re if regex.search(fname)] - if matches: - continue - nlist = vv[0].getNeighbors(fname) - for nn in nlist: - if nn in graph.nodes(): - try: - src = graph.edge[vv][nn]['src'] - src.add(fname) - except KeyError: - graph.add_edge(vv, nn, src=set([fname])) - - for fname in vv[0].getFieldNames('destFinfo'): - matches = [True for regex in ied_re if regex.search(fname)] - if matches: - continue - nlist = vv[0].getNeighbors(fname) - for nn in nlist: - if nn in graph.nodes(): - try: - dest = graph.edge[vv][nn]['dest'] - dest.add(fname) - except KeyError: - graph.add_edge(nn, vv, dest=set([fname])) - - for fname in vv[0].getFieldNames('sharedFinfo'): - nlist = vv[0].getNeighbors(fname) - for nn in nlist: - if nn in graph.nodes(): - try: - src = graph.edge[vv][nn]['src'] - src.add(fname) - except KeyError: - graph.add_edge(vv, nn, src=set([fname])) - try: - dest = graph.edge[nn][vv]['dest'] - dest.add(fname) - except KeyError: - graph.add_edge(nn, vv, dest=set([fname])) - if not keep_solitary: - solitary=[ n for n,d in graph.degree_iter() if d==0 ] - graph.remove_nodes_from(solitary) - return graph - -def draw_moosegraph(graph, pos=None, label_edges=True): - if pos is None: - pos = nx.spring_layout(graph) - edge_labels = {} - if label_edges: - for ee in graph.edges(): - try: - src = ','.join(graph.edge[ee[0]][ee[1]]['src']) - except KeyError: - src = '?' - try: - dest = ','.join(graph.edge[ee[0]][ee[1]]['dest']) - except KeyError: - dest = '?' - label = '%s-%s' % (src, dest) - edge_labels[ee] = label - nx.draw(graph, pos) - nx.draw_networkx_edge_labels(graph, pos, edge_labels) - -import unittest -import pylab - -class TestMooseGraph(unittest.TestCase): - def setUp(self): - cell = moose.Neutral('/n') - comp1 = moose.Compartment('/n/c1') - chan = moose.HHChannel('/n/c1/ch') - moose.connect(comp1, 'channel', chan, 'channel') - comp2 = moose.Compartment('/n/c2') - comp2.connect('raxial', comp1, 'axial') - self.graph = moosegraph('/n') - - def test_edgelabels(self): - for ee in self.graph.edges(): - keys = self.graph.edge[ee[0]][ee[1]].keys() - self.assertTrue('src' in keys) - self.assertTrue('dest' in keys) - - def test_vertexid(self): - for vv in self.graph.nodes(): - self.assertTrue(isinstance(vv, moose.Id)) - - def test_plot(self): - draw_moosegraph(self.graph) - pylab.show() - - -if '__main__' == __name__: - unittest.main() - - - -# -# graphutil.py ends here diff --git a/python/moose/methods_utils.py b/python/moose/methods_utils.py index 1a8cd31d..425cc20b 100644 --- a/python/moose/methods_utils.py +++ b/python/moose/methods_utils.py @@ -1,13 +1,6 @@ # -*- coding: utf-8 -*- - """methods_utils.py: - Some non-standard functions generic to moose. - - This library may not be exposed to end-users. Intended for development by - the maintainer of this file. - -Last modified: Sat Jan 18, 2014 05:01PM """ diff --git a/python/moose/model_utils.py b/python/moose/model_utils.py new file mode 100644 index 00000000..d4b7e21f --- /dev/null +++ b/python/moose/model_utils.py @@ -0,0 +1,248 @@ +# -*- coding: utf-8 -*- +# Utilties for loading NML and SBML models. +# Authored and maintained by Harsha Rani + +from __future__ import absolute_import, print_function, division + +import os +import moose._moose as _moose +import moose.utils as mu + +import logging +logger_ = logging.getLogger('moose.model') + +# sbml import. +sbmlImport_, sbmlError_ = True, '' +try: + import moose.SBML.readSBML as _readSBML + import moose.SBML.writeSBML as _writeSBML +except Exception as e: + sbmlImport_ = False + sbmlError_ = '%s' % e + +# NeuroML2 import. +nml2Import_, nml2ImportError_ = True, '' +try: + import moose.neuroml2 as _neuroml2 +except Exception as e: + nml2Import_ = False + nml2ImportError_ = ' '.join( [ + "NML2 support is disabled because `libneuroml` and " + , "`pyneuroml` modules are not found.\n" + , " $ pip install pyneuroml libneuroml \n" + , " should fix it." + , " Actual error: %s " % e ] + ) + +chemImport_, chemError_ = True, '' +try: + import moose.chemUtil as _chemUtil +except Exception as e: + chemImport_ = False + chemError_ = '%s' % e + +kkitImport_, kkitImport_error_ = True, '' +try: + import moose.genesis.writeKkit as _writeKkit +except ImportError as e: + kkitImport_ = False + kkitImport_err_ = '%s' % e + +mergechemImport_, mergechemError_ = True, '' +try: + import moose.chemMerge as _chemMerge +except Exception as e: + mergechemImport_ = False + mergechemError_ = '%s' % e + +# SBML related functions. +def mooseReadSBML(filepath, loadpath, solver='ee', validate="on"): + """Load SBML model. + + Parameter + -------- + filepath: str + filepath to be loaded. + loadpath : str + Root path for this model e.g. /model/mymodel + solver : str + Solver to use (default 'ee'). + Available options are "ee", "gsl", "stochastic", "gillespie" + "rk", "deterministic" + For full list see ?? + """ + global sbmlImport_ + if sbmlImport_: + modelpath = _readSBML.mooseReadSBML(filepath, loadpath, solver, validate) + sc = solver.lower() + if sc in ["gssa","gillespie","stochastic","gsolve"]: + method = "gssa" + elif sc in ["gsl","runge kutta","deterministic","ksolve","rungekutta","rk5","rkf","rk"]: + method = "gsl" + elif sc in ["exponential euler","exponentialeuler","neutral", "ee"]: + method = "ee" + else: + method = "ee" + + if method != 'ee': + _chemUtil.add_Delete_ChemicalSolver.mooseAddChemSolver(modelpath[0].path, method) + return modelpath + else: + logger_.error( sbmlError_ ) + return False + +def mooseWriteSBML(modelpath, filepath, sceneitems={}): + """mooseWriteSBML: Writes loaded model under modelpath to a file in SBML format. + + Parameters + ---------- + modelpath : str + model path in moose e.g /model/mymodel \n + filepath : str + Path of output file. \n + sceneitems : dict + UserWarning: user need not worry about this layout position is saved in + Annotation field of all the moose Object (pool,Reaction,enzyme). + If this function is called from + * GUI - the layout position of moose object is passed + * command line - NA + * if genesis/kkit model is loaded then layout position is taken from the file + * otherwise auto-coordinates is used for layout position. + """ + if sbmlImport_: + return _writeSBML.mooseWriteSBML(modelpath, filepath, sceneitems) + else: + logger_.error( sbmlError_ ) + return False + + +def mooseWriteKkit(modelpath, filepath, sceneitems={}): + """Writes loded model under modelpath to a file in Kkit format. + + Parameters + ---------- + modelpath : str + Model path in moose. + filepath : str + Path of output file. + """ + global kkitImport_, kkitImport_err_ + if not kkitImport_: + print( '[WARN] Could not import module to enable this function' ) + print( '\tError was %s' % kkitImport_error_ ) + return False + return _writeKkit.mooseWriteKkit(modelpath, filepath,sceneitems) + + +def mooseDeleteChemSolver(modelpath): + """mooseDeleteChemSolver + deletes solver on all the compartment and its children. + + Notes + ----- + This is neccesary while created a new moose object on a pre-existing modelpath, + this should be followed by mooseAddChemSolver for add solvers on to compartment + to simulate else default is Exponential Euler (ee) + """ + if chemImport_: + return _chemUtil.add_Delete_ChemicalSolver.mooseDeleteChemSolver(modelpath) + else: + print( chemError_ ) + return False + + +def mooseAddChemSolver(modelpath, solver): + """mooseAddChemSolver: + Add solver on chemical compartment and its children for calculation + + Parameters + ---------- + + modelpath : str + Model path that is loaded into moose. + solver : str + Exponential Euler "ee" is default. Other options are Gillespie ("gssa"), + Runge Kutta ("gsl") etc. Link to documentation? + """ + if chemImport_: + chemError_ = _chemUtil.add_Delete_ChemicalSolver.mooseAddChemSolver(modelpath, solver) + return chemError_ + else: + print( chemError_ ) + return False + +def mergeChemModel(src, des): + """mergeChemModel: Merges two chemical model. + File or filepath can be passed source is merged to destination + """ + #global mergechemImport_ + if mergechemImport_: + return _chemMerge.merge.mergeChemModel(src,des) + else: + return False + +# NML2 reader and writer function. +def mooseReadNML2( modelpath, verbose = False ): + """Read NeuroML model (version 2) and return reader object. + """ + global nml2Import_ + if not nml2Import_: + mu.warn( nml2ImportError_ ) + raise RuntimeError( "Could not load NML2 support." ) + + reader = _neuroml2.NML2Reader( verbose = verbose ) + reader.read( modelpath ) + return reader + +def mooseWriteNML2( outfile ): + raise NotImplementedError( "Writing to NML2 is not supported yet" ) + + +def loadModel(filename, modelpath, solverclass="gsl"): + """loadModel: Load model from a file to a specified path. + + Parameters + ---------- + filename: str + model description file. + modelpath: str + moose path for the top level element of the model to be created. + method: str + solver type to be used for simulating the model. + TODO: Link to detailed description of solvers? + + Returns + ------- + object + moose.element if succcessful else None. + """ + + if not os.path.isfile( os.path.realpath(filename) ): + mu.warn( "Model file '%s' does not exists or is not readable." % filename ) + return None + + extension = os.path.splitext(filename)[1] + if extension in [".swc", ".p"]: + return _moose.loadModelInternal(filename, modelpath, "Neutral" ) + + if extension in [".g", ".cspace"]: + # only if genesis or cspace file and method != ee then only + # mooseAddChemSolver is called. + ret = _moose.loadModelInternal(filename, modelpath, "ee") + sc = solverclass.lower() + if sc in ["gssa","gillespie","stochastic","gsolve"]: + method = "gssa" + elif sc in ["gsl","runge kutta","deterministic","ksolve","rungekutta","rk5","rkf","rk"]: + method = "gsl" + elif sc in ["exponential euler","exponentialeuler","neutral"]: + method = "ee" + else: + method = "ee" + + if method != 'ee': + _chemUtil.add_Delete_ChemicalSolver.mooseAddChemSolver(modelpath, method) + return ret + else: + logger_.error( "Unknown model extenstion '%s'" % extension) + return None + diff --git a/python/moose/moose.py b/python/moose/moose.py index 191d26d4..b78c7e0b 100644 --- a/python/moose/moose.py +++ b/python/moose/moose.py @@ -7,291 +7,37 @@ import warnings import os import pydoc -from io import StringIO +import io from contextlib import closing -# Import function from C++ module into moose namespace. import moose._moose as _moose import moose.utils as mu -# sbml import. -sbmlImport_, sbmlError_ = True, '' -try: - import moose.SBML.readSBML as _readSBML - import moose.SBML.writeSBML as _writeSBML -except Exception as e: - sbmlImport_ = False - sbmlError_ = '%s' % e - -# NeuroML2 import. -nml2Import_, nml2ImportError_ = True, '' -try: - import moose.neuroml2 as _neuroml2 -except Exception as e: - nml2Import_ = False - nml2ImportError_ = ' '.join( [ - "NML2 support is disabled because `libneuroml` and " - , "`pyneuroml` modules are not found.\n" - , " $ pip install pyneuroml libneuroml \n" - , " should fix it." - , " Actual error: %s " % e ] - ) - -chemImport_, chemError_ = True, '' -try: - import moose.chemUtil as _chemUtil -except Exception as e: - chemImport_ = False - chemError_ = '%s' % e - -kkitImport_, kkitImport_error_ = True, '' -try: - import moose.genesis.writeKkit as _writeKkit -except ImportError as e: - kkitImport_ = False - kkitImport_err_ = '%s' % e - -mergechemImport_, mergechemError_ = True, '' -try: - import moose.chemMerge as _chemMerge -except Exception as e: - mergechemImport_ = False - mergechemError_ = '%s' % e - -def loadModel(filename, modelpath, solverclass="gsl"): - """loadModel: Load model from a file to a specified path. - Parameters - ---------- - filename: str - model description file. - modelpath: str - moose path for the top level element of the model to be created. - method: str - solver type to be used for simulating the model. - TODO: Link to detailed description of solvers? - - Returns - ------- - object - moose.element if succcessful else None. +def about(): + """info: Return some 'about me' information. """ + return dict(path=os.path.dirname(__file__), + version=_moose.VERSION, + docs='https://moose.readthedocs.io/en/latest/') - if not os.path.isfile( os.path.realpath(filename) ): - mu.warn( "Model file '%s' does not exists or is not readable." % filename ) - return None - - extension = os.path.splitext(filename)[1] - if extension in [".swc", ".p"]: - return _moose.loadModelInternal(filename, modelpath, "Neutral" ) - - if extension in [".g", ".cspace"]: - # only if genesis or cspace file and method != ee then only - # mooseAddChemSolver is called. - ret = _moose.loadModelInternal(filename, modelpath, "ee") - sc = solverclass.lower() - if sc in ["gssa","gillespie","stochastic","gsolve"]: - method = "gssa" - elif sc in ["gsl","runge kutta","deterministic","ksolve","rungekutta","rk5","rkf","rk"]: - method = "gsl" - elif sc in ["exponential euler","exponentialeuler","neutral"]: - method = "ee" - else: - method = "ee" - - if method != 'ee': - chemError = _chemUtil.add_Delete_ChemicalSolver.mooseAddChemSolver(modelpath, method) - return ret - else: - mu.error( "Unknown model extenstion '%s'" % extension) - return None - # Version -def version( ): +def version(): # Show user version. return _moose.VERSION -# Tests -from moose.moose_test import test - -sequence_types = ['vector', - 'vector', - 'vector', - 'vector', - 'vector', - 'vector', - 'vector', - 'vector', - 'vector'] - -known_types = ['void', - 'char', - 'short', - 'int', - 'unsigned int', - 'double', - 'float', - 'long', - 'unsigned long', - 'string', - 'vec', - 'melement'] + sequence_types - -# SBML related functions. -def mooseReadSBML(filepath, loadpath, solver='ee',validate="on"): - """Load SBML model. - - Parameter - -------- - filepath: str - filepath to be loaded. - loadpath : str - Root path for this model e.g. /model/mymodel - solver : str - Solver to use (default 'ee'). - Available options are "ee", "gsl", "stochastic", "gillespie" - "rk", "deterministic" - For full list see ?? - """ - global sbmlImport_ - if sbmlImport_: - modelpath = _readSBML.mooseReadSBML(filepath, loadpath, solver, validate) - sc = solver.lower() - if sc in ["gssa","gillespie","stochastic","gsolve"]: - method = "gssa" - elif sc in ["gsl","runge kutta","deterministic","ksolve","rungekutta","rk5","rkf","rk"]: - method = "gsl" - elif sc in ["exponential euler","exponentialeuler","neutral"]: - method = "ee" - else: - method = "ee" - - if method != 'ee': - chemError = _chemUtil.add_Delete_ChemicalSolver.mooseAddChemSolver(modelpath[0].path, method) - - return modelpath - else: - print( sbmlError_ ) - return False - -def mooseWriteSBML(modelpath, filepath, sceneitems={}): - """mooseWriteSBML: Writes loaded model under modelpath to a file in SBML format. - - Parameters - ---------- - modelpath : str - model path in moose e.g /model/mymodel \n - filepath : str - Path of output file. \n - sceneitems : dict - UserWarning: user need not worry about this layout position is saved in - Annotation field of all the moose Object (pool,Reaction,enzyme). - If this function is called from - * GUI - the layout position of moose object is passed - * command line - NA - * if genesis/kkit model is loaded then layout position is taken from the file - * otherwise auto-coordinates is used for layout position. - """ - if sbmlImport_: - return _writeSBML.mooseWriteSBML(modelpath, filepath, sceneitems) - else: - print( sbmlError_ ) - return False - -def mooseWriteKkit(modelpath, filepath, sceneitems={}): - """Writes loded model under modelpath to a file in Kkit format. - - Parameters - ---------- - modelpath : str - Model path in moose. - filepath : str - Path of output file. - """ - global kkitImport_, kkitImport_err_ - if not kkitImport_: - print( '[WARN] Could not import module to enable this function' ) - print( '\tError was %s' % kkitImport_error_ ) - return False - return _writeKkit.mooseWriteKkit(modelpath, filepath,sceneitems) - - -def mooseDeleteChemSolver(modelpath): - """mooseDeleteChemSolver - deletes solver on all the compartment and its children. - - Notes - ----- - This is neccesary while created a new moose object on a pre-existing modelpath, - this should be followed by mooseAddChemSolver for add solvers on to compartment - to simulate else default is Exponential Euler (ee) - """ - if chemImport_: - return _chemUtil.add_Delete_ChemicalSolver.mooseDeleteChemSolver(modelpath) - else: - print( chemError_ ) - return False - - -def mooseAddChemSolver(modelpath, solver): - """mooseAddChemSolver: - Add solver on chemical compartment and its children for calculation - - Parameters - ---------- - - modelpath : str - Model path that is loaded into moose. - solver : str - Exponential Euler "ee" is default. Other options are Gillespie ("gssa"), - Runge Kutta ("gsl") etc. Link to documentation? - """ - if chemImport_: - chemError_ = _chemUtil.add_Delete_ChemicalSolver.mooseAddChemSolver(modelpath, solver) - return chemError_ - else: - print( chemError_ ) - return False - -def mergeChemModel(src, des): - """mergeChemModel: Merges two chemical model. - File or filepath can be passed source is merged to destination - """ - #global mergechemImport_ - if mergechemImport_: - return _chemMerge.merge.mergeChemModel(src,des) - else: - return False - -# NML2 reader and writer function. -def mooseReadNML2( modelpath, verbose = False ): - """Read NeuroML model (version 2) and return reader object. - """ - global nml2Import_ - if not nml2Import_: - mu.warn( nml2ImportError_ ) - raise RuntimeError( "Could not load NML2 support." ) - - reader = _neuroml2.NML2Reader( verbose = verbose ) - reader.read( modelpath ) - return reader - -def mooseWriteNML2( outfile ): - raise NotImplementedError( "Writing to NML2 is not supported yet" ) - -################################################################ -# Wrappers for global functions -################################################################ def pwe(): """Print present working element. Convenience function for GENESIS users. If you want to retrieve the element in stead of printing the path, use moose.getCwe() + >>> pwe() + >>> '/' """ pwe_ = _moose.getCwe() - print(pwe_.getPath()) + print(pwe_.path) return pwe_ @@ -318,12 +64,15 @@ def le(el=None): el = _moose.element(el) elif isinstance(el, _moose.vec): el = el[0] - print('Elements under', el.path) + print("Elements under '%s'" % el.path) for ch in el.children: - print(ch.path) + print(" %s" % ch.path) return [child.path for child in el.children] -ce = _moose.setCwe # ce is a GENESIS shorthand for change element. + +# ce is a GENESIS shorthand for change element. +ce = _moose.setCwe + def syncDataHandler(target): """Synchronize data handlers for target. @@ -343,7 +92,8 @@ def syncDataHandler(target): This function is defined for completeness, but currently it does not work. """ - raise NotImplementedError('The implementation is not working for IntFire - goes to invalid objects. \ + raise NotImplementedError( + 'The implementation is not working for IntFire - goes to invalid objects. \ First fix that issue with SynBase or something in that line.') if isinstance(target, str): if not _moose.exists(target): @@ -370,21 +120,23 @@ def showfield(el, field='*', showtype=False): Returns ------- - None + string """ if isinstance(el, str): if not _moose.exists(el): - raise ValueError('no such element') + raise ValueError('no such element: %s' % el) el = _moose.element(el) + result = [] if field == '*': value_field_dict = _moose.getFieldDict(el.className, 'valueFinfo') max_type_len = max(len(dtype) for dtype in value_field_dict.values()) max_field_len = max(len(dtype) for dtype in value_field_dict.keys()) - print('\n[', el.path, ']') + result.append('\n[' + el.path + ']\n') for key, dtype in sorted(value_field_dict.items()): - if dtype == 'bad' or key == 'this' or key == 'dummy' or key == 'me' or dtype.startswith( - 'vector') or 'ObjId' in dtype: + if dtype == 'bad' or key == 'this' or key == 'dummy' \ + or key == 'me' or dtype.startswith('vector') \ + or 'ObjId' in dtype: continue value = el.getField(key) if showtype: @@ -392,22 +144,27 @@ def showfield(el, field='*', showtype=False): # The following hack is for handling both Python 2 and # 3. Directly putting the print command in the if/else # clause causes syntax error in both systems. - print(typestr, end=' ') - print(key.ljust(max_field_len + 4), '=', value) + result.append(typestr + ' ') + result.append( + key.ljust(max_field_len + 4) + '=' + str(value) + '\n') else: try: - print(field, '=', el.getField(field)) + result.append(field + '=' + el.getField(field)) except AttributeError: pass # Genesis silently ignores non existent fields + print(''.join(result)) + return ''.join(result) def showfields(el, showtype=False): - """Convenience function. Should be deprecated if nobody uses it. + """ + Print all fields on a a given element. """ warnings.warn( 'Deprecated. Use showfield(element, field="*", showtype=True) instead.', DeprecationWarning) - showfield(el, field='*', showtype=showtype) + return showfield(el, field='*', showtype=showtype) + # Predefined field types and their human readable names finfotypes = [('valueFinfo', 'value field'), @@ -416,6 +173,7 @@ def showfields(el, showtype=False): ('sharedFinfo', 'shared message field'), ('lookupFinfo', 'lookup field')] + def listmsg(el): """Return a list containing the incoming and outgoing messages of `el`. @@ -434,9 +192,9 @@ def listmsg(el): """ obj = _moose.element(el) ret = [] - for msg in obj.inMsg: + for msg in obj.msgIn: ret.append(msg) - for msg in obj.outMsg: + for msg in obj.msgOut: ret.append(msg) return ret @@ -457,23 +215,15 @@ def showmsg(el): obj = _moose.element(el) print('INCOMING:') for msg in obj.msgIn: - print( - msg.e2.path, - msg.destFieldsOnE2, - '<---', - msg.e1.path, - msg.srcFieldsOnE1) + print(msg.e2.path, msg.destFieldsOnE2, '<---', msg.e1.path, + msg.srcFieldsOnE1) print('OUTGOING:') for msg in obj.msgOut: - print( - msg.e1.path, - msg.srcFieldsOnE1, - '--->', - msg.e2.path, - msg.destFieldsOnE2) + print(msg.e1.path, msg.srcFieldsOnE1, '--->', msg.e2.path, + msg.destFieldsOnE2) -def getfielddoc(tokens, indent=''): +def getFieldDoc(tokens, indent=''): """Return the documentation for field specified by `tokens`. Parameters @@ -497,7 +247,7 @@ def getfielddoc(tokens, indent=''): NameError If the specified fieldName is not present in the specified class. """ - assert(len(tokens) > 1) + assert (len(tokens) > 1) classname = tokens[0] fieldname = tokens[1] while True: @@ -512,8 +262,9 @@ def getfielddoc(tokens, indent=''): # The field elements are # /classes/{ParentClass}[0]/{fieldElementType}[N]. finfotype = fieldelement.name - return '{indent}{classname}.{fieldname}: type={type}, finfotype={finfotype}{baseinfo}\n\t{docs}\n'.format( - indent=indent, classname=tokens[0], + return u'{indent}{classname}.{fieldname}: type={type}, finfotype={finfotype}{baseinfo}\n\t{docs}\n'.format( + indent=indent, + classname=tokens[0], fieldname=fieldname, type=fieldelement.type, finfotype=finfotype, @@ -521,95 +272,61 @@ def getfielddoc(tokens, indent=''): docs=fieldelement.docs) classname = classelement.baseClass except ValueError: - raise NameError('`%s` has no field called `%s`' - % (tokens[0], tokens[1])) - + raise NameError('`%s` has no field called `%s`' % + (tokens[0], tokens[1])) -def toUnicode(v, encoding='utf8'): - # if isinstance(v, str): - # return v +def _appendFinfoDocs(classname, docstring, indent): + """Append list of finfos in class name to docstring""" try: - return v.decode(encoding) - except (AttributeError, UnicodeEncodeError): - return str(v) - - -def getmoosedoc(tokens, inherited=False): - """Return MOOSE builtin documentation. + classElem = _moose.element('/classes/%s' % (classname)) + except ValueError: + raise NameError('class \'%s\' not defined.' % (classname)) + for ftype, rname in finfotypes: + docstring.write(u'\n*%s*\n' % (rname.capitalize())) + try: + finfo = _moose.element('%s/%s' % (classElem.path, ftype)) + for field in finfo.vec: + docstring.write(u'%s%s: %s\n' % + (indent, field.fieldName, field.type)) + except ValueError: + docstring.write(u'%sNone\n' % (indent)) - Parameters - ---------- - tokens : (className, [fieldName]) - tuple containing one or two strings specifying class name - and field name (optional) to get documentation for. - inherited: bool (default: False) - include inherited fields. - - Returns - ------- - docstring : str - Documentation string for class `className`.`fieldName` if both - are specified, for the class `className` if fieldName is not - specified. In the latter case, the fields and their data types - and finfo types are listed. - - Raises - ------ - NameError - If class or field does not exist. +def _getMooseDoc(tokens, inherited=False): + """Return MOOSE builtin documentation. """ - indent = ' ' - docstring = StringIO() + indent = ' ' + docstring = io.StringIO() with closing(docstring): if not tokens: return "" try: - class_element = _moose.element('/classes/%s' % (tokens[0])) - except ValueError as e: - raise NameError('name \'%s\' not defined.' % (tokens[0])) - if len(tokens) > 1: - docstring.write(toUnicode(getfielddoc(tokens))) - else: - docstring.write(toUnicode('%s\n' % (class_element.docs))) - append_finfodocs(tokens[0], docstring, indent) - if inherited: - mro = eval('_moose.%s' % (tokens[0])).mro() - for class_ in mro[1:]: - if class_ == _moose.melement: - break - docstring.write(toUnicode( - '\n\n#Inherited from %s#\n' % (class_.__name__))) - append_finfodocs(class_.__name__, docstring, indent) - if class_ == _moose.Neutral: # Neutral is the toplevel moose class - break - return docstring.getvalue() - - -def append_finfodocs(classname, docstring, indent): - """Append list of finfos in class name to docstring""" - try: - class_element = _moose.element('/classes/%s' % (classname)) - except ValueError: - raise NameError('class \'%s\' not defined.' % (classname)) - for ftype, rname in finfotypes: - docstring.write(toUnicode('\n*%s*\n' % (rname.capitalize()))) - try: - finfo = _moose.element('%s/%s' % (class_element.path, ftype)) - for field in finfo.vec: - docstring.write(toUnicode( - '%s%s: %s\n' % (indent, field.fieldName, field.type))) + classElem = _moose.element('/classes/%s' % (tokens[0])) except ValueError: - docstring.write(toUnicode('%sNone\n' % (indent))) + raise NameError("Name '%s' not defined." % (tokens[0])) + if len(tokens) > 1: + docstring.write(getFieldDoc(tokens)) + return docstring.getvalue() + + docstring.write(u'%s\n' % (classElem.docs)) + _appendFinfoDocs(tokens[0], docstring, indent) + if not inherited: + return docstring.getvalue() + + mro = eval('_moose.%s' % (tokens[0])).mro() + for class_ in mro[1:]: + if class_ == _moose.melement: + break + docstring.write(u"\n# Inherited from '%s'\n" % (class_.__name__)) + _appendFinfoDocs(class_.__name__, docstring, indent) + if class_ == _moose.Neutral: + break + return docstring.getvalue() -# the global pager is set from pydoc even if the user asks for paged -# help once. this is to strike a balance between GENESIS user's -# expectation of control returning to command line after printing the -# help and python user's expectation of seeing the help via more/less. -pager = None +__pager = None def doc(arg, inherited=True, paged=True): """Display the documentation for class or field in a class. @@ -646,14 +363,14 @@ def doc(arg, inherited=True, paged=True): # pydoc. (using properties requires copying all the docs strings # from MOOSE increasing the loading time by ~3x). Hence we provide a # separate function. - global pager - if paged and pager is None: - pager = pydoc.pager + global __pager + if paged and __pager is None: + __pager = pydoc.pager tokens = [] text = '' if isinstance(arg, str): tokens = arg.split('.') - if tokens[0] == 'moose': + if tokens[0] in ['moose', '_moose']: tokens = tokens[1:] elif isinstance(arg, type): tokens = [arg.__name__] @@ -661,11 +378,11 @@ def doc(arg, inherited=True, paged=True): text = '%s: %s\n\n' % (arg.path, arg.className) tokens = [arg.className] if tokens: - text += getmoosedoc(tokens, inherited=inherited) + text += _getMooseDoc(tokens, inherited=inherited) else: text += pydoc.getdoc(arg) - if pager: - pager(text) + if __pager: + __pager(text) else: print(text) diff --git a/python/moose/moose_config.py b/python/moose/moose_config.py deleted file mode 100644 index 5b996c64..00000000 --- a/python/moose/moose_config.py +++ /dev/null @@ -1,61 +0,0 @@ -# -*- coding: utf-8 -*- -# This file is part of MOOSE simulator: http://moose.ncbs.res.in. - -# MOOSE is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - -# MOOSE is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with Foobar. If not, see . - - -"""multiscale_config.py: - -Last modified: Sat Jan 18, 2014 05:01PM - -""" - -__author__ = "Dilawar Singh" -__copyright__ = "Copyright 2013, NCBS Bangalore" -__credits__ = ["NCBS Bangalore", "Bhalla Lab"] -__license__ = "GNU GPL" -__version__ = "1.0.0" -__maintainer__ = "Dilawar Singh" -__email__ = "dilawars@ncbs.res.in" -__status__ = "Development" - -import logging -import datetime -import time -import os - -# Universal paths -nmlPath = '/neuroml' -nmlCellPath = os.path.join(nmlPath, 'cells') -libraryPath = os.path.join(nmlPath, 'cells') -cellPath = nmlCellPath -elecPath = os.path.join(nmlPath, 'electrical') - -mumblePath = '/mumbl' - - -st = time.time() -st = datetime.datetime.fromtimestamp(st).strftime('%Y-%m-%d-%H%M') - -logDir = os.environ['HOME'] -logFile = os.path.join(logDir, ".moose", 'mumble.log') -if not os.path.isdir(logDir): - os.makedirs(logDir) - -if os.path.exists(logFile): - os.rename(logFile, '{}_{}'.format(logFile, st)) - -logging.basicConfig(filename=logFile, level=logging.DEBUG) -mooseLogger = logging.getLogger() -disbleCopyingOfObject = True - diff --git a/python/moose/moose_constants.py b/python/moose/moose_constants.py index 804bc7ec..848213b3 100644 --- a/python/moose/moose_constants.py +++ b/python/moose/moose_constants.py @@ -21,13 +21,9 @@ """ __author__ = "Dilawar Singh" -__copyright__ = "Copyright 2013, Dilawar Singh, NCBS Bangalore" -__credits__ = ["NCBS Bangalore"] __license__ = "GNU GPL" -__version__ = "1.0.0" __maintainer__ = "Dilawar Singh" __email__ = "dilawars@ncbs.res.in" -__status__ = "Development" ## for Ca Pool # FARADAY = 96154.0 @@ -66,4 +62,3 @@ LOOKUPCLOCK = 6 STIMCLOCK = 7 PLOTCLOCK = 8 - diff --git a/python/moose/moose_test.py b/python/moose/moose_test.py index 78f2f921..3238bafe 100644 --- a/python/moose/moose_test.py +++ b/python/moose/moose_test.py @@ -1,19 +1,13 @@ # -*- coding: utf-8 -*- """ Test MOOSE installation with moose-examples. - """ from __future__ import print_function, division -__author__ = "Dilawar Singh" -__copyright__ = "Copyright 2016, Dilawar Singh" -__credits__ = ["NCBS Bangalore"] -__license__ = "GNU GPL" -__version__ = "1.0.0" -__maintainer__ = "Dilawar Singh" -__email__ = "dilawars@ncbs.res.in" -__status__ = "Development" +__author__ = "Dilawar Singh" +__copyright__ = "Copyright 2016, Dilawar Singh" +__email__ = "dilawars@ncbs.res.in" import sys import os @@ -23,27 +17,16 @@ import threading import signal import logging +import tempfile from collections import defaultdict import time -logging.basicConfig( - level=logging.DEBUG, - format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', - datefmt='%m-%d %H:%M' - ) -console = logging.StreamHandler() -console.setLevel(logging.WARNING) -formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') -console.setFormatter(formatter) -_logger = logging.getLogger('moose.test') -_logger.addHandler(console) - +test_dir_ = os.path.join(tempfile.gettempdir(), 'moose-examples') test_data_url_ = 'https://github.com/BhallaLab/moose-examples/archive/master.zip' test_repo_url_ = 'https://github.com/BhallaLab/moose-examples' -test_dir_ = os.path.join( tempfile.gettempdir( ), 'moose-examples' ) -ignored_dict_ = defaultdict( list ) -test_status_ = defaultdict( list ) +ignored_dict_ = defaultdict(list) +test_status_ = defaultdict(list) total_ = 0 matplotlibrc_ = ''' @@ -51,152 +34,155 @@ interactive : True ''' + # Handle CTRL+C def signal_handler(signal, frame): - print( 'You pressed Ctrl+C!' ) - print_test_stat( ) + print('You pressed Ctrl+C!') + print_test_stat() quit(-1) + signal.signal(signal.SIGINT, signal_handler) + # Credit: https://stackoverflow.com/a/4825933/1805129 class Command(object): def __init__(self, cmd): self.cmd = cmd self.process = None - self.fnull = open( os.devnull, 'w' ) - - def __repr__( self ): - return ' '.join( self.cmd ) - - def run(self, timeout): - def target(): - _logger.info( "Running %s" % self ) - self.process = subprocess.Popen( - self.cmd, shell=False - , stdout = self.fnull, stderr = subprocess.STDOUT - ) - self.process.communicate() - - thread = threading.Thread( target = target ) - thread.start() - thread.join(timeout) - if thread.is_alive(): - self.process.terminate() - thread.join() - - if self.process.stderr is not None: - _logger.warn( '%s' % self.process.stderr.read() ) - + self.fnull = open(os.devnull, 'w') + + def __repr__(self): + return ' '.join(self.cmd) + + def run(self, timeout, **kwargs): + self.process = subprocess.Popen(self.cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + timer = threading.Timer(timeout, self.process.kill) + try: + timer.start() + output, errors = self.process.communicate() + try: + errors = errors.decode('utf8') + except Exception: + pass + logging.warn('%s %s' % (output, errors)) + finally: + timer.cancel() return self.process.returncode -def init_test_dir( ): + +def init_test_dir(): global test_dir_ global test_url_ - if( not os.path.exists( test_dir_ ) ): - os.makedirs( test_dir_ ) - _logger.info( "Donwloading test repository" ) - subprocess.call( - [ 'git', 'clone', '--depth=10', test_repo_url_, test_dir_ ] - ) - os.chdir( test_dir_ ) - -def suitable_for_testing( script ): - with open(script, 'r', encoding='utf8') as f: + if not os.path.exists(test_dir_): + os.makedirs(test_dir_) + logging.info("Donwloading test repository") + subprocess.check_output( + ['git', 'clone', '--depth=10', test_repo_url_, test_dir_]) + os.chdir(test_dir_) + subprocess.check_output(['git', 'pull']) + + +def suitable_for_testing(script): + with open(script, 'r') as f: txt = f.read() - if not re.search( r'main\(\s*\)', txt ): - _logger.debug( 'Script %s does not contain main( )' % script ) + if not re.search(r'main\(\s*\)', txt): + logging.debug('Script %s does not contain main( )' % script) return False, 'main( ) not found' - if re.search( r'raw_input\(\s*\)', txt ): - _logger.debug( 'Script %s requires user input' % script ) + if re.search(r'raw_input\(\s*\)', txt): + logging.debug('Script %s requires user input' % script) return False, 'waits for user input' return True, 'OK' -def run_test( index, testfile, timeout, **kwargs): + +def run_test(index, testfile, timeout, **kwargs): """Run a given test """ global test_status_ global total_ - pyExec = os.environ.get( 'PYTHON_EXECUTABLE', sys.executable ) - cmd = Command( [ pyExec, testfile ] ) + pyExec = os.environ.get('PYTHON_EXECUTABLE', sys.executable) + cmd = Command([pyExec, testfile]) - ti = time.time( ) - name = os.path.basename( testfile ) + ti = time.time() + name = os.path.basename(testfile) out = (name + '.' * 50)[:40] - print( '[TEST %3d/%d] %41s ' % (index, total_, out), end='' ) - sys.stdout.flush( ) + print('[TEST %3d/%d] %41s ' % (index, total_, out), end='') + sys.stdout.flush() # Run the test. - status = cmd.run( timeout = timeout ) - t = time.time( ) - ti - print( '% 7.2f ' % t, end='' ) - sys.stdout.flush( ) + status = cmd.run(timeout=timeout, **kwargs) + t = time.time() - ti + print('% 7.2f s' % t, end='') + sys.stdout.flush() # Change to directory and copy before running then test. - cwd = os.path.dirname( testfile ) - os.chdir( cwd ) - with open( os.path.join( cwd, 'matplotlibrc' ), 'w' ) as f: - _logger.debug( 'Writing matplotlibrc to %s' % cwd ) - f.write( matplotlibrc_ ) + cwd = os.path.dirname(testfile) + os.chdir(cwd) + with open(os.path.join(cwd, 'matplotlibrc'), 'w') as f: + logging.debug('Writing matplotlibrc to %s' % cwd) + f.write(matplotlibrc_) if status != 0: if status == -15: msg = '% 4d TIMEOUT' % status - test_status_[ 'TIMED-OUT' ].append( testfile ) + test_status_['TIMED-OUT'].append(testfile) else: msg = '% 4d FAILED' % status - test_status_[ 'FAILED' ].append( testfile ) - print( msg ) + test_status_['FAILED'].append(testfile) + print(msg) else: - print( '% 4d PASSED' % status ) - test_status_[ 'PASSED' ].append( testfile ) + print('% 4d PASSED' % status) + test_status_['PASSED'].append(testfile) + + sys.stdout.flush() - sys.stdout.flush( ) -def print_test_stat( ): +def print_test_stat(): global test_status_ for status in test_status_: - print( 'Total %d tests %s' % (len( test_status_[status] ), status ) ) + print('Total %d tests %s' % (len(test_status_[status]), status)) -def test_all( timeout, **kwargs ): + +def test_all(timeout, **kwargs): global test_dir_ global total_ - scripts = [ ] - for d, ds, fs in os.walk( test_dir_ ): + scripts = [] + for d, ds, fs in os.walk(test_dir_): for f in fs: - if not re.match( r'.+\.py$', f): + if not re.match(r'.+\.py$', f): continue - filepath = os.path.join( d, f ) - isOK, msg = suitable_for_testing( filepath ) + filepath = os.path.join(d, f) + isOK, msg = suitable_for_testing(filepath) if isOK: - scripts.append( filepath ) + scripts.append(filepath) else: - ignored_dict_[ msg ].append( filepath ) + ignored_dict_[msg].append(filepath) for k in ignored_dict_: - _logger.debug( '[INFO] Ignored due to %s' % k ) - _logger.debug( '\n\t'.join( ignored_dict_[ k ] ) ) + logging.debug('[INFO] Ignored due to %s' % k) + logging.debug('\n\t'.join(ignored_dict_[k])) - _logger.info( 'Total %d valid tests found' % len( scripts ) ) - total_ = len( scripts ) - for i, s in enumerate( scripts ): - _logger.info( 'Running test (timeout=%s) : %s' % (timeout,s)) - run_test(i, s, timeout, **kwargs ) + logging.info('Total %d valid tests found' % len(scripts)) + total_ = len(scripts) + for i, s in enumerate(scripts): + logging.info('Running test (timeout=%s) : %s' % (timeout, s)) + run_test(i, s, timeout, **kwargs) -def test( timeout = 60, **kwargs ): +def test(timeout=60, **kwargs): """Download and run tests. - """ - print( '[INFO] Running test with timeout %d sec' % timeout ) + print('[INFO] Running test with timeout %d sec' % timeout) try: - init_test_dir( ) + init_test_dir() except Exception as e: - print( '[INFO] Failed to clone moose-examples. Error was %s' % e ) - quit( ) + print('[INFO] Failed to clone moose-examples. Error was %s' % e) + quit() + + test_all(timeout=timeout, **kwargs) + print_test_stat() - test_all( timeout = timeout, **kwargs ) - print_test_stat( ) if __name__ == '__main__': - test( ) + test() diff --git a/python/moose/network_utils.py b/python/moose/network_utils.py new file mode 100644 index 00000000..a87219f2 --- /dev/null +++ b/python/moose/network_utils.py @@ -0,0 +1,129 @@ +# -*- coding: utf-8 -*- +from __future__ import print_function, division, absolute_import + +# Some network analysis utilities. + +__author__ = "Dilawar Singh" +__copyright__ = "Copyright 2018-19, NCBS Bangalore" +__maintainer__ = "Dilawar Singh" +__email__ = "dilawars@ncbs.res.in" + +import sys +import hashlib +import moose._moose as _moose +import re + +import logging +logger_ = logging.getLogger('moose.utils.graph') + +pathPat_ = re.compile(r'.+?\[\d+\]$') + +def morphologyToGraphviz(filename=None, pat='/##[TYPE=Compartment]'): + '''Write Electrical network to a dot graph. + + Params: + + :filename: Default None. Write graphviz file to this path. If None, write to + stdout. + :pat: Compartment path. By default, search for all moose.Compartment. + ''' + + def fix(path): + '''Fix a given path so it can be written to a graphviz file''' + # If no [0] is at end of the path then append it. + global pathPat_ + if not pathPat_.match(path): + path = path + '[0]' + return path + + compList = _moose.wildcardFind(pat) + if not compList: + logger_.warn("No compartment found") + + dot = [] + dot.append("digraph G {") + dot.append("\tconcentrate=true;") + for c in compList: + if c.neighbors['raxial']: + for n in c.neighbors['raxial']: + lhs = fix(c.path) + rhs = fix(n.path) + dot.append('\t"{}" -> "{}";'.format(lhs, rhs)) + elif c.neighbors['axial']: + for n in c.neighbors['axial']: + lhs = fix(c.path) + rhs = fix(n.path) + dot.append('\t"{}" -> "{}" [dir=back];'.format(lhs, rhs)) + else: + p = fix(c.path) + dot.append('\t"{}"'.format(p)) + + dot.append('}') + dot = '\n'.join(dot) + if not filename: + print(dot) + else: + with open(filename, 'w') as graphviz: + logger_.info("Writing compartment topology to file {}".format(filename)) + graphviz.write(dot) + return True + + +def chemicalReactionNetworkToGraphviz(compt, path=None): + """Write chemical reaction network to a graphviz file. + + :param compt: Given compartment. + :param filepath: Save to this filepath. If None, write to stdout. + """ + dot = _crn(compt) + if path is None: + print(dot, file=sys.stdout) + return + with open(path, 'w') as f: + f.write(dot) + +# aliases +crnToDot = chemicalReactionNetworkToGraphviz +crnToGraphviz = chemicalReactionNetworkToGraphviz + +def _fixLabel(name): + name = name.replace('*', 'star') + name = name.replace('.', '_') + return "\"{}\"".format(name) + +def _addNode(n, nodes, dot): + node = hashlib.sha224(n.path.encode()).hexdigest() + nodeType = 'pool' + if isinstance(n, _moose.Reac) or isinstance(n, _moose.ZombieReac): + node = 'r'+node + nodeType = 'reac' + else: + node = 'p'+node + if node in nodes: + return node + + nLabel = n.name + if nodeType == 'reac': + nLabel = "kf=%g kb=%g"%(n.Kf, n.Kb) + dot.append('\t%s [label="%s", kf=%g, kb=%g, shape=rect]' % ( + node, nLabel, n.Kf, n.Kb)) + else: + dot.append('\t%s [label="%s", concInit=%g]' % ( + node, nLabel, n.concInit)) + return node + +def _crn(compt): + nodes = {} + reacs = _moose.wildcardFind(compt.path+'/##[TYPE=Reac]') + reacs += _moose.wildcardFind(compt.path+'/##[TYPE=ZombieReac]') + dot = ['digraph %s {\n\t overlap=false' % compt.name ] + for r in reacs: + rNode = _addNode(r, nodes, dot) + for s in r.neighbors['sub']: + sNode = _addNode(s, nodes, dot) + dot.append('\t%s -> %s' % (sNode, rNode)) + for p in r.neighbors['prd']: + pNode = _addNode(p, nodes, dot) + dot.append('\t%s -> %s' % (rNode, pNode)) + dot.append('}') + return '\n'.join(dot) diff --git a/python/moose/neuroml/MorphML.py b/python/moose/neuroml/MorphML.py index 57b983cf..42f774db 100644 --- a/python/moose/neuroml/MorphML.py +++ b/python/moose/neuroml/MorphML.py @@ -585,7 +585,7 @@ def set_compartment_param(self, compartment, name, value, mechanismname): compartment.refractoryPeriod = value # compartment is a moose.LIF instance (intfire) elif name == 'g_refrac': _logger.info("SORRY, current moose.LIF doesn't support g_refrac.") - elif mechanismname is 'synapse': # synapse being added to the compartment + elif mechanismname == 'synapse': # synapse being added to the compartment ## these are potential locations, we do not actually make synapses, ## unless the user has explicitly asked for it if self.createPotentialSynapses: @@ -595,7 +595,7 @@ def set_compartment_param(self, compartment, name, value, mechanismname): ## I assume below that compartment name has _segid at its end segid = compartment.name.split('_')[-1] # get segment id from compartment name self.segDict[segid][5].append(value) - elif mechanismname is 'spikegen': # spikegen being added to the compartment + elif mechanismname == 'spikegen': # spikegen being added to the compartment ## these are potential locations, we do not actually make the spikegens. ## spikegens for different synapses can have different thresholds, ## hence include synapse_type in its name diff --git a/python/moose/neuroml2/hhfit.py b/python/moose/neuroml2/hhfit.py index e82effda..796e6174 100644 --- a/python/moose/neuroml2/hhfit.py +++ b/python/moose/neuroml2/hhfit.py @@ -1,111 +1,75 @@ # -*- coding: utf-8 -*- # hhfit.py --- -# -# Filename: hhfit.py + # Description: # Author: # Maintainer: # Created: Tue May 21 16:31:56 2013 (+0530) -# Version: -# Last-Updated: Tue Jun 11 16:57:30 2013 (+0530) -# By: subha -# Update #: 34 -# URL: -# Keywords: -# Compatibility: -# -# - # Commentary: -# # Functions for fitting common equations for Hodgkin-Huxley type gate # equations. -# -# - -# Change log: -# -# Tue May 21 16:33:59 IST 2013 - Subha refactored the code from -# converter.py to hhfit.py. -# - - -# -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public License as -# published by the Free Software Foundation; either version 3, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, Fifth -# Floor, Boston, MA 02110-1301, USA. -# -# - -# Code: import traceback import warnings -import moose.utils as mu import numpy as np +import logging +logger_ = logging.getLogger('moose.nml2.hhfit') try: - from scipy.optimize import curve_fit -except ImportError as e: - mu.error( "To use this feature/module, please install python-scipy" ) - raise e + import scipy.optimize as _SO +except ImportError: + raise RuntimeError("To use this feature/module, please install scipy") + def exponential2(x, a, scale, x0, y0=0): - res = a * np.exp((x - x0)/scale) + y0 + res = a * np.exp((x - x0) / scale) + y0 #print('============ Calculating exponential2 for %s, a=%s, scale=%s, x0=%s, y0=%s; = %s'%(x, a, scale, x0, y0, res)) return res + def exponential(x, a, k, x0, y0=0): res = a * np.exp(k * (x - x0)) + y0 #print('============ Calculating exponential for %s, a=%s, k=%s, x0=%s, y0=%s; = %s'%(x, a, k, x0, y0, res)) return res + def sigmoid2(x, a, scale, x0, y0=0): - res = a / (np.exp(-1*(x - x0)/scale) + 1.0) + y0 + res = a / (np.exp(-1 * (x - x0) / scale) + 1.0) + y0 #print('============ Calculating sigmoid for %s, a=%s, scale=%s, x0=%s, y0=%s; = %s'%(x, a, scale, x0, y0, res)) return res + def sigmoid(x, a, k, x0, y0=0): res = a / (np.exp(k * (x - x0)) + 1.0) + y0 #print('============ Calculating sigmoid for %s, a=%s, k=%s, x0=%s, y0=%s; = %s'%(x, a, k, x0, y0, res)) return res + def linoid2(x, a, scale, x0, y0=0): """The so called linoid function. Called explinear in neuroml.""" - - denominator = 1 - np.exp(-1 * (x - x0)/scale) + + denominator = 1 - np.exp(-1 * (x - x0) / scale) # Linoid often includes a zero denominator - we need to fill those # points with interpolated values (interpolation is simpler than # finding limits). - ret = (a/scale) * (x - x0) / denominator + ret = (a / scale) * (x - x0) / denominator infidx = np.flatnonzero((ret == np.inf) | (ret == -np.inf)) if len(infidx) > 0: for ii in infidx: if ii == 0: - ret[ii] = ret[ii+1] - (ret[ii+2] - ret[ii+1]) + ret[ii] = ret[ii + 1] - (ret[ii + 2] - ret[ii + 1]) elif ii == len(ret): - ret[ii] = ret[ii-1] + (ret[ii-1] - ret[ii-2]) + ret[ii] = ret[ii - 1] + (ret[ii - 1] - ret[ii - 2]) else: - ret[ii] = (ret[ii+1] + ret[ii+2]) * 0.5 + ret[ii] = (ret[ii + 1] + ret[ii + 2]) * 0.5 res = ret + y0 #print('============ Calculating linoid2 for %s, a=%s, scale=%s, x0=%s, y0=%s; res=%s'%(x, a, scale, x0, y0,res)) return res + def linoid(x, a, k, x0, y0=0): """The so called linoid function. Called explinear in neuroml.""" - + denominator = np.exp(k * (x - x0)) - 1.0 # Linoid often includes a zero denominator - we need to fill those # points with interpolated values (interpolation is simpler than @@ -115,15 +79,16 @@ def linoid(x, a, k, x0, y0=0): if len(infidx) > 0: for ii in infidx: if ii == 0: - ret[ii] = ret[ii+1] - (ret[ii+2] - ret[ii+1]) + ret[ii] = ret[ii + 1] - (ret[ii + 2] - ret[ii + 1]) elif ii == len(ret): - ret[ii] = ret[ii-1] + (ret[ii-1] - ret[ii-2]) + ret[ii] = ret[ii - 1] + (ret[ii - 1] - ret[ii - 2]) else: - ret[ii] = (ret[ii+1] + ret[ii+2]) * 0.5 + ret[ii] = (ret[ii + 1] + ret[ii + 2]) * 0.5 res = ret + y0 #print('============ Calculating linoid for %s, a=%s, k=%s, x0=%s, y0=%s; res=%s'%(x, a, k, x0, y0,res)) return res + def double_exp(x, a, k1, x1, k2, x2, y0=0): """For functions of the form: @@ -134,9 +99,10 @@ def double_exp(x, a, k1, x1, k2, x2, y0=0): try: ret = a / (np.exp(k1 * (x - x1)) + np.exp(k2 * (x - x2))) + y0 except RuntimeWarning as e: - traceback.print_exc() + logger_.warn(e) return ret + # Map from the above functions to corresponding neuroml class fn_rate_map = { exponential: 'HHExpRate', @@ -153,6 +119,7 @@ def double_exp(x, a, k1, x1, k2, x2, y0=0): double_exp: (1e-3, -1.0, 0.0, 1.0, 0.0, 0.0), } + def randomized_curve_fit(fn, x, y, maxiter=10, best=True): """Repeatedly search for a good fit for common gate functions for HHtype channels with randomly generated initial parameter @@ -200,15 +167,15 @@ def randomized_curve_fit(fn, x, y, maxiter=10, best=True): p0 = fn_p0_map[fn] p = None p_best = None - min_err = 1e10 # A large value as placeholder + min_err = 1e10 # A large value as placeholder for ii in range(maxiter): try: - p = curve_fit(fn, x, y, p0=p0, full_output=True) - except (RuntimeError, RuntimeWarning) as e: + p = _SO.curve_fit(fn, x, y, p0=p0) + except (RuntimeError, RuntimeWarning): p = None # The last entry returned by scipy.optimize.leastsq used by # curve_fit is 1, 2, 3 or 4 if it succeeds. - bad = (p is None) or np.any(p[1] == np.inf) or (p[-1] not in [1, 2, 3, 4]) + bad = (p is None) or (p[1] == np.inf).any() if not bad: if not best: return p @@ -216,17 +183,22 @@ def randomized_curve_fit(fn, x, y, maxiter=10, best=True): if err < min_err: min_err = err p_best = p - p0 = np.random.uniform(low=min(x), high=max(x), size=len(fn_p0_map[fn])) + p0 = np.random.uniform(low=min(x), + high=max(x), + size=len(fn_p0_map[fn])) if p0[1] != 0.0: - p0[1] = 1 / p0[1] # k = 1/v_scale - could help faster convergence + p0[1] = 1 / p0[1] # k = 1/v_scale - could help faster convergence if p_best is None: if p is not None: msg = p[-2] else: msg = '' - warnings.warn('Maximum iteration %d reached. Could not find a decent fit. %s' % (maxiter, msg), RuntimeWarning) + warnings.warn( + 'Maximum iteration %d reached. Could not find a decent fit. %s' % + (maxiter, msg), RuntimeWarning) return p_best + def find_ratefn(x, y, **kwargs): """Find the function that fits the rate function best. This will try exponential, sigmoid and linoid and return the best fit. @@ -254,7 +226,7 @@ def find_ratefn(x, y, **kwargs): the optimal parameter values for the best fit function. """ - rms_error = 1e10 # arbitrarily setting this + rms_error = 1e10 # arbitrarily setting this best_fn = None best_p = None for fn in fn_rate_map: @@ -262,7 +234,6 @@ def find_ratefn(x, y, **kwargs): if p is None: continue popt = p[0] - pcov = p[1] error = y - fn(x, *popt) erms = np.sqrt(np.mean(error**2)) # Ideally I want a fuzzy selection criterion here - a @@ -273,16 +244,9 @@ def find_ratefn(x, y, **kwargs): # as a strong argument for taking a longer parameter function # as a really better fit. Even with 1%, double exponential # betters detected sigmoid for sigmoid curve in test case. - if erms < rms_error and \ - ((best_p is None) or \ - len(popt) <= len(best_p) or \ - erms / (max(y) - min(y)) < 0.001): + if erms < rms_error and ((best_p is None) or len(popt) <= len(best_p) + or erms / (max(y) - min(y)) < 0.001): rms_error = erms best_fn = fn best_p = popt return (best_fn, best_p) - - - -# -# hhfit.py ends here diff --git a/python/moose/neuroml2/reader.py b/python/moose/neuroml2/reader.py index 1629e6de..d858872c 100644 --- a/python/moose/neuroml2/reader.py +++ b/python/moose/neuroml2/reader.py @@ -23,10 +23,8 @@ import moose import logging -logging.basicConfig( format=moose.LOGGING_FORMAT ) -logger_ = logging.getLogger(__name__) +logger_ = logging.getLogger('moose.nml2') -import moose import neuroml as nml import pyneuroml.pynml as pynml from moose.neuroml2.units import SI @@ -276,7 +274,7 @@ def createCellPrototype(self, cell, symmetric=True): ep = '%s/%s' % (self.lib.path, cell.id) nrn = moose.element(ep) if moose.exists(ep) else moose.Neuron(ep) self.proto_cells[cell.id] = nrn - self.nml_to_moose[cell] = nrn + self.nml_to_moose[cell.id] = nrn self.moose_to_nml[nrn] = cell self.createMorphology(cell, nrn, symmetric=symmetric) self.importBiophysics(cell, nrn) @@ -323,7 +321,7 @@ def createMorphology(self, nmlcell, moosecell, symmetric=True): except AttributeError: parent = None self.moose_to_nml[comp] = segment - self.nml_to_moose[segment] = comp + self.nml_to_moose[segment.id] = comp p0 = segment.proximal if p0 is None: if parent: @@ -358,7 +356,7 @@ def createMorphology(self, nmlcell, moosecell, symmetric=True): if not 'all' in sg_to_segments: sg_to_segments['all'] = [ s for s in segments ] - self._cell_to_sg[nmlcell] = sg_to_segments + self._cell_to_sg[nmlcell.id] = sg_to_segments return id_to_comp, id_to_segment, sg_to_segments def importBiophysics(self, nmlcell, moosecell): @@ -380,19 +378,19 @@ def importMembraneProperties(self, nmlcell, moosecell, mp): self.importInitMembPotential(nmlcell, moosecell, mp) def importCapacitances(self, nmlcell, moosecell, specificCapacitances): - sg_to_segments = self._cell_to_sg[nmlcell] + sg_to_segments = self._cell_to_sg[nmlcell.id] for specific_cm in specificCapacitances: cm = SI(specific_cm.value) for seg in sg_to_segments[specific_cm.segment_groups]: - comp = self.nml_to_moose[seg] + comp = self.nml_to_moose[seg.id] comp.Cm = sarea(comp) * cm def importInitMembPotential(self, nmlcell, moosecell, membraneProperties): - sg_to_segments = self._cell_to_sg[nmlcell] + sg_to_segments = self._cell_to_sg[nmlcell.id] for imp in membraneProperties.init_memb_potentials: initv = SI(imp.value) for seg in sg_to_segments[imp.segment_groups]: - comp = self.nml_to_moose[seg] + comp = self.nml_to_moose[seg.id] comp.initVm = initv def importIntracellularProperties(self, nmlcell, moosecell, properties): @@ -400,7 +398,7 @@ def importIntracellularProperties(self, nmlcell, moosecell, properties): self.importSpecies(nmlcell, properties) def importSpecies(self, nmlcell, properties): - sg_to_segments = self._cell_to_sg[nmlcell] + sg_to_segments = self._cell_to_sg[nmlcell.id] for species in properties.species: # Developer note: Not sure if species.concentration_model should be # a nml element of just plain string. I was getting plain text from @@ -411,7 +409,7 @@ def importSpecies(self, nmlcell, properties): continue segments = getSegments(nmlcell, species, sg_to_segments) for seg in segments: - comp = self.nml_to_moose[seg] + comp = self.nml_to_moose[seg.id] self.copySpecies(species, comp) def copySpecies(self, species, compartment): @@ -439,11 +437,11 @@ def copySpecies(self, species, compartment): return pool def importAxialResistance(self, nmlcell, intracellularProperties): - sg_to_segments = self._cell_to_sg[nmlcell] + sg_to_segments = self._cell_to_sg[nmlcell.id] for r in intracellularProperties.resistivities: segments = getSegments(nmlcell, r, sg_to_segments) for seg in segments: - comp = self.nml_to_moose[seg] + comp = self.nml_to_moose[seg.id] setRa(comp, SI(r.value)) def isPassiveChan(self,chan): @@ -503,7 +501,7 @@ def calculateRateFn(self, ratefn, vmin, vmax, tablen=3000, vShift='0mV'): def importChannelsToCell(self, nmlcell, moosecell, membrane_properties): - sg_to_segments = self._cell_to_sg[nmlcell] + sg_to_segments = self._cell_to_sg[nmlcell.id] for chdens in membrane_properties.channel_densities + membrane_properties.channel_density_v_shifts: segments = getSegments(nmlcell, chdens, sg_to_segments) condDensity = SI(chdens.cond_density) @@ -522,11 +520,11 @@ def importChannelsToCell(self, nmlcell, moosecell, membrane_properties): if self.isPassiveChan(ionChannel): for seg in segments: # comp = self.nml_to_moose[seg] - setRm(self.nml_to_moose[seg], condDensity) - setEk(self.nml_to_moose[seg], erev) + setRm(self.nml_to_moose[seg.id], condDensity) + setEk(self.nml_to_moose[seg.id], erev) else: for seg in segments: - self.copyChannel(chdens, self.nml_to_moose[seg], condDensity, erev) + self.copyChannel(chdens, self.nml_to_moose[seg.id], condDensity, erev) '''moose.le(self.nml_to_moose[seg]) moose.showfield(self.nml_to_moose[seg], field="*", showtype=True)''' @@ -684,7 +682,7 @@ def importIonChannels(self, doc, vmin=-150e-3, vmax=100e-3, vdivs=5000): mchan = self.createHHChannel(chan) self.id_to_ionChannel[chan.id] = chan - self.nml_to_moose[chan] = mchan + self.nml_to_moose[chan.id] = mchan self.proto_chans[chan.id] = mchan logger_.info(self.filename + ': Created ion channel %s for %s %s'%( mchan.path, chan.type, chan.id)) diff --git a/python/moose/neuroml2/test_converter.py b/python/moose/neuroml2/test_converter.py deleted file mode 100644 index 20108b82..00000000 --- a/python/moose/neuroml2/test_converter.py +++ /dev/null @@ -1,104 +0,0 @@ -# -*- coding: utf-8 -*- -# test_converter.py --- -# -# Filename: test_converter.py -# Description: -# Author: -# Maintainer: -# Created: Tue Apr 23 18:51:58 2013 (+0530) -# Version: -# Last-Updated: Tue May 21 16:59:09 2013 (+0530) -# By: subha -# Update #: 327 -# URL: -# Keywords: -# Compatibility: -# -# - -# Commentary: -# -# -# -# - -# Change log: -# -# Tue May 21 16:58:53 IST 2013 - Subha moved code for testing curve -# fitting to test_hhfit.py. - -# -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 3, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, Fifth -# Floor, Boston, MA 02110-1301, USA. -# -# - -# Code: - -from __future__ import print_function -import os -import numpy as np -import uuid -import unittest -import pylab -import moose -import converter -import neuroml -from neuroml.writers import NeuroMLWriter - -outdir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'tmp') -if not os.access(outdir, os.F_OK): - print('Creating output directory', outdir) - os.mkdir(outdir) - -class TestConvertMorphology(unittest.TestCase): - def setUp(self): - self.test_id = uuid.uuid4() - self.model_container = moose.Neutral('test%s' % (self.test_id)) - self.neuron = moose.Neuron('%s/cell' % (self.model_container.path)) - self.soma = moose.Compartment('%s/soma' % (self.neuron.path)) - self.soma.diameter = 20e-6 - self.soma.length = 0.0 - parent = self.soma - comps = [] - for ii in range(100): - comp = moose.Compartment('%s/comp_%d' % (self.neuron.path, ii)) - comp.diameter = 10e-6 - comp.length = 100e-6 - moose.connect(parent, 'raxial', comp, 'axial') - comps.append(comp) - parent = comp - - def test_convert_morphology(self): - morph = converter.convert_morphology(self.neuron, positions='auto') - cell = neuroml.Cell() - cell.name = self.neuron.name - cell.id = cell.name - cell.morphology = morph - doc = neuroml.NeuroMLDocument() - doc.cells.append(cell) - doc.id = 'TestNeuroMLDocument' - fname = os.path.join(outdir, 'test_morphology_conversion.nml') - NeuroMLWriter.write(doc, fname) - print('Wrote', fname) - -if __name__ == '__main__': - unittest.main() - - - -# -# test_converter.py ends here diff --git a/python/moose/neuroml2/test_hhfit.py b/python/moose/neuroml2/test_hhfit.py deleted file mode 100644 index b97109f3..00000000 --- a/python/moose/neuroml2/test_hhfit.py +++ /dev/null @@ -1,157 +0,0 @@ -# -*- coding: utf-8 -*- -# test_hhfit.py --- -# -# Filename: test_hhfit.py -# Description: -# Author: -# Maintainer: -# Created: Tue May 21 16:34:45 2013 (+0530) -# Version: -# Last-Updated: Tue May 21 16:37:28 2013 (+0530) -# By: subha -# Update #: 9 -# URL: -# Keywords: -# Compatibility: -# -# - -# Commentary: -# -# -# -# - -# Change log: -# -# Tue May 21 16:34:53 IST 2013 - Subha moved code from -# test_converter.py to test_hhfit.py. - -# -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 3, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, Fifth -# Floor, Boston, MA 02110-1301, USA. -# -# - -# Code: - -from __future__ import print_function -import os -import numpy as np -import uuid -import unittest -import pylab -import hhfit - -class TestFindRateFn(unittest.TestCase): - def setUp(self): - self.vmin = -120e-3 - self.vmax = 40e-3 - self.vdivs = 640 - self.v_array = np.linspace(self.vmin, self.vmax, self.vdivs+1) - # Parameters for sigmoid function - from traub2005, NaF->m_inf - p_sigmoid = (1.0, 1/-10e-3, -38e-3, 0.0) - self.sigmoid = p_sigmoid[0] / (1.0 + np.exp(p_sigmoid[1] * (self.v_array - p_sigmoid[2]))) + p_sigmoid[3] - self.p_sigmoid = p_sigmoid - # Parameters for exponential function - from traub2005, KC->n_inf - p_exp = (2e3, 1/-27e-3, -53.5e-3, 0.0) - self.exp = p_exp[0] * np.exp(p_exp[1] * (self.v_array - p_exp[2])) + p_exp[3] - self.p_exp = p_exp - # Parameters for linoid function: alpha_n from original Hodgkin-Huxley K channel. - p_linoid = (-0.01*1e3, -1/10e-3, 10e-3, 0.0) - self.linoid = p_linoid[3] + p_linoid[0] * (self.v_array - p_linoid[2]) / (np.exp(p_linoid[1] * (self.v_array - p_linoid[2])) - 1) - self.p_linoid = p_linoid - # This is tau_m of transient Ca2+ current (eq. 7) from - # Huguenard and McCormick, J Neurophysiol, 68:1373-1383, - # 1992.; - #1e-3 * (0.612 + 1 / (np.exp((self.v_array*1e3 + 132)/-16.7) + np.exp((self.v_array*1e3 + 16.8)/18.2))) - p_dblexp = (1e-3, -1/16.7e-3, -132e-3, 1/18.2e-3, -16.8e-3, 0.612e-3) - self.dblexp = p_dblexp[5] + p_dblexp[0] / (np.exp(p_dblexp[1] * (self.v_array - p_dblexp[2])) + - np.exp(p_dblexp[3] * (self.v_array - p_dblexp[4]))) - self.p_dblexp = p_dblexp - - def test_sigmoid(self): - print('Testing sigmoid') - fn, params = hhfit.find_ratefn(self.v_array, self.sigmoid) - print('Sigmoid params original:', self.p_sigmoid, 'detected:', params) - pylab.plot(self.v_array, self.sigmoid, 'y-', - self.v_array, hhfit.sigmoid(self.v_array, *self.p_sigmoid), 'b--', - self.v_array, fn(self.v_array, *params), 'r-.') - pylab.legend(('original sigmoid', 'computed', 'fitted %s' % (fn))) - pylab.show() - self.assertEqual(hhfit.sigmoid, fn) - rms_error = np.sqrt(np.mean((self.sigmoid - fn(self.v_array, *params))**2)) - self.assertAlmostEqual(rms_error/max(abs(self.sigmoid)), 0.0, places=3) - - def test_exponential(self): - print('Testing exponential') - fn, params = hhfit.find_ratefn(self.v_array, self.exp) - print('Exponential params original:', self.p_exp, 'detected:', params) - fnval = hhfit.exponential(self.v_array, *params) - pylab.plot(self.v_array, self.exp, 'y-', - self.v_array, hhfit.exponential(self.v_array, *self.p_exp), 'b--', - self.v_array, fnval, 'r-.') - pylab.legend(('original exp', 'computed', 'fitted %s' % (fn))) - pylab.show() - self.assertEqual(hhfit.exponential, fn) - # The same exponential can be satisfied by an infinite number - # of parameter values. Hence we cannot compare the parameters, - # but only the fit - rms_error = np.sqrt(np.sum((self.exp - fnval)**2)) - # pylab.plot(self.v_array, self.exp, 'b-') - # pylab.plot(self.v_array, fnval, 'r-.') - # pylab.show() - print(rms_error, rms_error/max(self.exp)) - self.assertAlmostEqual(rms_error/max(self.exp), 0.0, places=3) - - def test_linoid(self): - print('Testing linoid') - fn, params = hhfit.find_ratefn(self.v_array, self.linoid) - print('Linoid params original:', self.p_linoid, 'detected:', params) - pylab.plot(self.v_array, self.linoid, 'y-', - self.v_array, hhfit.linoid(self.v_array, *self.p_linoid), 'b--', - self.v_array, fn(self.v_array, *params), 'r-.') - pylab.legend(('original linoid', 'computed', 'fitted %s' % (fn))) - pylab.show() - self.assertEqual(hhfit.linoid, fn) - fnval = fn(self.v_array, *params) - rms_error = np.sqrt(np.mean((self.linoid - fnval)**2)) - self.assertAlmostEqual(rms_error/max(self.linoid), 0.0, places=3) - # errors = params - np.array(self.p_linoid) - # for orig, err in zip(self.p_linoid, errors): - # self.assertAlmostEqual(abs(err/orig), 0.0, places=2) - - def test_dblexponential(self): - print('Testing double exponential') - fn, params = hhfit.find_ratefn(self.v_array, self.dblexp) - fnval = fn(self.v_array, *params) - pylab.plot(self.v_array, self.dblexp, 'y-', - self.v_array, hhfit.double_exp(self.v_array, *self.p_dblexp), 'b--', - self.v_array, fnval, 'r-.') - pylab.legend(('original dblexp', 'computed', 'fitted %s' % (fn))) - pylab.show() - self.assertEqual(hhfit.double_exp, fn) - rms_error = np.sqrt(np.mean((self.dblexp - fnval)**2)) - print(params, rms_error) - self.assertAlmostEqual(rms_error/max(self.dblexp), 0.0, places=3) - - -if __name__ == '__main__': - unittest.main() - - -# -# test_hhfit.py ends here diff --git a/python/moose/plot_utils.py b/python/moose/plot_utils.py index a680dbbe..97d3ee0f 100644 --- a/python/moose/plot_utils.py +++ b/python/moose/plot_utils.py @@ -15,10 +15,7 @@ import moose import moose.print_utils as pu import re - -# To support python 2.6. On Python3.6+, dictionaries are ordered by default. -# This is here to fill this gap. -from moose.OrderedDict import OrderedDict +from collections import OrderedDict def plotAscii(yvec, xvec = None, file=None): """Plot two list-like object in terminal using gnuplot. @@ -128,14 +125,23 @@ def plotTable(table, **kwargs): plt.legend(loc='best') def plotTables(tables, outfile=None, **kwargs): - """Plot a list of tables onto one figure only. + """Plot a dict of tables. + + Each axis will be labeled with dict keys. The dict values must be + moose.Table/moose.Table2. + + :param outfile: Default `None`. If given, plot will be saved to this filepath. + :param grid: A tuple with (cols, rows), default is (len(tables)//2+1, 2) + :param figsize: Size of figure (W, H) in inches. Default (10, 1.5*len(tables)) """ assert type(tables) == dict, "Expected a dict of moose.Table" - plt.figure(figsize=(10, 1.5*len(tables))) + plt.figure(figsize=kwargs.get('figsize', (10, 1.5*len(tables)))) subplot = kwargs.get('subplot', True) + gridSize = kwargs.get('grid', (len(tables)//2+1, 2)) for i, tname in enumerate(tables): if subplot: - plt.subplot(len(tables), 1, i+1) + assert gridSize[0] <= 9 + plt.subplot(100*gridSize[0]+10*gridSize[1]+(i+1)) yvec = tables[tname].vector xvec = np.linspace(0, moose.Clock('/clock').currentTime, len(yvec)) plt.plot(xvec, yvec, label=tname) @@ -152,9 +158,7 @@ def plotTables(tables, outfile=None, **kwargs): try: plt.savefig(outfile, transparent=True) except Exception as e: - pu.dump("WARN" - , "Failed to save figure, plotting onto a window" - ) + pu.dump("WARN", "Failed to save figure. Errror %s"%e) plt.show() else: plt.show() @@ -239,10 +243,9 @@ def plotRecords(records, xvec = None, **kwargs): try: for k in sorted(records.keys(), key=str.lower): dataDict[k] = records[k] - except Exception as e: + except Exception: dataDict = records - legend = kwargs.get('legend', True) outfile = kwargs.get('outfile', None) subplot = kwargs.get('subplot', False) filters = [ x.lower() for x in kwargs.get('filter', [])] diff --git a/python/moose/server.py b/python/moose/server.py index 9a9820e6..7f81d2e7 100644 --- a/python/moose/server.py +++ b/python/moose/server.py @@ -317,7 +317,7 @@ def find_files_to_run( files ): with open(f, 'r' ) as fh: txt = fh.read() if re.search(r'def\s+main\(', txt): - if re.search('^\s+main\(\S+?\)', txt): + if re.search(r'^\s+main\(\S+?\)', txt): toRun.append(f) return toRun diff --git a/python/moose/utils.py b/python/moose/utils.py index a5aba951..4ed1402e 100644 --- a/python/moose/utils.py +++ b/python/moose/utils.py @@ -16,13 +16,22 @@ from collections import defaultdict import re +import logging +logger_ = logging.getLogger('moose.utils') + from moose.moose_constants import * from moose.print_utils import * + +try: + from moose.network_utils import * +except Exception as e: + logger_.warn("Netowrk utilities are not loaded due to %s" % e) + # Print and Plot utilities. try: from moose.plot_utils import * except Exception as e: - info( "Plot utilities are not loaded due to '%s'" % e ) + logger_.warn( "Plot utilities are not loaded due to '%s'" % e ) def create_table_path(model, graph, element, field): @@ -83,7 +92,7 @@ def readtable(table, filename, separator=None): for line in in_file: line_no = line_no + 1 tokens = line.split(separator) - if len(tokens) is 0: + if not tokens: continue elif len(tokens) == 1: table[ii] = float(tokens[0]) @@ -521,13 +530,13 @@ def assignDefaultTicks(modelRoot='/model', dataRoot='/data', solver='hsolve'): def stepRun(simtime, steptime, verbose=True, logger=None): """Run the simulation in steps of `steptime` for `simtime`.""" + global logger_ + if logger is None: + logger = logger_ clock = moose.element('/clock') if verbose: msg = 'Starting simulation for %g' % (simtime) - if logger is None: - print(msg) - else: - logger.info(msg) + logger_.info(msg) ts = datetime.now() while clock.currentTime < simtime - steptime: ts1 = datetime.now() @@ -536,29 +545,20 @@ def stepRun(simtime, steptime, verbose=True, logger=None): td = te - ts1 if verbose: msg = 'Simulated till %g. Left: %g. %g of simulation took: %g s' % (clock.currentTime, simtime - clock.currentTime, steptime, td.days * 86400 + td.seconds + 1e-6 * td.microseconds) - if logger is None: - print(msg) - else: - logger.info(msg) + logger_.info(msg) remaining = simtime - clock.currentTime if remaining > 0: if verbose: msg = 'Running the remaining %g.' % (remaining) - if logger is None: - print(msg) - else: - logger.info(msg) + logger_.info(msg) moose.start(remaining) te = datetime.now() td = te - ts dt = min([t for t in moose.element('/clock').dts if t > 0.0]) if verbose: msg = 'Finished simulation of %g with minimum dt=%g in %g s' % (simtime, dt, td.days * 86400 + td.seconds + 1e-6 * td.microseconds) - if logger is None: - print(msg) - else: - logger.info(msg) + logger_.info(msg) diff --git a/python/moose/wrapper.py b/python/moose/wrapper.py new file mode 100644 index 00000000..9a85f3aa --- /dev/null +++ b/python/moose/wrapper.py @@ -0,0 +1,212 @@ +# -*- coding: utf-8 -*- +from __future__ import print_function, division, absolute_import + +# Wrappers around _moose.so classes. These wrappers accomplish the following. +# +# 1. When `moose.MooseClass(path)` is called and pass already exsists, +# `moose.element(path)` is returned. +# 2. `moose.connect(a, 'f1', b, 'f2')` can also be called as +# a.connect('f1', b, 'fn2') + +__author__ = "Dilawar Singh" +__copyright__ = "Copyright 2019-, Dilawar Singh" +__maintainer__ = "Dilawar Singh" +__email__ = "dilawars@ncbs.res.in" + +import difflib +import moose._moose as _moose +import pprint + +import logging + +logger_ = logging.getLogger("moose") + +# Provide a pretty printer. +pprint = pprint.pprint + +sympyFound_ = False +try: + import sympy + + sympy.init_printing(use_unicode=True) + sympyFound_ = True + # When sympy is found, pprint is sympy pprint. + pprint = sympy.pprint +except ImportError: + pass + + +def _didYouMean(v, options): + """Did you mean this when you types v + """ + return " or ".join(difflib.get_close_matches(v, list(options), n=2)) + + +def _eval(expr): + try: + if isinstance(expr, (int, float)): + return expr + return eval(str(expr)) + except Exception: + return expr + + +def _prettifyExpr(expr): + global sympyFound_ + if not sympyFound_: + return expr + try: + return sympy.pretty(sympy.simplify(expr, use_unicode=True)) + except Exception: + return expr + + +# Generic wrapper around moose.Neutral +class Neutral(_moose.Neutral): + def __init__(self, path, n=1, g=0, dtype="Neutral", **kwargs): + super(Neutral, self).__init__(path, n, g, dtype) + for k in kwargs: + try: + setattr(self, k, kwargs[k]) + except AttributeError: + logging.warn("Attribute %s is not found. Ignoring..." % k) + + def __new__(cls, pathOrObject, n=1, g=0, dtype="Neutral", **kwargs): + path = pathOrObject + if not isinstance(pathOrObject, str): + path = pathOrObject.path + if _moose.exists(path): + # logger_.info("%s already exists. Returning old element."%path) + return _moose.element(path) + return super(Neutral, cls).__new__(cls, pathOrObject, n, g, dtype) + + def connect(self, srcField, dest, destField): + """Wrapper around moose.connect. + """ + allSrcFields = self.sourceFields + allDestFields = dest.destFields + + if srcField not in allSrcFields: + logger_.warn( + "Could not find '{}' in {} sourceFields.".format(srcField, self) + ) + dym = _didYouMean(srcField, allSrcFields) + if dym: + logger_.warn("\tDid you mean %s?" % dym) + else: + logger_.warn(": Available options: %s" % ", ".join(allSrcFields)) + raise NameError("Failed to connect") + if destField not in allDestFields: + logger_.error( + "Could not find '{0}' in {1} destFields.".format(destField, dest) + ) + dym = _didYouMean(destField, allDestFields) + if dym: + logger_.warn("\tDid you mean %s?" % dym) + else: + logger_.warn(": Available options: %s" % ", ".join(allDestFields)) + raise NameError("Failed to connect") + + # Everything looks fine. Connect now. + _moose.connect(self, srcField, dest, destField) + + +class Function(_moose.Function, Neutral): + """Overides moose._Function + + Provides a convinient way to set expression and connect variables. + """ + + __expr = "" + + def __init__(self, path, n=1, g=0, dtype="Function", **kwargs): + super(Function, self).__init__(path, n, g, dtype) + for k in kwargs: + try: + setattr(self, k, kwargs[k]) + except AttributeError: + logging.warn("Attribute %s is not found. Ignoring..." % k) + + def __getitem__(self, key): + """Override [] operator. It returns the linked variable by name. + """ + assert self.numVars > 0 + return self.x[self.xindex[key]] + + def compile(self, expr, constants={}, variables=[], mode=0, **kwargs): + """Add an expression to a given function. + """ + __expr = expr + # Replace constants. + constants = {k: v for k, v in sorted(constants.items(), key=lambda x: len(x))} + for i, constName in enumerate(constants): + # replace constName with 'c%d' % i + mooseConstName = "c%d" % i + expr = expr.replace(constName, mooseConstName) + self.c[mooseConstName] = _eval(constants[constName]) + + self.expr = expr + self.mode = mode + if kwargs.get("independent", ""): + self.independent = kwargs["independent"] + + if __expr != expr: + msg = "Expression has been changed to MOOSE's form." + msg += "\nFrom,\n" + msg += _prettifyExpr(__expr) + msg += "\nto, \n" + msg += _prettifyExpr(expr) + logging.warn(msg.replace("\n", "\n ï¹… ")) + + # alias + setExpr = compile + + def sympyExpr(self): + import sympy + + return sympy.simplify(self.expr) + + def printUsingSympy(self): + """Print function expression using sympy. + """ + import sympy + + sympy.pprint(self.sympyExpr()) + + +def addAttrib(mooseObject, **kwargs): + for k, v in kwargs.items(): + try: + setattr(mooseObject, k, v) + except AttributeError: + logger_.warn("Attribute {0} not found on {1}".format(k, v)) + + +class StimulusTable(_moose.StimulusTable, Neutral): + """StimulusTable + Wrapper around _moose.StimulusTable + """ + + def __init__(self, path, n=1, g=0, dtype="StimulusTable", **kwargs): + super(StimulusTable, self).__init__(path, n, g, dtype) + addAttrib(self, **kwargs) + + +class IntFire(_moose.IntFire, Neutral): + """IntFire + Wrapper around _moose.IntFire + """ + + def __init__(self, path, n=1, g=0, dtype="IntFire", **kwargs): + super(IntFire, self).__init__(path, n, g, dtype) + addAttrib(self, **kwargs) + + +class PulseGen(_moose.PulseGen, Neutral): + """PulseGen + Wrapper around _moose.PulseGen + """ + + def __init__(self, path, n=1, g=0, dtype="PulseGen", **kwargs): + super(PulseGen, self).__init__(path, n, g, dtype) + addAttrib(self, **kwargs) diff --git a/python/rdesigneur/rdesigneur.py b/python/rdesigneur/rdesigneur.py index c1cb25ec..2849fc55 100644 --- a/python/rdesigneur/rdesigneur.py +++ b/python/rdesigneur/rdesigneur.py @@ -16,9 +16,11 @@ ## latter in the former, including mapping entities like calcium and ## channel conductances, between them. ########################################################################## -from __future__ import print_function, absolute_import +from __future__ import print_function, absolute_import, division +# FIXME: Deprecated since 3.4 import imp + import os import moose import numpy as np @@ -45,6 +47,19 @@ #EREST_ACT = -70e-3 +def _profile(func): + """ + Can be used to profile a function. Useful in debugging and profiling. + Author: Dilawar Singh + """ + def wrap(self=None, *args, **kwargs): + t0 = time.time() + result = func(self, *args, **kwargs) + print("[INFO ] Took %s sec" % (time.time()-t0)) + return result + return wrap + + class BuildError(Exception): def __init__(self, value): self.value = value @@ -99,6 +114,7 @@ def __init__(self, stimList = [], plotList = [], # elecpath, geom_expr, object, field, title ['wave' [min max]] moogList = [], + ode_method = "gsl", # gsl, lsoda, gssa, gillespie params = None ): """ Constructor of the rdesigner. This just sets up internal fields @@ -108,6 +124,7 @@ def __init__(self, self.modelPath = modelPath self.turnOffElec = turnOffElec self.useGssa = useGssa + self.ode_method = ode_method self.combineSegments = combineSegments self.stealCellFromLibrary = stealCellFromLibrary self.verbose = verbose @@ -116,7 +133,9 @@ def __init__(self, self.addEndoChemCompt = addEndoChemCompt self.diffusionLength= diffusionLength if meshLambda > 0.0: - print("Warning: meshLambda argument is deprecated. Please use 'diffusionLength' instead.\nFor now rdesigneur will accept this argument.") + print("Warning: meshLambda argument is deprecated. Please use " + "'diffusionLength' instead.\nFor now rdesigneur will " + "accept this argument.") self.diffusionLength = meshLambda self.temperature = temperature self.chemDt= chemDt @@ -148,7 +167,6 @@ def __init__(self, print("Error: rdesigneur: " + msg) quit() - #self.saveList = plotList #ADDED BY Sarthak self.saveAs = [] self.plotNames = [] self.wavePlotNames = [] @@ -175,16 +193,16 @@ def __init__(self, def _printModelStats( self ): if not self.verbose: return - print("\nRdesigneur: Elec model has", + print("Rdesigneur: Elec model has", self.elecid.numCompartments, "compartments and", self.elecid.numSpines, "spines on", len( self.cellPortionElist ), "compartments.") if hasattr( self , 'chemid') and len( self.chemDistrib ) > 0: - dmstoich = moose.element( self.dendCompt.path + '/stoich' ) - print("\tChem part of model has the following compartments: ") + # dmstoich = moose.element( self.dendCompt.path + '/stoich' ) + print(" Chem part of model has the following compartments: ") for j in moose.wildcardFind( '/model/chem/##[ISA=ChemCompt]'): s = moose.element( j.path + '/stoich' ) - print( "\t | In {}, {} voxels X {} pools".format( j.name, j.mesh.num, s.numAllPools ) ) + print( " | In {}, {} voxels X {} pools".format( j.name, j.mesh.num, s.numAllPools ) ) def buildModel( self, modelPath = '/model' ): if moose.exists( modelPath ): @@ -193,28 +211,28 @@ def buildModel( self, modelPath = '/model' ): return self.model = moose.Neutral( modelPath ) self.modelPath = modelPath - funcs = [ self.installCellFromProtos, self.buildPassiveDistrib + funcs = [self.installCellFromProtos, self.buildPassiveDistrib , self.buildChanDistrib, self.buildSpineDistrib, self.buildChemDistrib , self._configureSolvers, self.buildAdaptors, self._buildStims , self._buildPlots, self._buildMoogli, self._configureHSolve - , self._configureClocks, self._printModelStats - ] - for i, _func in enumerate( funcs ): + , self._configureClocks, self._printModelStats] + + for i, _func in enumerate(funcs): if self.benchmark: - print( " + (%d/%d) executing %25s"%(i, len(funcs), _func.__name__), end=' ' ) + print("- (%02d/%d) Executing %25s"%(i+1, len(funcs), _func.__name__), end=' ' ) t0 = time.time() try: - _func( ) + _func() except BuildError as msg: print("Error: rdesigneur: model build failed:", msg) - moose.delete( self.model ) + moose.delete(self.model) return t = time.time() - t0 if self.benchmark: msg = r' ... DONE' - if t > 1: + if t > 0.1: msg += ' %.3f sec' % t - print( msg ) + print(msg) sys.stdout.flush() def installCellFromProtos( self ): @@ -460,6 +478,9 @@ def _buildVclampOnCompt( self, dendCompts, spineCompts, stimInfo ): stimObj = [] for i in dendCompts + spineCompts: vclamp = make_vclamp( name = 'vclamp', parent = i.path ) + + # Assume SI units. Scale by Cm to get reasonable gain. + vclamp.gain = i.Cm * 1e4 moose.connect( i, 'VmOut', vclamp, 'sensedIn' ) moose.connect( vclamp, 'currentOut', i, 'injectMsg' ) stimObj.append( vclamp ) @@ -772,9 +793,9 @@ def displayMoogli( self, moogliDt, runtime, rotation = math.pi/500.0, fullscreen moose.reinit() moose.start( runtime ) if block: - self.display( len( self.moogNames ) + 1 ) + self.display( len( self.moogNames ) + 1) - def display( self, startIndex = 0 ): + def display( self, startIndex = 0, block=True ): for i in self.plotNames: plt.figure( i[2] + startIndex ) plt.title( i[1] ) @@ -800,7 +821,7 @@ def display( self, startIndex = 0 ): if len( self.wavePlotNames ) > 0: for i in range( 3 ): self.displayWavePlots() - plt.show( block=True ) + plt.show( block=block ) self._save() @@ -812,7 +833,7 @@ def initWavePlots( self, startIndex ): if len( vtab ) < 2: print( "Warning: Waveplot {} abandoned, only {} points".format( i[1], len( vtab ) ) ) continue - dFrame = len( vtab[0].vector ) / self.numWaveFrames + dFrame = len( vtab[0].vector ) // self.numWaveFrames if dFrame < 1: dFrame = 1 vpts = np.array( [ [k.vector[j] for j in range( 0, len( k.vector ), dFrame ) ] for k in vtab] ).T * i[3] @@ -1267,6 +1288,7 @@ def _assignComptNamesFromKkit( self ): #print( "SortedClist= {}".format( sortedComptList[i] )) if sortedComptList[i].name != sortedNames[i]: sortedComptList[i].name = sortedNames[i] + #print( "SortedClist= {} {}".format( sortedNames[i], sortedComptList[i].volume )) return sortedComptList @@ -1330,6 +1352,7 @@ def _configureSolvers( self ) : raise BuildError( "configureSolvers: no chem meshes defined." ) fixXreacs.fixXreacs( self.chemid.path ) dmksolve = moose.Ksolve( self.dendCompt.path + '/ksolve' ) + dmksolve.method = self.ode_method dmdsolve = moose.Dsolve( self.dendCompt.path + '/dsolve' ) dmstoich = moose.Stoich( self.dendCompt.path + '/stoich' ) dmstoich.compartment = self.dendCompt @@ -1343,6 +1366,7 @@ def _configureSolvers( self ) : smksolve = moose.Gsolve( self.spineCompt.path + '/ksolve' ) else: smksolve = moose.Ksolve( self.spineCompt.path + '/ksolve' ) + smksolve.method = self.ode_method smdsolve = moose.Dsolve( self.spineCompt.path + '/dsolve' ) smstoich = moose.Stoich( self.spineCompt.path + '/stoich' ) smstoich.compartment = self.spineCompt @@ -1354,6 +1378,7 @@ def _configureSolvers( self ) : pmksolve = moose.Gsolve( self.psdCompt.path + '/ksolve' ) else: pmksolve = moose.Ksolve( self.psdCompt.path + '/ksolve' ) + pmksolve.method = self.ode_method pmdsolve = moose.Dsolve( self.psdCompt.path + '/dsolve' ) pmstoich = moose.Stoich( self.psdCompt.path + '/stoich' ) pmstoich.compartment = self.psdCompt @@ -1564,7 +1589,6 @@ def convertArg( arg ): else: raise BuildError( "rmoog initialization failed" ) - # Stimlist = [path, geomExpr, relPath, field, expr_string] class rstim( baseplot ): def __init__( self, elecpath = 'soma', geom_expr = '1', relpath = '.', field = 'inject', expr = '0'): diff --git a/python/rdesigneur/rdesigneurProtos.py b/python/rdesigneur/rdesigneurProtos.py index 991bf4e8..b71ce8e4 100644 --- a/python/rdesigneur/rdesigneurProtos.py +++ b/python/rdesigneur/rdesigneurProtos.py @@ -240,7 +240,6 @@ def make_Ca( name ): yA[i] = 5.0 * math.exp( -50 * (x - EREST_ACT) ) else: yA[i] = 5.0 - #yB[i] = 6.0 - yA[i] yB[i] = 5.0 x += dx ygate.tableA = yA diff --git a/python/rdesigneur/rmoogli.py b/python/rdesigneur/rmoogli.py index f673dad7..c34060f0 100644 --- a/python/rdesigneur/rmoogli.py +++ b/python/rdesigneur/rmoogli.py @@ -1,4 +1,4 @@ -from __future__ import absolute_import, print_function +from __future__ import absolute_import, print_function, division # rmoogli.py: rdesigneur Moogli interface # This is a fallback version designed to work with moogul but using almost # the same interface as far as rdesigneur is concerned. diff --git a/python/setup.cmake.py b/python/setup.cmake.py deleted file mode 100644 index ca67559d..00000000 --- a/python/setup.cmake.py +++ /dev/null @@ -1,63 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import print_function - -# NOTE: This script is to be called by CMake. Not intended to be used standalone. - -__author__ = "Dilawar Singh" -__copyright__ = "Copyright 2013, Dilawar Singh and NCBS Bangalore" -__credits__ = ["NCBS Bangalore"] -__license__ = "GNU GPL" -__version__ = "1.0.0" -__maintainer__ = "Dilawar Singh" -__email__ = "dilawars@ncbs.res.in" -__status__ = "Development" - -import os -import sys - - -# NOTE: Though setuptool is preferred we use distutils. -# 1. setuptool normalize VERSION even when it is compatible with PyPI -# guidelines. This caused havoc on our OBS build. -from distutils.core import setup - - -# Read version from VERSION created by cmake file. This file must be present for -# setup.cmake.py to work perfectly. -script_dir = os.path.dirname( os.path.abspath( __file__ ) ) - -# Version file must be available. It MUST be written by cmake. Or create -# it manually before running this script. -with open( os.path.join( script_dir, 'VERSION'), 'r' ) as f: - version = f.read( ) -print( 'Got %s from VERSION file' % version ) - -# importlib is available only for python3. Since we build wheels, prefer .so -# extension. This way a wheel built by any python3.x will work with any python3. -suffix = '.so' -try: - import importlib.machinery - suffix = importlib.machinery.EXTENSION_SUFFIXES[-1] -except Exception as e: - print( '[WARN] Failed to determine importlib suffix' ) - suffix = '.so' -print( '[INFO] Suffix for python SO: %s' % suffix ) - -setup( - name = 'pymoose', - version = version, - description = 'Python scripting interface of MOOSE Simulator (https://moose.ncbs.res.in)', - author = 'MOOSERes', - author_email = 'bhalla@ncbs.res.in', - maintainer = 'Dilawar Singh', - maintainer_email = 'dilawars@ncbs.res.in', - url = 'http://moose.ncbs.res.in', - packages = [ 'rdesigneur', 'moose' - , 'moose.SBML', 'moose.genesis' - , 'moose.neuroml', 'moose.neuroml2' - , 'moose.chemUtil', 'moose.chemMerge' - ], - install_requires = [ 'numpy' ], - package_dir = { 'moose' : 'moose', 'rdesigneur' : 'rdesigneur' }, - package_data = { 'moose' : ['_moose' + suffix, 'neuroml2/schema/NeuroMLCoreDimensions.xml','chemUtil/rainbow2.pkl'] }, - ) diff --git a/randnum/CMakeLists.txt b/randnum/CMakeLists.txt index a926912a..e5ba81ca 100644 --- a/randnum/CMakeLists.txt +++ b/randnum/CMakeLists.txt @@ -1,10 +1,8 @@ cmake_minimum_required(VERSION 2.8) -add_executable( normal_dist - ${CMAKE_CURRENT_SOURCE_DIR}/test_normal_dist.cpp - ) - add_library(randnum RNG.cpp) +add_executable(normal_dist ${CMAKE_CURRENT_SOURCE_DIR}/test_normal_dist.cpp) + enable_testing() -add_test( NAME test_normal_dist COMMAND $ ) +add_test(NAME cpp_test_normal_dist COMMAND $ ) diff --git a/randnum/RNG.h b/randnum/RNG.h index 711a769a..3f925cb8 100644 --- a/randnum/RNG.h +++ b/randnum/RNG.h @@ -59,7 +59,7 @@ class RNG private: /* ==================== DATA MEMBERS ======================================= */ double res_; - size_t seed_; + double seed_; moose::MOOSE_RNG_DEFAULT_ENGINE rng_; moose::MOOSE_UNIFORM_DISTRIBUTION dist_; diff --git a/scheduling/Clock.cpp b/scheduling/Clock.cpp index aa7feb29..e905d705 100644 --- a/scheduling/Clock.cpp +++ b/scheduling/Clock.cpp @@ -700,13 +700,10 @@ void Clock::buildTicks( const Eref& e ) void Clock::handleStart( const Eref& e, double runtime, bool notify ) { notify_ = notify; - if ( stride_ == 0 || stride_ == ~0U ) stride_ = 1; unsigned long n = round( runtime / ( stride_ * dt_ ) ); - handleStep( e, n ); - } void Clock::handleStep( const Eref& e, unsigned long numSteps ) @@ -734,7 +731,9 @@ void Clock::handleStep( const Eref& e, unsigned long numSteps ) unsigned long endStep = currentStep_ + stride_; currentTime_ = info_.currTime = dt_ * endStep; -#if PARALLELIZE_CLOCK_USING_CPP11_ASYNC +#if 0 + +//#if PARALLELIZE_CLOCK_USING_CPP11_ASYNC // NOTE: It does not produce very promising results. The challenge here // is doing load-balancing. @@ -748,8 +747,7 @@ void Clock::handleStep( const Eref& e, unsigned long numSteps ) for( unsigned int i = 0; i < numThreads_; ++i ) { - std::async( std::launch::async - , [this,blockSize,i,nTasks,endStep,e] + std::async( std::launch::async, [this,blockSize,i,nTasks,endStep,e] { unsigned int mapI = i * blockSize; // Get the block we want to run in paralle. @@ -764,7 +762,7 @@ void Clock::handleStep( const Eref& e, unsigned long numSteps ) mapI++; } } - ); + ); } #else vector< unsigned int >::const_iterator k = activeTicksMap_.begin(); @@ -910,7 +908,7 @@ void Clock::buildDefaultTick() defaultTick_["HHChannel2D"] = 2; defaultTick_["Leakage"] = 2; defaultTick_["MarkovChannel"] = 2; - defaultTick_["MarkovGslSolver"] = 2; + defaultTick_["MarkovOdeSolver"] = 2; defaultTick_["MarkovRateTable"] = 2; defaultTick_["MarkovSolver"] = 2; defaultTick_["MarkovSolverBase"] = 2; diff --git a/scripts/submit.py b/scripts/submit.py deleted file mode 100755 index 93118736..00000000 --- a/scripts/submit.py +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -from __future__ import division, print_function - -__author__ = "Dilawar Singh" -__copyright__ = "Copyright 2017-, Dilawar Singh" -__version__ = "1.0.0" -__maintainer__ = "Dilawar Singh" -__email__ = "dilawars@ncbs.res.in" -__status__ = "Development" - -import sys -import os -import socket -import time -import tarfile -import tempfile - -def gen_prefix( msg, maxlength = 10 ): - msg = '>%s' % msg - if len(msg) < maxlength: - msg += ' ' * (maxlength - len(msg)) - return msg[:maxlength].encode( 'utf-8' ) - -def write_data_to_socket(conn, msg): - msg = b'%010d%s' % (len(msg), msg) - conn.sendall(msg) - -def relativePath(path, base): - return os.path.relpath(path, base) - -def gen_payload( args ): - path = args.path - archive = os.path.join(tempfile.mkdtemp(), 'data.tar.bz2') - - # This mode (w|bz2) is suitable for streaming. The blocksize is default to - # 20*512 bytes. We change this to 2048 - with tarfile.open(archive, 'w|bz2', bufsize=2048 ) as h: - if len(args.main) > 0: - for i, f in enumerate(args.main): - h.add(f, arcname='__main__%d.py'%i) - if os.path.isfile(path): - h.add(path, os.path.basename(path)) - elif os.path.isdir(path): - for d, ds, fs in os.walk(path): - for f in fs: - p = os.path.join(d, f) - h.add(os.path.realpath(p), arcname=relativePath(p, path)) - else: - print( "[ERROR] Neither file nor directory %s" % path ) - - - with open(archive, 'rb') as f: - data = f.read() - return data - -def offload( args ): - zfile = create_zipfile( args.path ) - send_zip( zfile ) - -def loop( sock ): - sock.settimeout(1e-2) - while True: - try: - d = sock.recv(10).strip() - if len(d) > 0: - print(d) - except socket.timeout as e: - print( '.', end='' ) - sys.stdout.flush() - -def read_msg(conn): - d = conn.recv(1024) - try: - d = d.decode('utf8').strip() - except Exception as e: - pass - return d - -def save_bz2(conn, outfile): - # first 6 bytes always tell how much to read next. Make sure the submit job - # script has it - d = conn.recv(10) - while len(d) < 10: - try: - d = conn.recv(10) - except Exception as e: - print( "[ERROR] Error in format. First 6 bytes are size of msg." ) - continue - - print( "Needs to get %s bytes" % d ) - data = conn.recv(int(d)) - with open(outfile, 'wb') as f: - f.write(data) - return data - -def main( args ): - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - try: - host, port = args.server.split(':') - sock.connect( (host, int(port)) ) - sock.settimeout(1) - except Exception as e: - print( "[ERROR] Failed to connect to %s... " % args.server ) - print( e ) - quit() - - data = gen_payload( args ) - print( "[INFO ] Total bytes to send: %d" % len(data), end = '') - write_data_to_socket(sock, data) - print( ' ... [SENT]' ) - while True: - try: - d = read_msg( sock ) - print( d ) - if '>DONE SIMULATION' in d: - break - except socket.timeout as e: - time.sleep(0.5) - - data = save_bz2(sock, 'results.tar.bz2' ) - print( "[INFO ] All done" ) - - -if __name__ == '__main__': - import argparse - # Argument parser. - description = '''Submit a job to moose server.''' - parser = argparse.ArgumentParser(description=description) - parser.add_argument('path', metavar='path' - , help = 'File or directory to execute on server.' - ) - parser.add_argument('--main', '-m', action = 'append' - , required = False, default = [] - , help = 'In case of multiple files, scripts to execute' - ' on the server, e.g. -m file1.py -m file2.py.' - ' If not given, server will try to guess the best option.' - ) - parser.add_argument('--server', '-s' - , required = False, type=str, default='localhost:31417' - , help = 'IP address and PORT number of moose server e.g.' - ' 172.16.1.2:31416' - ) - class Args: pass - args = Args() - parser.parse_args(namespace=args) - main(args) diff --git a/setup.py b/setup.py new file mode 100644 index 00000000..b973d53c --- /dev/null +++ b/setup.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +# This script can also be called directly to build and install the pymoose +# module. +# +# Alternatively, you can use cmake build system which provides finer control +# over the build. This script is called by cmake to install the python module. +# +# This script is compatible with python2.7 and python3+. Therefore use of +# super() is commented out. +# +# NOTES: +# * Python2 +# - Update setuptools using `python2 -m pip install setuptools --upgrade --user'. + +__author__ = "Dilawar Singh" + +__copyright__ = "Copyright 2019-, Dilawar Singh" +__maintainer__ = "Dilawar Singh" +__email__ = "dilawar.s.rajput@gmail.com" + +import os +import sys +import multiprocessing +import subprocess +import datetime + +try: + cmakeVersion = subprocess.call(["cmake", "--version"], + stdout=subprocess.PIPE) +except Exception as e: + print(e) + print("[ERROR] cmake is not found. Please install cmake.") + quit(-1) + +# See https://docs.python.org/3/library/distutils.html +# setuptools is preferred over distutils. And we are supporting python3 only. +from setuptools import setup, Extension, Command +from setuptools.command.build_ext import build_ext as _build_ext +import subprocess + +# Global variables. +sdir_ = os.path.dirname(os.path.realpath(__file__)) + +stamp = datetime.datetime.now().strftime('%Y%m%d') +builddir_ = os.path.join(sdir_, '_temp__build') + +if not os.path.exists(builddir_): + os.makedirs(builddir_) + +numCores_ = multiprocessing.cpu_count() + + +version_ = '3.2.1.dev%s' % stamp + +# importlib is available only for python3. Since we build wheels, prefer .so +# extension. This way a wheel built by any python3.x will work with any python3. + +class CMakeExtension(Extension): + def __init__(self, name, **kwargs): + # don't invoke the original build_ext for this special extension + import tempfile + # Create a temp file to create a dummy target. This build raises an + # exception because sources are empty. With python3 we can fix it by + # passing `optional=True` to the argument. With python2 there is no + # getaway from it. + f = tempfile.NamedTemporaryFile(suffix='.cpp', delete=False) + f.write(b'int main() { return 1; }') + Extension.__init__(self, name, sources=[f.name], **kwargs) + f.close() + +class TestCommand(Command): + user_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + print("[INFO ] Running tests... ") + os.chdir(builddir_) + self.spawn(["ctest", "--output-on-failure", '-j%d'%numCores_]) + os.chdir(sdir_) + +class build_ext(_build_ext): + user_options = [ + ('with-boost', None, 'Use Boost Libraries (OFF)') + , ('with-gsl', None, 'Use Gnu Scienfific Library (ON)') + , ('with-gsl-static', None, 'Use GNU Scientific Library (static library) (OFF)') + , ('debug', None, 'Build moose in debugging mode (OFF)') + , ('no-build', None, 'DO NOT BUILD. (for debugging/development)') + ] + _build_ext.user_options + + def initialize_options(self): + # Initialize options. + self.with_boost = 0 + self.with_gsl = 1 + self.with_gsl_static = 0 + self.debug = 0 + self.no_build = 0 + self.cmake_options = {} + # super().initialize_options() + _build_ext.initialize_options(self) + + def finalize_options(self): + # Finalize options. + # super().finalize_options() + _build_ext.finalize_options(self) + self.cmake_options['PYTHON_EXECUTABLE'] = os.path.realpath(sys.executable) + self.cmake_options['VERSION_MOOSE'] = version_ + if self.with_boost: + self.cmake_options['WITH_BOOST'] = 'ON' + self.cmake_options['WITH_GSL'] = 'OFF' + else: + if self.with_gsl_static: + self.cmake_options['GSL_USE_STATIC_LIBRARIES'] = 'ON' + if self.debug: + self.cmake_options['CMAKE_BUILD_TYPE'] = 'Debug' + else: + self.cmake_options['CMAKE_BUILD_TYPE'] = 'Release' + + def run(self): + if self.no_build: + return + for ext in self.extensions: + self.build_cmake(ext) + # super().run() + _build_ext.run(self) + + def build_cmake(self, ext): + global numCores_ + global sdir_ + print("\n==========================================================\n") + print("[INFO ] Building pymoose in %s ..." % builddir_) + cmake_args = [] + for k, v in self.cmake_options.items(): + cmake_args.append('-D%s=%s' % (k,v)) + os.chdir(str(builddir_)) + self.spawn(['cmake', str(sdir_)] + cmake_args) + if not self.dry_run: + self.spawn(['make', '-j%d'%numCores_]) + os.chdir(str(sdir_)) + +with open(os.path.join(sdir_, "README.md")) as f: + readme = f.read() + +setup( + name="pymoose", + version=version_, + description= 'Python scripting interface of MOOSE Simulator (https://moose.ncbs.res.in)', + long_description=readme, + long_description_content_type='text/markdown', + author='MOOSERes', + author_email='bhalla@ncbs.res.in', + maintainer='Dilawar Singh', + maintainer_email='dilawars@ncbs.res.in', + url='http://moose.ncbs.res.in', + packages=[ + 'rdesigneur', 'moose', 'moose.SBML', 'moose.genesis', 'moose.neuroml', + 'moose.neuroml2', 'moose.chemUtil', 'moose.chemMerge' + ], + package_dir={ + 'rdesigneur': os.path.join(sdir_, 'python', 'rdesigneur'), + 'moose': os.path.join(sdir_, 'python', 'moose') + }, + package_data={ + 'moose': [ + '_moose.so' + , os.path.join('neuroml2','schema','NeuroMLCoreDimensions.xml') + , os.path.join('chemUtil', 'rainbow2.pkl') + ] + }, + # python2 specific version here as well. + install_requires=['numpy', 'matplotlib'], + extra_requires={'dev' : [ 'coverage', 'pytest', 'pytest-cov' ]}, + ext_modules=[CMakeExtension('dummy', optional=True)], + cmdclass={'build_ext': build_ext, 'test': TestCommand}, +) diff --git a/shell/Neutral.cpp b/shell/Neutral.cpp index 314ece6c..4256ae21 100644 --- a/shell/Neutral.cpp +++ b/shell/Neutral.cpp @@ -15,266 +15,264 @@ const Cinfo* Neutral::initCinfo() { - ///////////////////////////////////////////////////////////////// - // Element Value Finfos - ///////////////////////////////////////////////////////////////// - - static ElementValueFinfo< Neutral, string > name( - "name", - "Name of object", - &Neutral::setName, - &Neutral::getName ); - - // Should be renamed to myId - static ReadOnlyElementValueFinfo< Neutral, ObjId > me( - "me", - "ObjId for current object", - &Neutral::getObjId ); - - static ReadOnlyElementValueFinfo< Neutral, ObjId > parent( - "parent", - "Parent ObjId for current object", - &Neutral::getParent ); - - static ReadOnlyElementValueFinfo< Neutral, vector< Id > > children( - "children", - "vector of ObjIds listing all children of current object", - &Neutral::getChildren ); - - static ReadOnlyElementValueFinfo< Neutral, string > path( - "path", - "text path for object", - &Neutral::getPath ); - - /* - */ - static ReadOnlyElementValueFinfo< Neutral, string > className( - "className", - "Class Name of object", - &Neutral::getClass ); - - static ElementValueFinfo< Neutral, unsigned int > numData( - "numData", - "# of Data entries on Element." - "Note that on a FieldElement this does NOT refer to field entries," - "but to the number of DataEntries on the parent of the " - "FieldElement.", - &Neutral::setNumData, - &Neutral::getNumData ); - - static ElementValueFinfo< Neutral, unsigned int > numField( - "numField", - "For a FieldElement: number of entries of self." - "For a regular Element: One.", - &Neutral::setNumField, - &Neutral::getNumField ); - - static ReadOnlyElementValueFinfo< Neutral, unsigned int > id( - "idValue", - "Object id of self, converted to an unsigned int.", - &Neutral::getId ); - - static ReadOnlyElementValueFinfo< Neutral, unsigned int > index( - "index", - "For a FieldElement: Object index of parent." - "For a regular Element: Object index (dataId) of self.", - &Neutral::getIndex ); - - static ReadOnlyElementValueFinfo< Neutral, unsigned int > fieldIndex( - "fieldIndex", - "For a FieldElement: field Index of self." - "For a regular Element: zero.", - &Neutral::getFieldIndex ); - - static ElementValueFinfo< Neutral, int > - tick( - "tick", - "Clock tick for this Element for periodic execution in the " - "main simulation event loop. A default is normally assigned, " - "based on object class, but one can override to any value " - "between 0 and 19. Assigning to -1 means that the object is " - "disabled and will not be called during simulation execution " - "The actual timestep (dt) belonging to a clock tick is defined " - "by the Clock object.", - &Neutral::setTick, - &Neutral::getTick ); - - static ReadOnlyElementValueFinfo< Neutral, double > - dt( - "dt", - "Timestep used for this Element. Zero if not scheduled.", - &Neutral::getDt ); - - - static ReadOnlyElementValueFinfo< Neutral, vector< string > > - valueFields( - "valueFields", - "List of all value fields on Element." - "These fields are accessed through the assignment operations " - "in the Python interface." - "These fields may also be accessed as functions through the " - "set and get commands.", - &Neutral::getValueFields - ); - - static ReadOnlyElementValueFinfo< Neutral, vector< string > > - sourceFields( - "sourceFields", - "List of all source fields on Element, that is fields that " - "can act as message sources. ", - &Neutral::getSourceFields - ); - - static ReadOnlyElementValueFinfo< Neutral, vector< string > > - destFields( - "destFields", - "List of all destination fields on Element, that is, fields" - "that are accessed as Element functions.", - &Neutral::getDestFields - ); - - static ReadOnlyElementValueFinfo< Neutral, vector< ObjId > > msgOut( - "msgOut", - "Messages going out from this Element", - &Neutral::getOutgoingMsgs ); - - static ReadOnlyElementValueFinfo< Neutral, vector< ObjId > > msgIn( - "msgIn", - "Messages coming in to this Element", - &Neutral::getIncomingMsgs ); - - static ReadOnlyLookupElementValueFinfo< Neutral, string, vector< Id > > neighbors( - "neighbors", - "Ids of Elements connected this Element on specified field.", - &Neutral::getNeighbors ); - - static ReadOnlyLookupElementValueFinfo< Neutral, string, vector< ObjId > > msgDests( - "msgDests", - "ObjIds receiving messages from the specified SrcFinfo", - &Neutral::getMsgDests ); - - static ReadOnlyLookupElementValueFinfo< Neutral, string, vector< string > > msgDestFunctions( - "msgDestFunctions", - "Matching function names for each ObjId receiving a msg from " - "the specified SrcFinfo", - &Neutral::getMsgDestFunctions ); - - static ReadOnlyLookupElementValueFinfo< Neutral, string, bool >isA( - "isA", - "Returns true if the current object is derived from the specified " - "the specified class", - &Neutral::isA ); - - ///////////////////////////////////////////////////////////////// - // Value Finfos - ///////////////////////////////////////////////////////////////// - static ValueFinfo< Neutral, Neutral > thisFinfo ( - "this", - "Access function for entire object", - &Neutral::setThis, - &Neutral::getThis - ); - ///////////////////////////////////////////////////////////////// - // SrcFinfos - ///////////////////////////////////////////////////////////////// - static SrcFinfo1< int > childOut( "childOut", - "Message to child Elements"); - - ///////////////////////////////////////////////////////////////// - // DestFinfos - ///////////////////////////////////////////////////////////////// - static DestFinfo parentMsg( "parentMsg", - "Message from Parent Element(s)", - new EpFunc1< Neutral, int >( &Neutral::destroy ) ); - - static DestFinfo blockNodeBalance( "blockNodeBalance", - "Request conversion of data into a blockDataHandler subclass," - "and to carry out node balancing of data." - "The amount of data is not altered, and if the data is already a" - "blockDataHandler subclass it retains its original dimensions" - "If converting from a generalDataHandler to blockHandler it treats" - "it as a linear array" - "The function preserves the old data and shuffles info around" - "between nodes to complete the balancing." - "Arguments are: myNode, startNode, endNode", - new EpFunc3< Neutral, unsigned int, unsigned int, unsigned int >( - &Neutral::blockNodeBalance ) ); - - static DestFinfo generalNodeBalance( "generalNodeBalance", - "Request conversion of data into a generalDataHandler subclass," - "and to carry out node balancing of data as per specified args." - "The amount of data is not altered. The generalDataHandler loses" - "any dimensional information that may have been present in an " - "earlier blockDataHandler incarnation." - "Arguments are: myNode, nodeAssignment", - new EpFunc2< Neutral, unsigned int, vector< unsigned int > >( - &Neutral::generalNodeBalance ) ); - - ///////////////////////////////////////////////////////////////// - // Setting up the Finfo list. - ///////////////////////////////////////////////////////////////// - static Finfo* neutralFinfos[] = { - &childOut, // SrcFinfo - &parentMsg, // DestFinfo - &thisFinfo, // Value - &name, // Value - &me, // ReadOnlyValue - &parent, // ReadOnlyValue - &children, // ReadOnlyValue - &path, // ReadOnlyValue - &className, // ReadOnlyValue - &numData, // Value - &numField, // Value - &id, // ReadOnlyValue - &index, // ReadOnlyValue - &fieldIndex, // ReadOnlyValue - &tick, // Value - &dt, // ReadOnlyValue - &valueFields, // ReadOnlyValue - &sourceFields, // ReadOnlyValue - &destFields, // ReadOnlyValue - &msgOut, // ReadOnlyValue - &msgIn, // ReadOnlyValue - &neighbors, // ReadOnlyLookupValue - &msgDests, // ReadOnlyLookupValue - &msgDestFunctions, // ReadOnlyLookupValue - &isA, // ReadOnlyLookupValue - }; - - ///////////////////////////////////////////////////////////////// - // Setting up the Cinfo. - ///////////////////////////////////////////////////////////////// - - static string doc[] = - { - "Name", "Neutral", - "Author", "Upinder S. Bhalla, 2007, NCBS", - "Description", "Neutral: Base class for all MOOSE classes. Provides" - "access functions for housekeeping fields and operations, message" - "traversal, and so on." - }; - static Dinfo< Neutral > dinfo; - static Cinfo neutralCinfo ( - "Neutral", - 0, // No base class. - neutralFinfos, - sizeof( neutralFinfos ) / sizeof( Finfo* ), - &dinfo, - doc, - sizeof(doc)/sizeof(string) - ); - - return &neutralCinfo; + ///////////////////////////////////////////////////////////////// + // Element Value Finfos + ///////////////////////////////////////////////////////////////// + + static ElementValueFinfo< Neutral, string > name( + "name", + "Name of object", + &Neutral::setName, + &Neutral::getName ); + + // Should be renamed to myId + static ReadOnlyElementValueFinfo< Neutral, ObjId > me( + "me", + "ObjId for current object", + &Neutral::getObjId ); + + static ReadOnlyElementValueFinfo< Neutral, ObjId > parent( + "parent", + "Parent ObjId for current object", + &Neutral::getParent ); + + static ReadOnlyElementValueFinfo< Neutral, vector< Id > > children( + "children", + "vector of ObjIds listing all children of current object", + &Neutral::getChildren ); + + static ReadOnlyElementValueFinfo< Neutral, string > path( + "path", + "text path for object", + &Neutral::getPath ); + + /* + */ + static ReadOnlyElementValueFinfo< Neutral, string > className( + "className", + "Class Name of object", + &Neutral::getClass ); + + static ElementValueFinfo< Neutral, unsigned int > numData( + "numData", + "# of Data entries on Element." + "Note that on a FieldElement this does NOT refer to field entries," + "but to the number of DataEntries on the parent of the " + "FieldElement.", + &Neutral::setNumData, + &Neutral::getNumData ); + + static ElementValueFinfo< Neutral, unsigned int > numField( + "numField", + "For a FieldElement: number of entries of self." + "For a regular Element: One.", + &Neutral::setNumField, + &Neutral::getNumField ); + + static ReadOnlyElementValueFinfo< Neutral, unsigned int > id( + "idValue", + "Object id of self, converted to an unsigned int.", + &Neutral::getId ); + + static ReadOnlyElementValueFinfo< Neutral, unsigned int > index( + "index", + "For a FieldElement: Object index of parent." + "For a regular Element: Object index (dataId) of self.", + &Neutral::getIndex ); + + static ReadOnlyElementValueFinfo< Neutral, unsigned int > fieldIndex( + "fieldIndex", + "For a FieldElement: field Index of self." + "For a regular Element: zero.", + &Neutral::getFieldIndex ); + + static ElementValueFinfo< Neutral, int > + tick( + "tick", + "Clock tick for this Element for periodic execution in the " + "main simulation event loop. A default is normally assigned, " + "based on object class, but one can override to any value " + "between 0 and 19. Assigning to -1 means that the object is " + "disabled and will not be called during simulation execution " + "The actual timestep (dt) belonging to a clock tick is defined " + "by the Clock object.", + &Neutral::setTick, + &Neutral::getTick ); + + static ReadOnlyElementValueFinfo< Neutral, double > + dt( + "dt", + "Timestep used for this Element. Zero if not scheduled.", + &Neutral::getDt ); + + + static ReadOnlyElementValueFinfo< Neutral, vector< string > > + valueFields( + "valueFields", + "List of all value fields on Element." + "These fields are accessed through the assignment operations " + "in the Python interface." + "These fields may also be accessed as functions through the " + "set and get commands.", + &Neutral::getValueFields + ); + + static ReadOnlyElementValueFinfo< Neutral, vector< string > > + sourceFields( + "sourceFields", + "List of all source fields on Element, that is fields that " + "can act as message sources. ", + &Neutral::getSourceFields + ); + + static ReadOnlyElementValueFinfo< Neutral, vector< string > > + destFields( + "destFields", + "List of all destination fields on Element, that is, fields" + "that are accessed as Element functions.", + &Neutral::getDestFields + ); + + static ReadOnlyElementValueFinfo< Neutral, vector< ObjId > > msgOut( + "msgOut", + "Messages going out from this Element", + &Neutral::getOutgoingMsgs ); + + static ReadOnlyElementValueFinfo< Neutral, vector< ObjId > > msgIn( + "msgIn", + "Messages coming in to this Element", + &Neutral::getIncomingMsgs ); + + static ReadOnlyLookupElementValueFinfo< Neutral, string, vector< Id > > neighbors( + "neighbors", + "Ids of Elements connected this Element on specified field.", + &Neutral::getNeighbors ); + + static ReadOnlyLookupElementValueFinfo< Neutral, string, vector< ObjId > > msgDests( + "msgDests", + "ObjIds receiving messages from the specified SrcFinfo", + &Neutral::getMsgDests ); + + static ReadOnlyLookupElementValueFinfo< Neutral, string, vector< string > > msgDestFunctions( + "msgDestFunctions", + "Matching function names for each ObjId receiving a msg from " + "the specified SrcFinfo", + &Neutral::getMsgDestFunctions ); + + static ReadOnlyLookupElementValueFinfo< Neutral, string, bool >isA( + "isA", + "Returns true if the current object is derived from the specified " + "the specified class", + &Neutral::isA ); + + ///////////////////////////////////////////////////////////////// + // Value Finfos + ///////////////////////////////////////////////////////////////// + static ValueFinfo< Neutral, Neutral > thisFinfo ( + "this", + "Access function for entire object", + &Neutral::setThis, + &Neutral::getThis + ); + ///////////////////////////////////////////////////////////////// + // SrcFinfos + ///////////////////////////////////////////////////////////////// + static SrcFinfo1< int > childOut( "childOut", + "Message to child Elements"); + + ///////////////////////////////////////////////////////////////// + // DestFinfos + ///////////////////////////////////////////////////////////////// + static DestFinfo parentMsg( "parentMsg", + "Message from Parent Element(s)", + new EpFunc1< Neutral, int >( &Neutral::destroy ) ); + + static DestFinfo blockNodeBalance( "blockNodeBalance", + "Request conversion of data into a blockDataHandler subclass," + "and to carry out node balancing of data." + "The amount of data is not altered, and if the data is already a" + "blockDataHandler subclass it retains its original dimensions" + "If converting from a generalDataHandler to blockHandler it treats" + "it as a linear array" + "The function preserves the old data and shuffles info around" + "between nodes to complete the balancing." + "Arguments are: myNode, startNode, endNode", + new EpFunc3< Neutral, unsigned int, unsigned int, unsigned int >( + &Neutral::blockNodeBalance ) ); + + static DestFinfo generalNodeBalance( "generalNodeBalance", + "Request conversion of data into a generalDataHandler subclass," + "and to carry out node balancing of data as per specified args." + "The amount of data is not altered. The generalDataHandler loses" + "any dimensional information that may have been present in an " + "earlier blockDataHandler incarnation." + "Arguments are: myNode, nodeAssignment", + new EpFunc2< Neutral, unsigned int, vector< unsigned int > >( + &Neutral::generalNodeBalance ) ); + + ///////////////////////////////////////////////////////////////// + // Setting up the Finfo list. + ///////////////////////////////////////////////////////////////// + static Finfo* neutralFinfos[] = + { + &childOut, // SrcFinfo + &parentMsg, // DestFinfo + &thisFinfo, // Value + &name, // Value + &me, // ReadOnlyValue + &parent, // ReadOnlyValue + &children, // ReadOnlyValue + &path, // ReadOnlyValue + &className, // ReadOnlyValue + &numData, // Value + &numField, // Value + &id, // ReadOnlyValue + &index, // ReadOnlyValue + &fieldIndex, // ReadOnlyValue + &tick, // Value + &dt, // ReadOnlyValue + &valueFields, // ReadOnlyValue + &sourceFields, // ReadOnlyValue + &destFields, // ReadOnlyValue + &msgOut, // ReadOnlyValue + &msgIn, // ReadOnlyValue + &neighbors, // ReadOnlyLookupValue + &msgDests, // ReadOnlyLookupValue + &msgDestFunctions, // ReadOnlyLookupValue + &isA, // ReadOnlyLookupValue + }; + + ///////////////////////////////////////////////////////////////// + // Setting up the Cinfo. + ///////////////////////////////////////////////////////////////// + + static string doc[] = + { + "Name", "Neutral", + "Author", "Upinder S. Bhalla, 2007, NCBS", + "Description", "Neutral: Base class for all MOOSE classes. Provides" + "access functions for housekeeping fields and operations, message" + "traversal, and so on." + }; + static Dinfo< Neutral > dinfo; + static Cinfo neutralCinfo ( + "Neutral", + 0, // No base class. + neutralFinfos, + sizeof( neutralFinfos ) / sizeof( Finfo* ), + &dinfo, + doc, + sizeof(doc)/sizeof(string) + ); + + return &neutralCinfo; } static const Cinfo* neutralCinfo = Neutral::initCinfo(); Neutral::Neutral() - // : name_( "" ) -{ - ; -} +{ ; } //////////////////////////////////////////////////////////////////////// // Access functions @@ -283,49 +281,54 @@ Neutral::Neutral() void Neutral::setThis( Neutral v ) { - ; + ; } Neutral Neutral::getThis() const { - return *this; + return *this; } void Neutral::setName( const Eref& e, string name ) { - if ( e.id().value() <= 3 ) { - cout << "Warning: Neutral::setName on '" << e.id().path() << - "'. Cannot rename core objects\n"; - return; - } - if ( !Shell::isNameValid( name ) ) { - cout << "Warning: Neutral::setName on '" << e.id().path() << - "'. Illegal character in name.\n"; - return; - } - ObjId pa = parent( e ); - Id sibling = Neutral::child( pa.eref(), name ); - if ( sibling == Id() ) { // OK, no existing object with same name. - e.element()->setName( name ); - } else { - cout << "Warning: Neutral::setName: an object with the name '" << - name << "'\n already exists on the same parent. Not changed\n"; - } + if ( e.id().value() <= 3 ) + { + cout << "Warning: Neutral::setName on '" << e.id().path() << + "'. Cannot rename core objects\n"; + return; + } + if ( !Shell::isNameValid( name ) ) + { + cout << "Warning: Neutral::setName on '" << e.id().path() << + "'. Illegal character in name.\n"; + return; + } + ObjId pa = parent( e ); + Id sibling = Neutral::child( pa.eref(), name ); + if ( sibling == Id() ) // OK, no existing object with same name. + { + e.element()->setName( name ); + } + else + { + cout << "Warning: Neutral::setName: an object with the name '" << + name << "'\n already exists on the same parent. Not changed\n"; + } } string Neutral::getName( const Eref& e ) const { - return e.element()->getName(); + return e.element()->getName(); } ObjId Neutral::getObjId( const Eref& e ) const { - return e.objId(); + return e.objId(); } ObjId Neutral::getParent( const Eref& e ) const { - return parent( e ); + return parent( e ); } /** @@ -333,265 +336,284 @@ ObjId Neutral::getParent( const Eref& e ) const */ vector< Id > Neutral::getChildren( const Eref& e ) const { - vector< Id > ret; - children( e, ret ); - return ret; + vector< Id > ret; + children( e, ret ); + return ret; } // Static function void Neutral::children( const Eref& e, vector< Id >& ret ) { - /* - vector< Id > temp; - getNeighbors( ret, neutralCinfo->findFinfo( "childOut" ) ); - for ( vector< Id >::iterator i = temp.begin(); i != temp.end(); ++i ) { - if ( ret - } - */ - - - - static const Finfo* pf = neutralCinfo->findFinfo( "parentMsg" ); - static const DestFinfo* pf2 = dynamic_cast< const DestFinfo* >( pf ); - static const FuncId pafid = pf2->getFid(); - static const Finfo* cf = neutralCinfo->findFinfo( "childOut" ); - static const SrcFinfo* cf2 = dynamic_cast< const SrcFinfo* >( cf ); - static const BindIndex bi = cf2->getBindIndex(); - - const vector< MsgFuncBinding >* bvec = e.element()->getMsgAndFunc( bi ); - - for ( vector< MsgFuncBinding >::const_iterator i = bvec->begin(); - i != bvec->end(); ++i ) { - if ( i->fid == pafid ) { - const Msg* m = Msg::getMsg( i->mid ); - assert( m ); - vector< vector< Eref > > kids; - m->targets( kids ); - if ( e.dataIndex() == ALLDATA ) { - for ( vector< vector< Eref > >::iterator - i = kids.begin(); i != kids.end(); ++i ) { - for ( vector< Eref >::iterator - j = i->begin(); j != i->end(); ++j ) - ret.push_back( j->id() ); - } - } else { - const vector< Eref >& temp = kids[e.dataIndex()]; - for ( vector< Eref >::const_iterator - i = temp.begin(); i != temp.end(); ++i ) - ret.push_back( i->id() ); - } - } - } + /* + vector< Id > temp; + getNeighbors( ret, neutralCinfo->findFinfo( "childOut" ) ); + for ( vector< Id >::iterator i = temp.begin(); i != temp.end(); ++i ) { + if ( ret + } + */ + + + + static const Finfo* pf = neutralCinfo->findFinfo( "parentMsg" ); + static const DestFinfo* pf2 = dynamic_cast< const DestFinfo* >( pf ); + static const FuncId pafid = pf2->getFid(); + static const Finfo* cf = neutralCinfo->findFinfo( "childOut" ); + static const SrcFinfo* cf2 = dynamic_cast< const SrcFinfo* >( cf ); + static const BindIndex bi = cf2->getBindIndex(); + + const vector< MsgFuncBinding >* bvec = e.element()->getMsgAndFunc( bi ); + + for ( vector< MsgFuncBinding >::const_iterator i = bvec->begin(); + i != bvec->end(); ++i ) + { + if ( i->fid == pafid ) + { + const Msg* m = Msg::getMsg( i->mid ); + assert( m ); + vector< vector< Eref > > kids; + m->targets( kids ); + if ( e.dataIndex() == ALLDATA ) + { + for ( vector< vector< Eref > >::iterator + i = kids.begin(); i != kids.end(); ++i ) + { + for ( vector< Eref >::iterator + j = i->begin(); j != i->end(); ++j ) + ret.push_back( j->id() ); + } + } + else + { + const vector< Eref >& temp = kids[e.dataIndex()]; + for ( vector< Eref >::const_iterator + i = temp.begin(); i != temp.end(); ++i ) + ret.push_back( i->id() ); + } + } + } } string Neutral::getPath( const Eref& e ) const { - return path( e ); + return path( e ); } string Neutral::getClass( const Eref& e ) const { - return e.element()->cinfo()->name(); + return e.element()->cinfo()->name(); } unsigned int Neutral::getNumData( const Eref& e ) const { - return e.element()->numData(); + return e.element()->numData(); } void Neutral::setNumData( const Eref& e, unsigned int num ) { - e.element()->resize( num ); + e.element()->resize( num ); } unsigned int Neutral::getNumField( const Eref& e ) const { - assert( e.isDataHere() ); - unsigned int rawIndex = e.element()->rawIndex( e.dataIndex() ); - return e.element()->numField( rawIndex ); + assert( e.isDataHere() ); + unsigned int rawIndex = e.element()->rawIndex( e.dataIndex() ); + return e.element()->numField( rawIndex ); } void Neutral::setNumField( const Eref& e, unsigned int num ) { - assert( e.isDataHere() ); - unsigned int rawIndex = e.element()->rawIndex( e.dataIndex() ); - e.element()->resizeField( rawIndex, num ); + assert( e.isDataHere() ); + unsigned int rawIndex = e.element()->rawIndex( e.dataIndex() ); + e.element()->resizeField( rawIndex, num ); } unsigned int Neutral::getId( const Eref& e ) const { - return e.id().value(); + return e.id().value(); } unsigned int Neutral::getIndex( const Eref& e ) const { - return e.dataIndex(); + return e.dataIndex(); } unsigned int Neutral::getFieldIndex( const Eref& e ) const { - return e.fieldIndex(); + return e.fieldIndex(); } int Neutral::getTick( const Eref& e ) const { - return e.element()->getTick(); + return e.element()->getTick(); } void Neutral::setTick( const Eref& e, int num ) { - e.element()->setTick( num ); + e.element()->setTick( num ); } double Neutral::getDt( const Eref& e ) const { - int tick = e.element()->getTick(); - if ( tick < 0 ) - return 0.0; - Id clockId( 1 ); - return LookupField< unsigned int, double >::get( - clockId, "tickDt", tick ); + int tick = e.element()->getTick(); + if ( tick < 0 ) + return 0.0; + Id clockId( 1 ); + return LookupField< unsigned int, double >::get( + clockId, "tickDt", tick ); } vector< string > Neutral::getValueFields( const Eref& e ) const { - unsigned int num = e.element()->cinfo()->getNumValueFinfo(); - vector< string > ret( num ); - for ( unsigned int i = 0; i < num; ++i ) { - const Finfo *f = e.element()->cinfo()->getValueFinfo( i ); - assert( f ); - ret[i] = f->name(); - } - return ret; + unsigned int num = e.element()->cinfo()->getNumValueFinfo(); + vector< string > ret( num ); + for ( unsigned int i = 0; i < num; ++i ) + { + const Finfo *f = e.element()->cinfo()->getValueFinfo( i ); + assert( f ); + ret[i] = f->name(); + } + return ret; } vector< string > Neutral::getSourceFields( const Eref& e ) const { - unsigned int num = e.element()->cinfo()->getNumSrcFinfo(); - vector< string > ret( num ); - for ( unsigned int i = 0; i < num; ++i ) { - const Finfo *f = e.element()->cinfo()->getSrcFinfo( i ); - assert( f ); - ret[i] = f->name(); - } - return ret; + unsigned int num = e.element()->cinfo()->getNumSrcFinfo(); + vector< string > ret( num ); + for ( unsigned int i = 0; i < num; ++i ) + { + const Finfo *f = e.element()->cinfo()->getSrcFinfo( i ); + assert( f ); + ret[i] = f->name(); + } + return ret; } vector< string > Neutral::getDestFields( const Eref& e ) const { - unsigned int num = e.element()->cinfo()->getNumDestFinfo(); - vector< string > ret( num ); - for ( unsigned int i = 0; i < num; ++i ) { - const Finfo *f = e.element()->cinfo()->getDestFinfo( i ); - assert( f ); - ret[i] = f->name(); - } - return ret; + unsigned int num = e.element()->cinfo()->getNumDestFinfo(); + vector< string > ret( num ); + for ( unsigned int i = 0; i < num; ++i ) + { + const Finfo *f = e.element()->cinfo()->getDestFinfo( i ); + assert( f ); + ret[i] = f->name(); + } + return ret; } vector< ObjId > Neutral::getOutgoingMsgs( const Eref& e ) const { - vector< ObjId > ret; - unsigned int numBindIndex = e.element()->cinfo()->numBindIndex(); - - for ( unsigned int i = 0; i < numBindIndex; ++i ) { - const vector< MsgFuncBinding >* v = - e.element()->getMsgAndFunc( i ); - if ( v ) { - for ( vector< MsgFuncBinding >::const_iterator mb = v->begin(); - mb != v->end(); ++mb ) { - ret.push_back( mb->mid ); - } - } - } - return ret; + vector< ObjId > ret; + unsigned int numBindIndex = e.element()->cinfo()->numBindIndex(); + + for ( unsigned int i = 0; i < numBindIndex; ++i ) + { + const vector< MsgFuncBinding >* v = + e.element()->getMsgAndFunc( i ); + if ( v ) + { + for ( vector< MsgFuncBinding >::const_iterator mb = v->begin(); + mb != v->end(); ++mb ) + { + ret.push_back( mb->mid ); + } + } + } + return ret; } vector< ObjId > Neutral::getIncomingMsgs( const Eref& e ) const { - vector< ObjId > ret; - const vector< ObjId >& msgIn = e.element()->msgIn(); + vector< ObjId > ret; + const vector< ObjId >& msgIn = e.element()->msgIn(); - for (unsigned int i = 0; i < msgIn.size(); ++i ) { - const Msg* m = Msg::getMsg( msgIn[i] ); - assert( m ); - if ( m->e2() == e.element() ) - ret.push_back( m->mid() ); - } - return ret; + for (unsigned int i = 0; i < msgIn.size(); ++i ) + { + const Msg* m = Msg::getMsg( msgIn[i] ); + assert( m ); + if ( m->e2() == e.element() ) + ret.push_back( m->mid() ); + } + return ret; } vector< Id > Neutral::getNeighbors( const Eref& e, string field ) const { - vector< Id > ret; - const Finfo* finfo = e.element()->cinfo()->findFinfo( field ); - if ( finfo ) - e.element()->getNeighbors( ret, finfo ); - else - cout << "Warning: Neutral::getNeighbors: Id.Field '" << - e.id().path() << "." << field << - "' not found\n"; - return ret; + vector< Id > ret; + const Finfo* finfo = e.element()->cinfo()->findFinfo( field ); + if ( finfo ) + e.element()->getNeighbors( ret, finfo ); + else + cout << "Warning: Neutral::getNeighbors: Id.Field '" << + e.id().path() << "." << field << + "' not found\n"; + return ret; } vector< ObjId > Neutral::getMsgDests( const Eref& e, string field ) const { - const Finfo* finfo = e.element()->cinfo()->findFinfo( field ); - const SrcFinfo* sf = dynamic_cast< const SrcFinfo* >( finfo ); - if ( sf ) { - vector< ObjId > tgt; - vector< string > func; - e.element()->getMsgTargetAndFunctions( e.dataIndex(), sf, - tgt, func ); - return tgt; - } else { - cout << "Warning: Neutral::getMsgDests: Id.Field '" << - e.id().path() << "." << field << - "' not found or not a SrcFinfo\n"; - } - static vector< ObjId > ret( 0 ); - return ret; + const Finfo* finfo = e.element()->cinfo()->findFinfo( field ); + const SrcFinfo* sf = dynamic_cast< const SrcFinfo* >( finfo ); + if ( sf ) + { + vector< ObjId > tgt; + vector< string > func; + e.element()->getMsgTargetAndFunctions( e.dataIndex(), sf, + tgt, func ); + return tgt; + } + else + { + cout << "Warning: Neutral::getMsgDests: Id.Field '" << + e.id().path() << "." << field << + "' not found or not a SrcFinfo\n"; + } + static vector< ObjId > ret( 0 ); + return ret; } vector< string > Neutral::getMsgDestFunctions( const Eref& e, string field ) const { - vector< string > ret( 0 ); - const Finfo* finfo = e.element()->cinfo()->findFinfo( field ); - const SrcFinfo* sf = dynamic_cast< const SrcFinfo* >( finfo ); - if ( sf ) { - vector< ObjId > tgt; - vector< string > func; - e.element()->getMsgTargetAndFunctions( e.dataIndex(), sf, - tgt, func ); - return func; - } else { - cout << "Warning: Neutral::getMsgDestFunctions: Id.Field '" << - e.id().path() << "." << field << - "' not found or not a SrcFinfo\n"; - } - return ret; + vector< string > ret( 0 ); + const Finfo* finfo = e.element()->cinfo()->findFinfo( field ); + const SrcFinfo* sf = dynamic_cast< const SrcFinfo* >( finfo ); + if ( sf ) + { + vector< ObjId > tgt; + vector< string > func; + e.element()->getMsgTargetAndFunctions( e.dataIndex(), sf, + tgt, func ); + return func; + } + else + { + cout << "Warning: Neutral::getMsgDestFunctions: Id.Field '" << + e.id().path() << "." << field << + "' not found or not a SrcFinfo\n"; + } + return ret; } bool Neutral::isA( const Eref& e, string className ) const { - return e.element()->cinfo()->isA( className ); + return e.element()->cinfo()->isA( className ); } ////////////////////////////////////////////////////////////////////////// unsigned int Neutral::buildTree( const Eref& e, vector< Id >& tree ) - const -{ - unsigned int ret = 1; - Eref er( e.element(), ALLDATA ); - vector< Id > kids = getChildren( er ); - sort( kids.begin(), kids.end() ); - kids.erase( unique( kids.begin(), kids.end() ), kids.end() ); - for ( vector< Id >::iterator i = kids.begin(); i != kids.end(); ++i ) - ret += buildTree( i->eref(), tree ); - tree.push_back( e.element()->id() ); - return ret; +const +{ + unsigned int ret = 1; + Eref er( e.element(), ALLDATA ); + vector< Id > kids = getChildren( er ); + sort( kids.begin(), kids.end() ); + kids.erase( unique( kids.begin(), kids.end() ), kids.end() ); + for ( vector< Id >::iterator i = kids.begin(); i != kids.end(); ++i ) + ret += buildTree( i->eref(), tree ); + tree.push_back( e.element()->id() ); + return ret; } ////////////////////////////////////////////////////////////////////////// // Dest Functions @@ -604,20 +626,21 @@ unsigned int Neutral::buildTree( const Eref& e, vector< Id >& tree ) // Stage 3: delete self and attached msgs, void Neutral::destroy( const Eref& e, int stage ) { - if ( e.element()->cinfo()->isA( "Msg" ) ) { - Msg::deleteMsg( e.objId() ); - return; - } - vector< Id > tree; - Eref er( e.element(), ALLDATA ); - unsigned int numDescendants = buildTree( er, tree ); - /* - cout << "Neutral::destroy: id = " << e.id() << - ", name = " << e.element()->getName() << - ", numDescendants = " << numDescendants << endl; - */ - assert( numDescendants == tree.size() ); - Element::destroyElementTree( tree ); + if ( e.element()->cinfo()->isA( "Msg" ) ) + { + Msg::deleteMsg( e.objId() ); + return; + } + vector< Id > tree; + Eref er( e.element(), ALLDATA ); + unsigned int numDescendants = buildTree( er, tree ); + /* + cout << "Neutral::destroy: id = " << e.id() << + ", name = " << e.element()->getName() << + ", numDescendants = " << numDescendants << endl; + */ + assert( numDescendants == tree.size() ); + Element::destroyElementTree( tree ); } /** @@ -625,7 +648,7 @@ void Neutral::destroy( const Eref& e, int stage ) * and to carry out node balancing of data as per args. */ void Neutral::blockNodeBalance( const Eref& e, - unsigned int, unsigned int, unsigned int ) + unsigned int, unsigned int, unsigned int ) { } @@ -634,7 +657,7 @@ void Neutral::blockNodeBalance( const Eref& e, * and to carry out node balancing of data as per args. */ void Neutral::generalNodeBalance( const Eref& e, - unsigned int myNode, vector< unsigned int > nodeAssignment ) + unsigned int myNode, vector< unsigned int > nodeAssignment ) { } @@ -646,150 +669,163 @@ void Neutral::generalNodeBalance( const Eref& e, // static function bool Neutral::isDescendant( Id me, Id ancestor ) { - static const Finfo* pf = neutralCinfo->findFinfo( "parentMsg" ); - static const DestFinfo* pf2 = dynamic_cast< const DestFinfo* >( pf ); - static const FuncId pafid = pf2->getFid(); + static const Finfo* pf = neutralCinfo->findFinfo( "parentMsg" ); + static const DestFinfo* pf2 = dynamic_cast< const DestFinfo* >( pf ); + static const FuncId pafid = pf2->getFid(); - Eref e = me.eref(); + Eref e = me.eref(); - while ( e.element()->id() != Id() && e.element()->id() != ancestor ) { - ObjId mid = e.element()->findCaller( pafid ); - assert( mid != ObjId() ); - ObjId fid = Msg::getMsg( mid )->findOtherEnd( e.objId() ); - e = fid.eref(); - } - return ( e.element()->id() == ancestor ); + while ( e.element()->id() != Id() && e.element()->id() != ancestor ) + { + ObjId mid = e.element()->findCaller( pafid ); + assert( mid != ObjId() ); + ObjId fid = Msg::getMsg( mid )->findOtherEnd( e.objId() ); + e = fid.eref(); + } + return ( e.element()->id() == ancestor ); } // static function Id Neutral::child( const Eref& e, const string& name ) { - static const Finfo* pf = neutralCinfo->findFinfo( "parentMsg" ); - static const DestFinfo* pf2 = dynamic_cast< const DestFinfo* >( pf ); - static const FuncId pafid = pf2->getFid(); - static const Finfo* cf = neutralCinfo->findFinfo( "childOut" ); - static const SrcFinfo* cf2 = dynamic_cast< const SrcFinfo* >( cf ); - static const BindIndex bi = cf2->getBindIndex(); - - const vector< MsgFuncBinding >* bvec = e.element()->getMsgAndFunc( bi ); - - vector< Id > ret; - - for ( vector< MsgFuncBinding >::const_iterator i = bvec->begin(); - i != bvec->end(); ++i ) { - if ( i->fid == pafid ) { - const Msg* m = Msg::getMsg( i->mid ); - assert( m ); - Element* e2 = m->e2(); - if ( e2->getName() == name ) { - if ( e.dataIndex() == ALLDATA ) {// Child of any index is OK - return e2->id(); - } else { - ObjId parent = m->findOtherEnd( m->getE2() ); - // If child is a fieldElement, then all parent indices - // are permitted. Otherwise insist parent dataIndex OK. - if ( e2->hasFields() || parent == e.objId() ) - return e2->id(); - } - } - } - } - return Id(); + static const Finfo* pf = neutralCinfo->findFinfo( "parentMsg" ); + static const DestFinfo* pf2 = dynamic_cast< const DestFinfo* >( pf ); + static const FuncId pafid = pf2->getFid(); + static const Finfo* cf = neutralCinfo->findFinfo( "childOut" ); + static const SrcFinfo* cf2 = dynamic_cast< const SrcFinfo* >( cf ); + static const BindIndex bi = cf2->getBindIndex(); + + const vector< MsgFuncBinding >* bvec = e.element()->getMsgAndFunc( bi ); + + vector< Id > ret; + + for ( vector< MsgFuncBinding >::const_iterator i = bvec->begin(); + i != bvec->end(); ++i ) + { + if ( i->fid == pafid ) + { + const Msg* m = Msg::getMsg( i->mid ); + assert( m ); + Element* e2 = m->e2(); + if ( e2->getName() == name ) + { + if ( e.dataIndex() == ALLDATA ) // Child of any index is OK + { + return e2->id(); + } + else + { + ObjId parent = m->findOtherEnd( m->getE2() ); + // If child is a fieldElement, then all parent indices + // are permitted. Otherwise insist parent dataIndex OK. + if ( e2->hasFields() || parent == e.objId() ) + return e2->id(); + } + } + } + } + return Id(); } // Static function. ObjId Neutral::parent( const Eref& e ) { - return Neutral::parent( e.objId() ); + return Neutral::parent( e.objId() ); } ObjId Neutral::parent( ObjId oid ) { - static const Finfo* pf = neutralCinfo->findFinfo( "parentMsg" ); - static const DestFinfo* pf2 = dynamic_cast< const DestFinfo* >( pf ); - static const FuncId pafid = pf2->getFid(); + static const Finfo* pf = neutralCinfo->findFinfo( "parentMsg" ); + static const DestFinfo* pf2 = dynamic_cast< const DestFinfo* >( pf ); + static const FuncId pafid = pf2->getFid(); - if ( oid.id == Id() ) { - cout << "Warning: Neutral::parent: tried to take parent of root\n"; - return Id(); - } + if ( oid.id == Id() ) + { + cout << "Warning: Neutral::parent: tried to take parent of root\n"; + return Id(); + } - ObjId mid = oid.element()->findCaller( pafid ); - assert( mid != ObjId() ); + ObjId mid = oid.element()->findCaller( pafid ); + assert( mid != ObjId() ); - ObjId pa = Msg::getMsg( mid )->findOtherEnd( oid ); - return pa; + ObjId pa = Msg::getMsg( mid )->findOtherEnd( oid ); + return pa; } // Static function string Neutral::path( const Eref& e ) { - static const Finfo* pf = neutralCinfo->findFinfo( "parentMsg" ); - static const DestFinfo* pf2 = dynamic_cast< const DestFinfo* >( pf ); - static const FuncId pafid = pf2->getFid(); - - vector< ObjId > pathVec; - ObjId curr = e.objId(); - stringstream ss; - - pathVec.push_back( curr ); - while ( curr.id != Id() ) { - ObjId mid = curr.eref().element()->findCaller( pafid ); - if ( mid == ObjId() ) { - cout << "Error: Neutral::path:Cannot follow msg of ObjId: " << - e.objId() << " for func: " << pafid << endl; - break; - } - curr = Msg::getMsg( mid )->findOtherEnd( curr ); - pathVec.push_back( curr ); - } - if ( pathVec.size() <= 1 ) - return "/"; - for ( unsigned int i = 1; i < pathVec.size(); ++i ) { - ss << "/"; - ObjId& oid = pathVec[ pathVec.size() - i - 1 ]; - ss << oid.element()->getName(); - if ( !oid.element()->hasFields() ) - ss << "[" << oid.dataIndex << "]"; - /* - if ( !oid.element()->hasFields() ) - ss << "[" << oid.dataIndex << "]"; - if ( oid.element()->numData() > 1 ) - ss << "[" << oid.dataIndex << "]"; - */ - } - // Append braces if Eref was for a fieldElement. This should - // work even if it is off-node. - if ( e.element()->hasFields() ) { - ss << "[" << e.fieldIndex() << "]"; - } - - return ss.str(); + static const Finfo* pf = neutralCinfo->findFinfo( "parentMsg" ); + static const DestFinfo* pf2 = dynamic_cast< const DestFinfo* >( pf ); + static const FuncId pafid = pf2->getFid(); + + vector< ObjId > pathVec; + ObjId curr = e.objId(); + stringstream ss; + + pathVec.push_back( curr ); + while ( curr.id != Id() ) + { + ObjId mid = curr.eref().element()->findCaller( pafid ); + if ( mid == ObjId() ) + { + cout << "Error: Neutral::path:Cannot follow msg of ObjId: " << + e.objId() << " for func: " << pafid << endl; + break; + } + curr = Msg::getMsg( mid )->findOtherEnd( curr ); + pathVec.push_back( curr ); + } + if ( pathVec.size() <= 1 ) + return "/"; + for ( unsigned int i = 1; i < pathVec.size(); ++i ) + { + ss << "/"; + ObjId& oid = pathVec[ pathVec.size() - i - 1 ]; + ss << oid.element()->getName(); + if ( !oid.element()->hasFields() ) + ss << "[" << oid.dataIndex << "]"; + /* + if ( !oid.element()->hasFields() ) + ss << "[" << oid.dataIndex << "]"; + if ( oid.element()->numData() > 1 ) + ss << "[" << oid.dataIndex << "]"; + */ + } + // Append braces if Eref was for a fieldElement. This should + // work even if it is off-node. + if ( e.element()->hasFields() ) + { + ss << "[" << e.fieldIndex() << "]"; + } + + return ss.str(); } // Neutral does not have any fields. istream& operator >>( istream& s, Neutral& d ) { - return s; + return s; } ostream& operator <<( ostream& s, const Neutral& d ) { - return s; + return s; } bool Neutral::isGlobalField( const string& field ) { - if ( field.length() < 8 ) - return 0; - if ( field.substr( 0, 4 ) == "set_" ) { - if ( field == "set_name" ) - return 1; - if ( field == "set_group" ) - return 1; - if ( field == "set_lastDimension" ) // This is the critical one! - return 1; - } - return 0; + if ( field.length() < 8 ) + return 0; + if ( field.substr( 0, 4 ) == "set_" ) + { + if ( field == "set_name" ) + return 1; + if ( field == "set_group" ) + return 1; + if ( field == "set_lastDimension" ) // This is the critical one! + return 1; + } + return 0; } diff --git a/shell/Neutral.h b/shell/Neutral.h index b5bf3e69..939d396b 100644 --- a/shell/Neutral.h +++ b/shell/Neutral.h @@ -21,218 +21,218 @@ class Cinfo; class Neutral { - public: - friend istream& operator >>( istream& s, Neutral& d ); - friend ostream& operator <<( ostream& s, const Neutral& d ); - Neutral(); - - ///////////////////////////////////////////////////////////////// - // Field access functions - ///////////////////////////////////////////////////////////////// - - /** - * Field access functions for the entire object. For Neutrals - * the setThis function is a dummy: it doesn't do anything because - * the Neutral has no data to set. However, the function name acts - * as a placeholder and derived objects can override the function - * so that the entire object can be accessed as a field and also - * for inter-node data transfer. - */ - void setThis( Neutral v ); - - /** - * Field access functions for the entire object. For Neutrals - * the getThis function does return the Neutral object, but it - * has no data to set. However, the function name acts - * as a placeholder and derived objects can override the function - * so that the entire object can be accessed as a field and also - * used for inter-node data transfer. - */ - Neutral getThis() const; - - /** - * Field access functions for the name of the Element/Neutral - */ - void setName( const Eref& e, string name ); - string getName( const Eref& e ) const; - - /** - * Readonly field access function for getting all outgoing Msgs. - */ - vector< ObjId > getOutgoingMsgs( const Eref& e ) const; - - /** - * Readonly field access function for getting all incoming Msgs. - */ - vector< ObjId > getIncomingMsgs( const Eref& e ) const; - - /** - * Readonly field access function for getting Ids connected to - * current Id via specified Field. - * Field is specified by its name. - * Returns an empty vector if it fails. - */ - vector< Id > getNeighbors( const Eref& e, string field ) const; - - /** - * Return vector of target ObjIds - * called by the specified SrcFinfo, by the current object. - * Twin function to getMsgDestFunctions. - */ - vector< ObjId > getMsgDests( const Eref& e, string src ) const; - - /** - * Return vector of function names called on each target ObjId - * of the specified SrcFinfo, by the current object. - * Twin function to getMsgDests. - */ - vector< string > getMsgDestFunctions( - const Eref& e, string src ) const; - - /** - * Returns True if the object is derived from the specified class - */ - bool isA( const Eref& e, string className ) const; - - /** - * Simply returns own ObjId - */ - ObjId getObjId( const Eref& e ) const; - - /** - * Looks up the full Id info for the parent of the current Element - */ - ObjId getParent( const Eref& e ) const; - - /** - * Looks up all the Element children of the current Element - */ - vector< Id > getChildren( const Eref& e ) const; - - /** - * Builds a vector of all descendants of e - */ - unsigned int buildTree( const Eref& e, vector< Id >& tree ) const; - - /** - * Traverses to root, building path. - */ - string getPath( const Eref& e ) const; - - /** - * Looks up the Class name of the current Element - */ - string getClass( const Eref& e ) const; - - /** - * numData is the number of data entries on this Element. - */ - void setNumData( const Eref& e, unsigned int num ); - unsigned int getNumData( const Eref& e ) const; - - /** - * numField is the size of the field array on the FieldElement - * specified by the Eref including its data index. - */ - void setNumField( const Eref& e, unsigned int num ); - unsigned int getNumField( const Eref& e ) const; - - /// Id is the Id of the object, converted to unsigned int. - unsigned int getId( const Eref& e ) const; - /// Index is the dataIndex of the object - unsigned int getIndex( const Eref& e ) const; - /// fieldIndex specifies field entry if FieldElement. Otherwise zero - unsigned int getFieldIndex( const Eref& e ) const; - - /** - * The clock Tick specifies the timing and order of execution - * of the 'process' action of this object in the simulation. - * The timing is set by assigning the appropriate dt to - * this tick in the Clock object. - * A value of -1 means that the object is disabled. - */ - void setTick( const Eref& e, int num ); - /// Returns clock tick of this object. - int getTick( const Eref& e ) const; - - /// Returns dt associated with this object based on its clock tick. - double getDt( const Eref& e ) const; - - /// Information function to return names of all value Finfos. - vector< string > getValueFields( const Eref& e ) const; - /// Information function to return names of all SrcFinfos. - vector< string > getSourceFields( const Eref& e ) const; - /// Information function to return names of all DestFinfos. - vector< string > getDestFields( const Eref& e ) const; - //////////////////////////////////////////////////////////// - // DestFinfo functions - //////////////////////////////////////////////////////////// - - /** - * Destroys Element and all children - */ - void destroy( const Eref& e, int stage ); - - /** - * Request conversion of data into a blockDataHandler subclass, - * and to carry out node balancing of data as per args. - */ - void blockNodeBalance( const Eref& e, - unsigned int, unsigned int, unsigned int ); - - /** - * Request conversion of data into a generalDataHandler subclass, - * and to carry out node balancing of data as per args. - */ - void generalNodeBalance( const Eref& e, - unsigned int myNode, vector< unsigned int > nodeAssignment ); - - - //////////////////////////////////////////////////////////// - // Static utility functions - //////////////////////////////////////////////////////////// - - /** - * Finds specific named child - */ - static Id child( const Eref& e, const string& name ); - - /** - * Returns parent object - */ - static ObjId parent( const Eref& e ); - static ObjId parent( ObjId id ); - - /** - * Checks if 'me' is a descendant of 'ancestor' - */ - static bool isDescendant( Id me, Id ancestor ); - - /** - * Standard initialization function, used whenever we want to - * look up the class Cinfo - */ - static const Cinfo* initCinfo(); - - /** - * return ids of all the children in ret. - */ - static void children( const Eref& e, vector< Id >& ret ); - - /** - * Finds the path of element e - */ - static string path( const Eref& e ); - - /** - * Checks if specified field is a global, typically because it is - * present on the Element and therefore should be assigned uniformly - * on all nodes - */ - static bool isGlobalField( const string& field ); - - private: - // string name_; +public: + friend istream& operator >>( istream& s, Neutral& d ); + friend ostream& operator <<( ostream& s, const Neutral& d ); + Neutral(); + + ///////////////////////////////////////////////////////////////// + // Field access functions + ///////////////////////////////////////////////////////////////// + + /** + * Field access functions for the entire object. For Neutrals + * the setThis function is a dummy: it doesn't do anything because + * the Neutral has no data to set. However, the function name acts + * as a placeholder and derived objects can override the function + * so that the entire object can be accessed as a field and also + * for inter-node data transfer. + */ + void setThis( Neutral v ); + + /** + * Field access functions for the entire object. For Neutrals + * the getThis function does return the Neutral object, but it + * has no data to set. However, the function name acts + * as a placeholder and derived objects can override the function + * so that the entire object can be accessed as a field and also + * used for inter-node data transfer. + */ + Neutral getThis() const; + + /** + * Field access functions for the name of the Element/Neutral + */ + void setName( const Eref& e, string name ); + string getName( const Eref& e ) const; + + /** + * Readonly field access function for getting all outgoing Msgs. + */ + vector< ObjId > getOutgoingMsgs( const Eref& e ) const; + + /** + * Readonly field access function for getting all incoming Msgs. + */ + vector< ObjId > getIncomingMsgs( const Eref& e ) const; + + /** + * Readonly field access function for getting Ids connected to + * current Id via specified Field. + * Field is specified by its name. + * Returns an empty vector if it fails. + */ + vector< Id > getNeighbors( const Eref& e, string field ) const; + + /** + * Return vector of target ObjIds + * called by the specified SrcFinfo, by the current object. + * Twin function to getMsgDestFunctions. + */ + vector< ObjId > getMsgDests( const Eref& e, string src ) const; + + /** + * Return vector of function names called on each target ObjId + * of the specified SrcFinfo, by the current object. + * Twin function to getMsgDests. + */ + vector< string > getMsgDestFunctions( + const Eref& e, string src ) const; + + /** + * Returns True if the object is derived from the specified class + */ + bool isA( const Eref& e, string className ) const; + + /** + * Simply returns own ObjId + */ + ObjId getObjId( const Eref& e ) const; + + /** + * Looks up the full Id info for the parent of the current Element + */ + ObjId getParent( const Eref& e ) const; + + /** + * Looks up all the Element children of the current Element + */ + vector< Id > getChildren( const Eref& e ) const; + + /** + * Builds a vector of all descendants of e + */ + unsigned int buildTree( const Eref& e, vector< Id >& tree ) const; + + /** + * Traverses to root, building path. + */ + string getPath( const Eref& e ) const; + + /** + * Looks up the Class name of the current Element + */ + string getClass( const Eref& e ) const; + + /** + * numData is the number of data entries on this Element. + */ + void setNumData( const Eref& e, unsigned int num ); + unsigned int getNumData( const Eref& e ) const; + + /** + * numField is the size of the field array on the FieldElement + * specified by the Eref including its data index. + */ + void setNumField( const Eref& e, unsigned int num ); + unsigned int getNumField( const Eref& e ) const; + + /// Id is the Id of the object, converted to unsigned int. + unsigned int getId( const Eref& e ) const; + /// Index is the dataIndex of the object + unsigned int getIndex( const Eref& e ) const; + /// fieldIndex specifies field entry if FieldElement. Otherwise zero + unsigned int getFieldIndex( const Eref& e ) const; + + /** + * The clock Tick specifies the timing and order of execution + * of the 'process' action of this object in the simulation. + * The timing is set by assigning the appropriate dt to + * this tick in the Clock object. + * A value of -1 means that the object is disabled. + */ + void setTick( const Eref& e, int num ); + /// Returns clock tick of this object. + int getTick( const Eref& e ) const; + + /// Returns dt associated with this object based on its clock tick. + double getDt( const Eref& e ) const; + + /// Information function to return names of all value Finfos. + vector< string > getValueFields( const Eref& e ) const; + /// Information function to return names of all SrcFinfos. + vector< string > getSourceFields( const Eref& e ) const; + /// Information function to return names of all DestFinfos. + vector< string > getDestFields( const Eref& e ) const; + //////////////////////////////////////////////////////////// + // DestFinfo functions + //////////////////////////////////////////////////////////// + + /** + * Destroys Element and all children + */ + void destroy( const Eref& e, int stage ); + + /** + * Request conversion of data into a blockDataHandler subclass, + * and to carry out node balancing of data as per args. + */ + void blockNodeBalance( const Eref& e, + unsigned int, unsigned int, unsigned int ); + + /** + * Request conversion of data into a generalDataHandler subclass, + * and to carry out node balancing of data as per args. + */ + void generalNodeBalance( const Eref& e, + unsigned int myNode, vector< unsigned int > nodeAssignment ); + + + //////////////////////////////////////////////////////////// + // Static utility functions + //////////////////////////////////////////////////////////// + + /** + * Finds specific named child + */ + static Id child( const Eref& e, const string& name ); + + /** + * Returns parent object + */ + static ObjId parent( const Eref& e ); + static ObjId parent( ObjId id ); + + /** + * Checks if 'me' is a descendant of 'ancestor' + */ + static bool isDescendant( Id me, Id ancestor ); + + /** + * Standard initialization function, used whenever we want to + * look up the class Cinfo + */ + static const Cinfo* initCinfo(); + + /** + * return ids of all the children in ret. + */ + static void children( const Eref& e, vector< Id >& ret ); + + /** + * Finds the path of element e + */ + static string path( const Eref& e ); + + /** + * Checks if specified field is a global, typically because it is + * present on the Element and therefore should be assigned uniformly + * on all nodes + */ + static bool isGlobalField( const string& field ); + +private: + // string name_; }; #endif // _NEUTRAL_H diff --git a/shell/Shell.cpp b/shell/Shell.cpp index fe55a708..78ce73ff 100644 --- a/shell/Shell.cpp +++ b/shell/Shell.cpp @@ -290,18 +290,15 @@ ObjId Shell::doAddMsg( const string& msgType, const Finfo* f1 = src.id.element()->cinfo()->findFinfo( srcField ); if ( !f1 ) { - cout << myNode_ << ": Shell::doAddMsg: Error: Failed to find field " << srcField << - " on src: " << src.id.element()->getName() << endl; + cout << myNode_ << ": Shell::doAddMsg: Error: Failed to find field '" << srcField << + "' on src: " << src.id.element()->getName() << endl; return ObjId(0, BADINDEX ); } const Finfo* f2 = dest.id.element()->cinfo()->findFinfo( destField ); if ( !f2 ) { - cout << myNode_ << ": Shell::doAddMsg: Error: Failed to find field " << destField << - " on dest: " << dest.id.element()->getName() << endl; - cout << "Available fields are : " << endl - << moose::mapToString(dest.id.element()->cinfo()->finfoMap()); - + cout << myNode_ << ": Shell::doAddMsg: Error: Failed to find field '" << destField << + "' on dest: " << dest.id.element()->getName() << endl; return ObjId( 0, BADINDEX ); } if ( ! f1->checkTarget( f2 ) ) diff --git a/synapse/RollingMatrix.cpp b/synapse/RollingMatrix.cpp index 189d85bc..37abbe0f 100644 --- a/synapse/RollingMatrix.cpp +++ b/synapse/RollingMatrix.cpp @@ -8,13 +8,15 @@ **********************************************************************/ #include +#include +#include using namespace std; + #include "RollingMatrix.h" -#include -// #include + RollingMatrix::RollingMatrix() - : nrows_(0), ncolumns_(0), currentStartRow_(0) + : nrows_(0), ncolumns_(0), currentStartRow_(0) {;} @@ -23,101 +25,103 @@ RollingMatrix::~RollingMatrix() RollingMatrix& RollingMatrix::operator=( const RollingMatrix& other ) { - nrows_ = other.nrows_; - ncolumns_ = other.ncolumns_; - currentStartRow_ = other.currentStartRow_; - rows_ = other.rows_; - return *this; + nrows_ = other.nrows_; + ncolumns_ = other.ncolumns_; + currentStartRow_ = other.currentStartRow_; + rows_ = other.rows_; + return *this; } -void RollingMatrix::resize( unsigned int nrows, unsigned int ncolumns ) +void RollingMatrix::resize( size_t nrows, size_t ncolumns ) { - rows_.resize( nrows ); - nrows_ = nrows; - ncolumns_ = ncolumns; - for ( unsigned int i = 0; i < nrows; ++i ) { - rows_[i].resize( ncolumns, 0.0 ); - } - currentStartRow_ = 0; + rows_.resize( nrows ); + nrows_ = nrows; + ncolumns_ = ncolumns; + for ( size_t i = 0; i < nrows; ++i ) + { + rows_[i].resize( ncolumns, 0.0 ); + } + currentStartRow_ = 0; } -double RollingMatrix::get( unsigned int row, unsigned int column ) const +double RollingMatrix::get( size_t row, size_t column ) const { - unsigned int index = (row + currentStartRow_ ) % nrows_; - return rows_[index][column]; + size_t index = (row + currentStartRow_ ) % nrows_; + return rows_[index][column]; } -void RollingMatrix::sumIntoEntry( double input, unsigned int row, unsigned int column ) +void RollingMatrix::sumIntoEntry( double input, size_t row, size_t column ) { - unsigned int index = (row + currentStartRow_ ) % nrows_; - SparseVector& sv = rows_[index]; - sv[column] += input; + size_t index = (row + currentStartRow_ ) % nrows_; + SparseVector& sv = rows_[index]; + sv[column] += input; } -void RollingMatrix::sumIntoRow( const vector< double >& input, unsigned int row ) +void RollingMatrix::sumIntoRow( const vector< double >& input, size_t row ) { - unsigned int index = (row + currentStartRow_) % nrows_; - SparseVector& sv = rows_[index]; + size_t index = (row + currentStartRow_) % nrows_; + SparseVector& sv = rows_[index]; - for (unsigned int i = 0; i < input.size(); ++i ) - sv[i] += input[i]; + for (size_t i = 0; i < input.size(); ++i ) + sv[i] += input[i]; } double RollingMatrix::dotProduct( const vector< double >& input, - unsigned int row, unsigned int startColumn ) const + size_t row, size_t startColumn ) const { - /// startColumn is the middle of the kernel. - unsigned int index = (row + currentStartRow_) % nrows_; - const SparseVector& sv = rows_[index]; - unsigned int i2 = input.size()/2; - unsigned int istart = (startColumn >= i2) ? 0 : i2-startColumn; - unsigned int colstart = (startColumn <= i2) ? 0 : startColumn - i2; - unsigned int iend = (sv.size()-startColumn > i2 ) ? input.size() : - i2 - startColumn + sv.size(); - - // if ( iend >= istart ) cout << startColumn << i2 << istart << iend << colstart << "\n"; - double ret = 0; - for (unsigned int i = istart, j = 0; i < iend; ++i, ++j ) - ret += sv[j + colstart] * input[i]; - - /* - double ret = 0; - if ( input.size() + startColumn <= sv.size() ) { - for (unsigned int i = 0; i < input.size(); ++i ) - ret += sv[i + startColumn] * input[i]; - } else if ( sv.size() > startColumn ) { - unsigned int end = sv.size() - startColumn; - for (unsigned int i = 0; i < end; ++i ) - ret += sv[i + startColumn] * input[i]; - } - */ - return ret; + /// startColumn is the middle of the kernel. + size_t index = (row + currentStartRow_) % nrows_; + const SparseVector& sv = rows_[index]; + size_t i2 = input.size()/2; + size_t istart = (startColumn >= i2) ? 0 : i2-startColumn; + size_t colstart = (startColumn <= i2) ? 0 : startColumn - i2; + size_t iend = (sv.size()-startColumn > i2 ) ? input.size() : + i2 - startColumn + sv.size(); + + // if ( iend >= istart ) cout << startColumn << i2 << istart << iend << colstart << "\n"; + double ret = 0; + for (size_t i = istart, j = 0; i < iend; ++i, ++j ) + ret += sv[j + colstart] * input[i]; + + /* + double ret = 0; + if ( input.size() + startColumn <= sv.size() ) { + for (size_t i = 0; i < input.size(); ++i ) + ret += sv[i + startColumn] * input[i]; + } else if ( sv.size() > startColumn ) { + size_t end = sv.size() - startColumn; + for (size_t i = 0; i < end; ++i ) + ret += sv[i + startColumn] * input[i]; + } + */ + return ret; } void RollingMatrix::correl( vector< double >& ret, - const vector< double >& input, unsigned int row) const + const vector< double >& input, size_t row) const { - if ( ret.size() < ncolumns_ ) - ret.resize( ncolumns_, 0.0 ); - for ( unsigned int i = 0; i < ncolumns_; ++i ) { - ret[i] += dotProduct( input, row, i ); - } + if ( ret.size() < ncolumns_ ) + ret.resize( ncolumns_, 0.0 ); + for ( size_t i = 0; i < ncolumns_; ++i ) + { + ret[i] += dotProduct( input, row, i ); + } } -void RollingMatrix::zeroOutRow( unsigned int row ) +void RollingMatrix::zeroOutRow( size_t row ) { - unsigned int index = (row + currentStartRow_) % nrows_; - rows_[index].assign( rows_[index].size(), 0.0 ); + size_t index = (row + currentStartRow_) % nrows_; + rows_[index].assign( rows_[index].size(), 0.0 ); } void RollingMatrix::rollToNextRow() { - if ( currentStartRow_ == 0 ) - currentStartRow_ = nrows_ - 1; - else - currentStartRow_--; - zeroOutRow( 0 ); + if ( currentStartRow_ == 0 ) + currentStartRow_ = nrows_ - 1; + else + currentStartRow_--; + zeroOutRow( 0 ); } diff --git a/synapse/RollingMatrix.h b/synapse/RollingMatrix.h index b78a5b25..dc12d6b2 100644 --- a/synapse/RollingMatrix.h +++ b/synapse/RollingMatrix.h @@ -13,49 +13,50 @@ // Temporary, just to get going. typedef vector< double > SparseVector; -class RollingMatrix { - public: - // Specify empty matrix. - RollingMatrix(); - ~RollingMatrix(); - RollingMatrix& operator=( const RollingMatrix& other ); - - // Specify size of matrix. Allocations may happen later. - void resize( unsigned int numRows, unsigned int numColumns ); - - // Return specified entry. - double get( unsigned int row, unsigned int column ) const; - - // Sum contents of input into entry at specfied row, column. - // Row index is relative to current zero. - void sumIntoEntry( double input, unsigned int row, unsigned int column ); - - // Sum contents of input into vector at specfied row. - // Row index is relative to current zero. - void sumIntoRow( const vector< double >& input, unsigned int row ); - - // Return dot product of input with internal vector at specified - // row, starting at specified column. - double dotProduct( const vector< double >& input, unsigned int row, - unsigned int startColumn ) const; - - // Return correlation found by summing dotProduct across all columns - void correl( vector< double >& ret, const vector< double >& input, - unsigned int row ) const; - - // Zero out contents of row. - void zeroOutRow( unsigned int row ); - - // Roll the matrix by one row. What was row 0 becomes row 1, etc. - // Last row vanishes. - void rollToNextRow(); // - - private: - unsigned int nrows_; - unsigned int ncolumns_; - unsigned int currentStartRow_; - - vector< SparseVector > rows_; +class RollingMatrix +{ +public: + // Specify empty matrix. + RollingMatrix(); + ~RollingMatrix(); + RollingMatrix& operator=( const RollingMatrix& other ); + + // Specify size of matrix. Allocations may happen later. + void resize( size_t numRows, size_t numColumns ); + + // Return specified entry. + double get( size_t row, size_t column ) const; + + // Sum contents of input into entry at specfied row, column. + // Row index is relative to current zero. + void sumIntoEntry( double input, size_t row, size_t column ); + + // Sum contents of input into vector at specfied row. + // Row index is relative to current zero. + void sumIntoRow( const vector< double >& input, size_t row ); + + // Return dot product of input with internal vector at specified + // row, starting at specified column. + double dotProduct( const vector< double >& input, size_t row, + size_t startColumn ) const; + + // Return correlation found by summing dotProduct across all columns + void correl( vector< double >& ret, const vector< double >& input, + size_t row ) const; + + // Zero out contents of row. + void zeroOutRow( size_t row ); + + // Roll the matrix by one row. What was row 0 becomes row 1, etc. + // Last row vanishes. + void rollToNextRow(); // + +private: + size_t nrows_; + size_t ncolumns_; + size_t currentStartRow_; + + vector< SparseVector > rows_; }; #endif // _ROLLING_MATRIX diff --git a/synapse/SeqSynHandler.cpp b/synapse/SeqSynHandler.cpp index da94fc42..ff20d636 100644 --- a/synapse/SeqSynHandler.cpp +++ b/synapse/SeqSynHandler.cpp @@ -19,187 +19,188 @@ const Cinfo* SeqSynHandler::initCinfo() { - static string doc[] = - { - "Name", "SeqSynHandler", - "Author", "Upi Bhalla", - "Description", - "The SeqSynHandler handles synapses that recognize sequentially " - "ordered input, where the ordering is both in space and time. " - "It assumes that the N input synapses are ordered and " - "equally spaced along a single linear vector.\n " - "To do this it maintains a record of recent synaptic input, " - "for a duration of *historyTime*, at a time interval *seqDt*. " - "*SeqDt* is typically longer than the simulation " - "timestep *dt* for the synapse, and cannot be shorter. " - "*SeqDt* should represent the characteristic time of advance " - "of the sequence. \n" - "The SeqSynHandler uses a 2-D kernel to define how to recognize" - " a sequence, with dependence both on space and history. " - "This kernel is defined by the *kernelEquation* as a " - "mathematical expression in x (synapse number) and t (time)." - "It computes a vector with the local *response* term for each " - "point along all inputs, by taking a 2-d convolution of the " - "kernel with the history[time][synapse#] matrix." - "\nThe local response can affect the synapse in three ways: " - "1. It can sum the entire response vector, scale by the " - "*sequenceScale* term, and send to the synapse as a steady " - "activation. Consider this a cell-wide immediate response to " - "a sequence that it likes.\n" - "2. It do an instantaneous scaling of the weight of each " - "individual synapse by the corresponding entry in the response " - "vector. It uses the *plasticityScale* term to do this. " - "Consider " - "this a short-term plasticity effect on specific synapses. \n" - "3. It can do long-term plasticity of each individual synapse " - "using the matched local entries in the response vector and " - "individual synapse history as inputs to the learning rule. " - "This is not yet implemented.\n" - "In addition to all these, the SeqSynHandler can act just like " - "a regular synapse, where it responds to individual synaptic " - "input according to the weight of the synapse. The size of " - "this component of the output is scaled by *baseScale*\n" - }; - - static FieldElementFinfo< SynHandlerBase, Synapse > synFinfo( - "synapse", - "Sets up field Elements for synapse", - Synapse::initCinfo(), - &SynHandlerBase::getSynapse, - &SynHandlerBase::setNumSynapses, - &SynHandlerBase::getNumSynapses - ); - - static ValueFinfo< SeqSynHandler, string > kernelEquation( - "kernelEquation", - "Equation in x and t to define kernel for sequence recognition", - &SeqSynHandler::setKernelEquation, - &SeqSynHandler::getKernelEquation - ); - static ValueFinfo< SeqSynHandler, unsigned int > kernelWidth( - "kernelWidth", - "Width of kernel, i.e., number of synapses taking part in seq.", - &SeqSynHandler::setKernelWidth, - &SeqSynHandler::getKernelWidth - ); - static ValueFinfo< SeqSynHandler, double > seqDt( - "seqDt", - "Characteristic time for advancing the sequence.", - &SeqSynHandler::setSeqDt, - &SeqSynHandler::getSeqDt - ); - static ValueFinfo< SeqSynHandler, double > historyTime( - "historyTime", - "Duration to keep track of history of inputs to all synapses.", - &SeqSynHandler::setHistoryTime, - &SeqSynHandler::getHistoryTime - ); - static ValueFinfo< SeqSynHandler, double > baseScale( - "baseScale", - "Basal scaling factor for regular synaptic activation.", - &SeqSynHandler::setBaseScale, - &SeqSynHandler::getBaseScale - ); - static ValueFinfo< SeqSynHandler, double > sequenceScale( - "sequenceScale", - "Scaling factor for sustained activation of synapse by seq", - &SeqSynHandler::setSequenceScale, - &SeqSynHandler::getSequenceScale - ); - static ValueFinfo< SeqSynHandler, vector< unsigned int > > synapseOrder( - "synapseOrder", - "Mapping of synapse input order to spatial order on syn array." - "Entries in this vector are indices which must remain smaller " - "than numSynapses. The system will fix up if you mess up. " - "It does not insist on unique mappings, but these are " - "desirable as outcome is undefined for repeated entries.", - &SeqSynHandler::setSynapseOrder, - &SeqSynHandler::getSynapseOrder - ); - static ValueFinfo< SeqSynHandler, int > synapseOrderOption( - "synapseOrderOption", - "How to do the synapse order remapping. This rule stays in " - "place and guarantees safe mappings even if the number of " - "synapses is altered. Options:\n" - "-2: User ordering.\n" - "-1: Sequential ordering, 0 to numSynapses-1.\n" - "0: Random ordering using existing system seed.\n" - ">0: Random ordering using seed specified by this number\n" - "Default is -1, sequential ordering.", - &SeqSynHandler::setSynapseOrderOption, - &SeqSynHandler::getSynapseOrderOption - ); - static ReadOnlyValueFinfo< SeqSynHandler, double > seqActivation( - "seqActivation", - "Reports summed activation of synaptic channel by sequence", - &SeqSynHandler::getSeqActivation - ); - static ValueFinfo< SeqSynHandler, double > plasticityScale( - "plasticityScale", - "Scaling factor for doing plasticity by scaling each synapse by response vector", - &SeqSynHandler::setPlasticityScale, - &SeqSynHandler::getPlasticityScale - ); - - static ValueFinfo< SeqSynHandler, double > sequencePower( - "sequencePower", - "Exponent for the outcome of the sequential calculations. " - "This is needed because linear summation of terms in the kernel" - "means that a brief stong sequence match is no better than lots" - "of successive low matches. In other words, 12345 is no better" - "than 11111. Using an exponent lets us select the former." - "Defaults to 1.0.", - &SeqSynHandler::setSequencePower, - &SeqSynHandler::getSequencePower - ); - - static ReadOnlyValueFinfo< SeqSynHandler, vector< double > > - weightScaleVec( - "weightScaleVec", - "Vector of weight scaling for each synapse", - &SeqSynHandler::getWeightScaleVec - ); - static ReadOnlyValueFinfo< SeqSynHandler, vector< double > > kernel( - "kernel", - "All entries of kernel, as a linear vector", - &SeqSynHandler::getKernel - ); - static ReadOnlyValueFinfo< SeqSynHandler, vector< double > > history( - "history", - "All entries of history, as a linear vector", - &SeqSynHandler::getHistory - ); - - static Finfo* seqSynHandlerFinfos[] = { - &synFinfo, // FieldElement - &kernelEquation, // Field - &kernelWidth, // Field - &seqDt, // Field - &historyTime, // Field - &sequenceScale, // Field - &baseScale, // Field - &synapseOrder, // Field - &synapseOrderOption, // Field - &seqActivation, // ReadOnlyField - &plasticityScale, // Field - &sequencePower, // Field - &weightScaleVec, // ReadOnlyField - &kernel, // ReadOnlyField - &history // ReadOnlyField - }; - - static Dinfo< SeqSynHandler > dinfo; - static Cinfo seqSynHandlerCinfo ( - "SeqSynHandler", - SynHandlerBase::initCinfo(), - seqSynHandlerFinfos, - sizeof( seqSynHandlerFinfos ) / sizeof ( Finfo* ), - &dinfo, - doc, - sizeof( doc ) / sizeof( string ) - ); - - return &seqSynHandlerCinfo; + static string doc[] = + { + "Name", "SeqSynHandler", + "Author", "Upi Bhalla", + "Description", + "The SeqSynHandler handles synapses that recognize sequentially " + "ordered input, where the ordering is both in space and time. " + "It assumes that the N input synapses are ordered and " + "equally spaced along a single linear vector.\n " + "To do this it maintains a record of recent synaptic input, " + "for a duration of *historyTime*, at a time interval *seqDt*. " + "*SeqDt* is typically longer than the simulation " + "timestep *dt* for the synapse, and cannot be shorter. " + "*SeqDt* should represent the characteristic time of advance " + "of the sequence. \n" + "The SeqSynHandler uses a 2-D kernel to define how to recognize" + " a sequence, with dependence both on space and history. " + "This kernel is defined by the *kernelEquation* as a " + "mathematical expression in x (synapse number) and t (time)." + "It computes a vector with the local *response* term for each " + "point along all inputs, by taking a 2-d convolution of the " + "kernel with the history[time][synapse#] matrix." + "\nThe local response can affect the synapse in three ways: " + "1. It can sum the entire response vector, scale by the " + "*sequenceScale* term, and send to the synapse as a steady " + "activation. Consider this a cell-wide immediate response to " + "a sequence that it likes.\n" + "2. It do an instantaneous scaling of the weight of each " + "individual synapse by the corresponding entry in the response " + "vector. It uses the *plasticityScale* term to do this. " + "Consider " + "this a short-term plasticity effect on specific synapses. \n" + "3. It can do long-term plasticity of each individual synapse " + "using the matched local entries in the response vector and " + "individual synapse history as inputs to the learning rule. " + "This is not yet implemented.\n" + "In addition to all these, the SeqSynHandler can act just like " + "a regular synapse, where it responds to individual synaptic " + "input according to the weight of the synapse. The size of " + "this component of the output is scaled by *baseScale*\n" + }; + + static FieldElementFinfo< SynHandlerBase, Synapse > synFinfo( + "synapse", + "Sets up field Elements for synapse", + Synapse::initCinfo(), + &SynHandlerBase::getSynapse, + &SynHandlerBase::setNumSynapses, + &SynHandlerBase::getNumSynapses + ); + + static ValueFinfo< SeqSynHandler, string > kernelEquation( + "kernelEquation", + "Equation in x and t to define kernel for sequence recognition", + &SeqSynHandler::setKernelEquation, + &SeqSynHandler::getKernelEquation + ); + static ValueFinfo< SeqSynHandler, unsigned int > kernelWidth( + "kernelWidth", + "Width of kernel, i.e., number of synapses taking part in seq.", + &SeqSynHandler::setKernelWidth, + &SeqSynHandler::getKernelWidth + ); + static ValueFinfo< SeqSynHandler, double > seqDt( + "seqDt", + "Characteristic time for advancing the sequence.", + &SeqSynHandler::setSeqDt, + &SeqSynHandler::getSeqDt + ); + static ValueFinfo< SeqSynHandler, double > historyTime( + "historyTime", + "Duration to keep track of history of inputs to all synapses.", + &SeqSynHandler::setHistoryTime, + &SeqSynHandler::getHistoryTime + ); + static ValueFinfo< SeqSynHandler, double > baseScale( + "baseScale", + "Basal scaling factor for regular synaptic activation.", + &SeqSynHandler::setBaseScale, + &SeqSynHandler::getBaseScale + ); + static ValueFinfo< SeqSynHandler, double > sequenceScale( + "sequenceScale", + "Scaling factor for sustained activation of synapse by seq", + &SeqSynHandler::setSequenceScale, + &SeqSynHandler::getSequenceScale + ); + static ValueFinfo< SeqSynHandler, vector< unsigned int > > synapseOrder( + "synapseOrder", + "Mapping of synapse input order to spatial order on syn array." + "Entries in this vector are indices which must remain smaller " + "than numSynapses. The system will fix up if you mess up. " + "It does not insist on unique mappings, but these are " + "desirable as outcome is undefined for repeated entries.", + &SeqSynHandler::setSynapseOrder, + &SeqSynHandler::getSynapseOrder + ); + static ValueFinfo< SeqSynHandler, int > synapseOrderOption( + "synapseOrderOption", + "How to do the synapse order remapping. This rule stays in " + "place and guarantees safe mappings even if the number of " + "synapses is altered. Options:\n" + "-2: User ordering.\n" + "-1: Sequential ordering, 0 to numSynapses-1.\n" + "0: Random ordering using existing system seed.\n" + ">0: Random ordering using seed specified by this number\n" + "Default is -1, sequential ordering.", + &SeqSynHandler::setSynapseOrderOption, + &SeqSynHandler::getSynapseOrderOption + ); + static ReadOnlyValueFinfo< SeqSynHandler, double > seqActivation( + "seqActivation", + "Reports summed activation of synaptic channel by sequence", + &SeqSynHandler::getSeqActivation + ); + static ValueFinfo< SeqSynHandler, double > plasticityScale( + "plasticityScale", + "Scaling factor for doing plasticity by scaling each synapse by response vector", + &SeqSynHandler::setPlasticityScale, + &SeqSynHandler::getPlasticityScale + ); + + static ValueFinfo< SeqSynHandler, double > sequencePower( + "sequencePower", + "Exponent for the outcome of the sequential calculations. " + "This is needed because linear summation of terms in the kernel" + "means that a brief stong sequence match is no better than lots" + "of successive low matches. In other words, 12345 is no better" + "than 11111. Using an exponent lets us select the former." + "Defaults to 1.0.", + &SeqSynHandler::setSequencePower, + &SeqSynHandler::getSequencePower + ); + + static ReadOnlyValueFinfo< SeqSynHandler, vector< double > > + weightScaleVec( + "weightScaleVec", + "Vector of weight scaling for each synapse", + &SeqSynHandler::getWeightScaleVec + ); + static ReadOnlyValueFinfo< SeqSynHandler, vector< double > > kernel( + "kernel", + "All entries of kernel, as a linear vector", + &SeqSynHandler::getKernel + ); + static ReadOnlyValueFinfo< SeqSynHandler, vector< double > > history( + "history", + "All entries of history, as a linear vector", + &SeqSynHandler::getHistory + ); + + static Finfo* seqSynHandlerFinfos[] = + { + &synFinfo, // FieldElement + &kernelEquation, // Field + &kernelWidth, // Field + &seqDt, // Field + &historyTime, // Field + &sequenceScale, // Field + &baseScale, // Field + &synapseOrder, // Field + &synapseOrderOption, // Field + &seqActivation, // ReadOnlyField + &plasticityScale, // Field + &sequencePower, // Field + &weightScaleVec, // ReadOnlyField + &kernel, // ReadOnlyField + &history // ReadOnlyField + }; + + static Dinfo< SeqSynHandler > dinfo; + static Cinfo seqSynHandlerCinfo ( + "SeqSynHandler", + SynHandlerBase::initCinfo(), + seqSynHandlerFinfos, + sizeof( seqSynHandlerFinfos ) / sizeof ( Finfo* ), + &dinfo, + doc, + sizeof( doc ) / sizeof( string ) + ); + + return &seqSynHandlerCinfo; } static const Cinfo* seqSynHandlerCinfo = SeqSynHandler::initCinfo(); @@ -207,19 +208,19 @@ static const Cinfo* seqSynHandlerCinfo = SeqSynHandler::initCinfo(); ////////////////////////////////////////////////////////////////////// SeqSynHandler::SeqSynHandler() - : - kernelEquation_( "" ), - kernelWidth_( 5 ), - historyTime_( 2.0 ), - seqDt_ ( 1.0 ), - baseScale_( 0.0 ), - sequenceScale_( 1.0 ), - plasticityScale_( 0.0 ), - sequencePower_( 1.0 ), - seqActivation_( 0.0 ), - synapseOrderOption_( -1 ) // sequential ordering + : + kernelEquation_( "" ), + kernelWidth_( 5 ), + historyTime_( 2.0 ), + seqDt_ ( 1.0 ), + baseScale_( 0.0 ), + sequenceScale_( 1.0 ), + plasticityScale_( 0.0 ), + sequencePower_( 1.0 ), + seqActivation_( 0.0 ), + synapseOrderOption_( -1 ) // sequential ordering { - history_.resize( numHistory(), 0 ); + history_.resize( numHistory(), 0 ); } SeqSynHandler::~SeqSynHandler() @@ -228,45 +229,45 @@ SeqSynHandler::~SeqSynHandler() ////////////////////////////////////////////////////////////////////// SeqSynHandler& SeqSynHandler::operator=( const SeqSynHandler& ssh) { - synapses_ = ssh.synapses_; - for ( vector< Synapse >::iterator - i = synapses_.begin(); i != synapses_.end(); ++i ) - i->setHandler( this ); + synapses_ = ssh.synapses_; + for ( vector< Synapse >::iterator + i = synapses_.begin(); i != synapses_.end(); ++i ) + i->setHandler( this ); - // For no apparent reason, priority queues don't have a clear operation. - while( !events_.empty() ) - events_.pop(); + // For no apparent reason, priority queues don't have a clear operation. + while( !events_.empty() ) + events_.pop(); - return *this; + return *this; } void SeqSynHandler::vSetNumSynapses( const unsigned int v ) { - unsigned int prevSize = synapses_.size(); - synapses_.resize( v ); - for ( unsigned int i = prevSize; i < v; ++i ) - synapses_[i].setHandler( this ); + unsigned int prevSize = synapses_.size(); + synapses_.resize( v ); + for ( unsigned int i = prevSize; i < v; ++i ) + synapses_[i].setHandler( this ); - history_.resize( numHistory(), v ); - latestSpikes_.resize( v, 0.0 ); - weightScaleVec_.resize( v, 0.0 ); - refillSynapseOrder( v ); - updateKernel(); + history_.resize( numHistory(), v ); + latestSpikes_.resize( v, 0.0 ); + weightScaleVec_.resize( v, 0.0 ); + refillSynapseOrder( v ); + updateKernel(); } unsigned int SeqSynHandler::vGetNumSynapses() const { - return synapses_.size(); + return synapses_.size(); } Synapse* SeqSynHandler::vGetSynapse( unsigned int i ) { - static Synapse dummy; - if ( i < synapses_.size() ) - return &synapses_[i]; - cout << "Warning: SeqSynHandler::getSynapse: index: " << i << - " is out of range: " << synapses_.size() << endl; - return &dummy; + static Synapse dummy; + if ( i < synapses_.size() ) + return &synapses_[i]; + cout << "Warning: SeqSynHandler::getSynapse: index: " << i << + " is out of range: " << synapses_.size() << endl; + return &dummy; } ////////////////////////////////////////////////////////////////////// @@ -275,330 +276,353 @@ Synapse* SeqSynHandler::vGetSynapse( unsigned int i ) // values within the range that have not yet been used. void SeqSynHandler::fixSynapseOrder() { - unsigned int sz = synapseOrder_.size(); - vector< unsigned int > availableEntries( sz ); - iota( availableEntries.begin(), availableEntries.end(), 0 ); - for( unsigned int i = 0; i < sz; ++i ) { - if ( synapseOrder_[i] < sz ) - availableEntries[ synapseOrder_[i] ] = sz; - } - vector< unsigned int > ae; - for( unsigned int i = 0; i < sz; ++i ) - if ( availableEntries[i] < sz ) - ae.push_back( availableEntries[i] ); - - auto jj = ae.begin(); - for( unsigned int i = 0; i < sz; ++i ) { - if ( synapseOrder_[i] >= sz ) - synapseOrder_[i] = *jj++; - } + unsigned int sz = synapseOrder_.size(); + vector< unsigned int > availableEntries( sz ); + iota( availableEntries.begin(), availableEntries.end(), 0 ); + for( unsigned int i = 0; i < sz; ++i ) + { + if ( synapseOrder_[i] < sz ) + availableEntries[ synapseOrder_[i] ] = sz; + } + vector< unsigned int > ae; + for( unsigned int i = 0; i < sz; ++i ) + if ( availableEntries[i] < sz ) + ae.push_back( availableEntries[i] ); + + auto jj = ae.begin(); + for( unsigned int i = 0; i < sz; ++i ) + { + if ( synapseOrder_[i] >= sz ) + synapseOrder_[i] = *jj++; + } } // Beautiful snippet from Lukasz Wiklendt on StackOverflow. Returns order // of entries in a vector. -template vector sort_indexes(const vector &v) { - // initialize original index locations - vector idx(v.size()); - iota(idx.begin(), idx.end(), 0); - // sort indexes based on comparing values in v - sort(idx.begin(), idx.end(), - [&v](size_t i1, size_t i2) {return v[i1] < v[i2];}); - return idx; +template vector sort_indexes(const vector &v) +{ + // initialize original index locations + vector idx(v.size()); + iota(idx.begin(), idx.end(), 0); + // sort indexes based on comparing values in v + sort(idx.begin(), idx.end(), + [&v](size_t i1, size_t i2) + { + return v[i1] < v[i2]; + }); + return idx; } void SeqSynHandler::refillSynapseOrder( unsigned int newSize ) { - if ( synapseOrderOption_ <= -2 ) { // User order - synapseOrder_.resize( newSize, newSize ); - fixSynapseOrder(); - } else if ( synapseOrderOption_ == -1 ) { // Ordered - synapseOrder_.resize( newSize ); - for ( unsigned int i = 0 ; i < newSize; ++i ) - synapseOrder_[i] = i; - } else { - synapseOrder_.resize( newSize ); - if ( synapseOrderOption_ > 0 ) { // Specify seed explicitly - moose::mtseed( synapseOrderOption_ ); - } - vector< double > x; - for ( unsigned int i = 0; i < newSize; ++i ) - x.push_back( moose::mtrand() ); - auto idx = sort_indexes< double >( x ); - for ( unsigned int i = 0; i < newSize; ++i ) - synapseOrder_[i] = idx[i]; - } + if ( synapseOrderOption_ <= -2 ) // User order + { + synapseOrder_.resize( newSize, newSize ); + fixSynapseOrder(); + } + else if ( synapseOrderOption_ == -1 ) // Ordered + { + synapseOrder_.resize( newSize ); + for ( unsigned int i = 0 ; i < newSize; ++i ) + synapseOrder_[i] = i; + } + else + { + synapseOrder_.resize( newSize ); + if ( synapseOrderOption_ > 0 ) // Specify seed explicitly + { + moose::mtseed( synapseOrderOption_ ); + } + vector< double > x; + for ( unsigned int i = 0; i < newSize; ++i ) + x.push_back( moose::mtrand() ); + auto idx = sort_indexes< double >( x ); + for ( unsigned int i = 0; i < newSize; ++i ) + synapseOrder_[i] = idx[i]; + } } void SeqSynHandler::updateKernel() { - if ( kernelEquation_ == "" || seqDt_ < 1e-9 || historyTime_ < 1e-9 ) - return; - double x = 0; - double t = 0; - mu::Parser p; - p.DefineVar("x", &x); - p.DefineVar("t", &t); - p.DefineConst(_T("pi"), (mu::value_type)M_PI); - p.DefineConst(_T("e"), (mu::value_type)M_E); - p.SetExpr( kernelEquation_ ); - kernel_.clear(); - int nh = numHistory(); - kernel_.resize( nh ); - for ( int i = 0; i < nh; ++i ) { - kernel_[i].resize( kernelWidth_ ); - t = i * seqDt_; - for ( unsigned int j = 0; j < kernelWidth_; ++j ) { - x = j; - kernel_[i][j] = p.Eval(); - } - } + if ( kernelEquation_ == "" || seqDt_ < 1e-9 || historyTime_ < 1e-9 ) + return; + double x = 0; + double t = 0; + moose::MooseParser p; + p.DefineVar("x", &x); + p.DefineVar("t", &t); + p.SetExpr( kernelEquation_ ); + kernel_.clear(); + int nh = numHistory(); + kernel_.resize( nh ); + for ( int i = 0; i < nh; ++i ) + { + kernel_[i].resize( kernelWidth_ ); + t = i * seqDt_; + for ( unsigned int j = 0; j < kernelWidth_; ++j ) + { + x = j; + kernel_[i][j] = p.Eval(); + } + } } ////////////////////////////////////////////////////////////////////// void SeqSynHandler::setKernelEquation( string eq ) { - kernelEquation_ = eq; - updateKernel(); + kernelEquation_ = eq; + updateKernel(); } string SeqSynHandler::getKernelEquation() const { - return kernelEquation_; + return kernelEquation_; } void SeqSynHandler::setKernelWidth( unsigned int v ) { - kernelWidth_ = v; - updateKernel(); + kernelWidth_ = v; + updateKernel(); } unsigned int SeqSynHandler::getKernelWidth() const { - return kernelWidth_; + return kernelWidth_; } void SeqSynHandler::setSeqDt( double v ) { - seqDt_ = v; - updateKernel(); - history_.resize( numHistory(), vGetNumSynapses() ); + seqDt_ = v; + updateKernel(); + history_.resize( numHistory(), vGetNumSynapses() ); } double SeqSynHandler::getSeqDt() const { - return seqDt_; + return seqDt_; } void SeqSynHandler::setHistoryTime( double v ) { - historyTime_ = v; - history_.resize( numHistory(), vGetNumSynapses() ); - updateKernel(); + historyTime_ = v; + history_.resize( numHistory(), vGetNumSynapses() ); + updateKernel(); } double SeqSynHandler::getHistoryTime() const { - return historyTime_; + return historyTime_; } void SeqSynHandler::setBaseScale( double v ) { - baseScale_ = v; + baseScale_ = v; } double SeqSynHandler::getBaseScale() const { - return baseScale_; + return baseScale_; } void SeqSynHandler::setSequenceScale( double v ) { - sequenceScale_ = v; + sequenceScale_ = v; } double SeqSynHandler::getSequenceScale() const { - return sequenceScale_; + return sequenceScale_; } double SeqSynHandler::getSeqActivation() const { - return seqActivation_; + return seqActivation_; } double SeqSynHandler::getPlasticityScale() const { - return plasticityScale_; + return plasticityScale_; } void SeqSynHandler::setPlasticityScale( double v ) { - plasticityScale_ = v; + plasticityScale_ = v; } double SeqSynHandler::getSequencePower() const { - return sequencePower_; + return sequencePower_; } void SeqSynHandler::setSequencePower( double v ) { - sequencePower_ = v; + sequencePower_ = v; } vector< double >SeqSynHandler::getWeightScaleVec() const { - return weightScaleVec_; + return weightScaleVec_; } vector< double > SeqSynHandler::getKernel() const { - int nh = numHistory(); - vector< double > ret; - for ( int i = 0; i < nh; ++i ) { - ret.insert( ret.end(), kernel_[i].begin(), kernel_[i].end() ); - } - return ret; + int nh = numHistory(); + vector< double > ret; + for ( int i = 0; i < nh; ++i ) + { + ret.insert( ret.end(), kernel_[i].begin(), kernel_[i].end() ); + } + return ret; } vector< double > SeqSynHandler::getHistory() const { - int nh = numHistory(); - int numX = vGetNumSynapses(); - vector< double > ret( numX * nh, 0.0 ); - vector< double >::iterator k = ret.begin(); - for ( int i = 0; i < nh; ++i ) { - for ( int j = 0; j < numX; ++j ) - *k++ = history_.get( i, j ); - } - return ret; + int nh = numHistory(); + int numX = vGetNumSynapses(); + vector< double > ret( numX * nh, 0.0 ); + vector< double >::iterator k = ret.begin(); + for ( int i = 0; i < nh; ++i ) + { + for ( int j = 0; j < numX; ++j ) + *k++ = history_.get( i, j ); + } + return ret; } void SeqSynHandler::setSynapseOrder( vector< unsigned int > v ) { - synapseOrder_ = v; - fixSynapseOrder(); - synapseOrderOption_ = -2; // Set the flag to say it is User defined. + synapseOrder_ = v; + fixSynapseOrder(); + synapseOrderOption_ = -2; // Set the flag to say it is User defined. } vector< unsigned int > SeqSynHandler::getSynapseOrder() const { - return synapseOrder_; + return synapseOrder_; } void SeqSynHandler::setSynapseOrderOption( int v ) { - synapseOrderOption_ = v; - refillSynapseOrder( synapseOrder_.size() ); + synapseOrderOption_ = v; + refillSynapseOrder( synapseOrder_.size() ); } int SeqSynHandler::getSynapseOrderOption() const { - return synapseOrderOption_; + return synapseOrderOption_; } ///////////////////////////////////////////////////////////////////// void SeqSynHandler::addSpike(unsigned int index, double time, double weight) { - assert( index < synapses_.size() ); - events_.push( PreSynEvent( index, time, weight ) ); - // Strictly speaking this isn't right. If we have a long time lag - // then the correct placement of the spike may be in another time - // slice. For now, to get it going for LIF neurons, this will do. - // Even in the general case we will probably have a very wide window - // for the latestSpikes slice. - // - // Here we reorder the entries in latestSpikes by the synapse order. - latestSpikes_[ synapseOrder_[index] ] += weight; + assert( index < synapses_.size() ); + events_.push( PreSynEvent( index, time, weight ) ); + // Strictly speaking this isn't right. If we have a long time lag + // then the correct placement of the spike may be in another time + // slice. For now, to get it going for LIF neurons, this will do. + // Even in the general case we will probably have a very wide window + // for the latestSpikes slice. + // + // Here we reorder the entries in latestSpikes by the synapse order. + latestSpikes_[ synapseOrder_[index] ] += weight; } double SeqSynHandler::getTopSpike( unsigned int index ) const { - if ( events_.empty() ) - return 0.0; - return events_.top().time; + if ( events_.empty() ) + return 0.0; + return events_.top().time; } unsigned int SeqSynHandler::addSynapse() { - unsigned int newSynIndex = synapses_.size(); - synapses_.resize( newSynIndex + 1 ); - synapses_[newSynIndex].setHandler( this ); - return newSynIndex; + unsigned int newSynIndex = synapses_.size(); + synapses_.resize( newSynIndex + 1 ); + synapses_[newSynIndex].setHandler( this ); + return newSynIndex; } void SeqSynHandler::dropSynapse( unsigned int msgLookup ) { - assert( msgLookup < synapses_.size() ); - synapses_[msgLookup].setWeight( -1.0 ); + assert( msgLookup < synapses_.size() ); + synapses_[msgLookup].setWeight( -1.0 ); } ///////////////////////////////////////////////////////////////////// void SeqSynHandler::vProcess( const Eref& e, ProcPtr p ) { - // Here we look at the correlations and do something with them. - int nh = numHistory(); - - // Check if we need to do correlations at all. - if ( nh > 0 && kernel_.size() > 0 ) { - // Check if timestep rolls over a seqDt boundary - if ( static_cast< int >( p->currTime / seqDt_ ) > - static_cast< int >( (p->currTime - p->dt) / seqDt_ ) ) { - history_.rollToNextRow(); - history_.sumIntoRow( latestSpikes_, 0 ); - latestSpikes_.assign( vGetNumSynapses(), 0.0 ); - - // Build up the sum of correlations over time - vector< double > correlVec( vGetNumSynapses(), 0.0 ); - for ( int i = 0; i < nh; ++i ) - history_.correl( correlVec, kernel_[i], i ); - if ( sequenceScale_ > 0.0 ) { // Sum all responses, send to chan - seqActivation_ = 0.0; - for ( vector< double >::iterator y = correlVec.begin(); - y != correlVec.end(); ++y ) - seqActivation_ += pow( *y, sequencePower_ ); - - // We'll use the seqActivation_ to send a special msg. - seqActivation_ *= sequenceScale_; - } - if ( plasticityScale_ > 0.0 ) { // Short term changes in individual wts - weightScaleVec_ = correlVec; - for ( vector< double >::iterator y=weightScaleVec_.begin(); - y != weightScaleVec_.end(); ++y ) - *y *= plasticityScale_; - } - } - } - - // Here we go through the regular synapse activation calculations. - // We can't leave it to the base class vProcess, because we need - // to scale the weights individually in some cases. - double activation = seqActivation_; // Start with seq activation - if ( plasticityScale_ > 0.0 ) { - while( !events_.empty() && events_.top().time <= p->currTime ) { - activation += events_.top().weight * baseScale_ * - weightScaleVec_[ events_.top().synIndex ] / p->dt; - events_.pop(); - } - } else { - while( !events_.empty() && events_.top().time <= p->currTime ) { - activation += baseScale_ * events_.top().weight / p->dt; - events_.pop(); - } - } - if ( activation != 0.0 ) - SynHandlerBase::activationOut()->send( e, activation ); + // Here we look at the correlations and do something with them. + int nh = numHistory(); + + // Check if we need to do correlations at all. + if ( nh > 0 && kernel_.size() > 0 ) + { + // Check if timestep rolls over a seqDt boundary + if ( static_cast< int >( p->currTime / seqDt_ ) > + static_cast< int >( (p->currTime - p->dt) / seqDt_ ) ) + { + history_.rollToNextRow(); + history_.sumIntoRow( latestSpikes_, 0 ); + latestSpikes_.assign( vGetNumSynapses(), 0.0 ); + + // Build up the sum of correlations over time + vector< double > correlVec( vGetNumSynapses(), 0.0 ); + for ( int i = 0; i < nh; ++i ) + history_.correl( correlVec, kernel_[i], i ); + if ( sequenceScale_ > 0.0 ) // Sum all responses, send to chan + { + seqActivation_ = 0.0; + for ( vector< double >::iterator y = correlVec.begin(); + y != correlVec.end(); ++y ) + seqActivation_ += pow( *y, sequencePower_ ); + + // We'll use the seqActivation_ to send a special msg. + seqActivation_ *= sequenceScale_; + } + if ( plasticityScale_ > 0.0 ) // Short term changes in individual wts + { + weightScaleVec_ = correlVec; + for ( vector< double >::iterator y=weightScaleVec_.begin(); + y != weightScaleVec_.end(); ++y ) + *y *= plasticityScale_; + } + } + } + + // Here we go through the regular synapse activation calculations. + // We can't leave it to the base class vProcess, because we need + // to scale the weights individually in some cases. + double activation = seqActivation_; // Start with seq activation + if ( plasticityScale_ > 0.0 ) + { + while( !events_.empty() && events_.top().time <= p->currTime ) + { + activation += events_.top().weight * baseScale_ * + weightScaleVec_[ events_.top().synIndex ] / p->dt; + events_.pop(); + } + } + else + { + while( !events_.empty() && events_.top().time <= p->currTime ) + { + activation += baseScale_ * events_.top().weight / p->dt; + events_.pop(); + } + } + if ( activation != 0.0 ) + SynHandlerBase::activationOut()->send( e, activation ); } void SeqSynHandler::vReinit( const Eref& e, ProcPtr p ) { - // For no apparent reason, priority queues don't have a clear operation. - while( !events_.empty() ) - events_.pop(); + // For no apparent reason, priority queues don't have a clear operation. + while( !events_.empty() ) + events_.pop(); } int SeqSynHandler::numHistory() const { - return static_cast< int >( 1.0 + floor( historyTime_ * (1.0 - 1e-6 ) / seqDt_ ) ); + return static_cast< int >( 1.0 + floor( historyTime_ * (1.0 - 1e-6 ) / seqDt_ ) ); } diff --git a/tests/alpha/function.py b/tests/alpha/function.py deleted file mode 100644 index 1dc982bf..00000000 --- a/tests/alpha/function.py +++ /dev/null @@ -1,160 +0,0 @@ -# function.py --- - -import numpy as np -import sys -import moose - -simtime = 1.0 -plot_ = False -if plot_: - import matplotlib.pyplot as plt - -def example(): - """Function objects can be used to evaluate expressions with arbitrary - number of variables and constants. We can assign expression of the - form:: - - f(c0, c1, ..., cM, x0, x1, ..., xN, y0,..., yP ) - - where `c_i`'s are constants and `x_i`'s and `y_i`'s are variables. - - The constants must be defined before setting the expression and - variables are connected via messages. The constants can have any - name, but the variable names must be of the form x{i} or y{i} - where i is increasing integer starting from 0. - - The `x_i`'s are field elements and you have to set their number - first (function.x.num = N). Then you can connect any source field - sending out double to the 'input' destination field of the - `x[i]`. - - The `y_i`'s are useful when the required variable is a value field - and is not available as a source field. In that case you connect - the `requestOut` source field of the function element to the - `get{Field}` destination field on the target element. The `y_i`'s - are automatically added on connecting. Thus, if you call:: - - moose.connect(function, 'requestOut', a, 'getSomeField') - moose.connect(function, 'requestOut', b, 'getSomeField') - - then ``a.someField`` will be assigned to ``y0`` and - ``b.someField`` will be assigned to ``y1``. - - In this example we evaluate the expression: ``z = c0 * exp(c1 * - x0) * cos(y0)`` - - with x0 ranging from -1 to +1 and y0 ranging from -pi to - +pi. These values are stored in two stimulus tables called xtab - and ytab respectively, so that at each timestep the next values of - x0 and y0 are assigned to the function. - - Along with the value of the expression itself we also compute its - derivative with respect to y0 and its derivative with respect to - time (rate). The former uses a five-point stencil for the - numerical differentiation and has a glitch at y=0. The latter uses - backward difference divided by dt. - - Unlike Func class, the number of variables and constants are - unlimited in Function and you can set all the variables via - messages. - - """ - demo = moose.Neutral('/model') - function = moose.Function('/model/function') - function.c['c0'] = 1.0 - function.c['c1'] = 2.0 - function.x.num = 1 - function.expr = 'c0 * exp(c1*x0) * cos(y0) + sin(t)' - # mode 0 - evaluate function value, derivative and rate - # mode 1 - just evaluate function value, - # mode 2 - evaluate derivative, - # mode 3 - evaluate rate - function.mode = 0 - function.independent = 'y0' - nsteps = 10000 - xarr = np.linspace(0.0, 1.0, nsteps) - # Stimulus tables allow you to store sequences of numbers which - # are delivered via the 'output' message at each time step. This - # is a placeholder and in real scenario you will be using any - # sourceFinfo that sends out a double value. - input_x = moose.StimulusTable('/xtab') - input_x.vector = xarr - input_x.startTime = 0.0 - input_x.stepPosition = xarr[0] - input_x.stopTime = simtime - moose.connect(input_x, 'output', function.x[0], 'input') - - yarr = np.linspace(-np.pi, np.pi, nsteps) - input_y = moose.StimulusTable('/ytab') - input_y.vector = yarr - input_y.startTime = 0.0 - input_y.stepPosition = yarr[0] - input_y.stopTime = simtime - moose.connect(function, 'requestOut', input_y, 'getOutputValue') - - # data recording - result = moose.Table('/ztab') - moose.connect(result, 'requestOut', function, 'getValue') - derivative = moose.Table('/zprime') - moose.connect(derivative, 'requestOut', function, 'getDerivative') - rate = moose.Table('/dz_by_dt') - moose.connect(rate, 'requestOut', function, 'getRate') - x_rec = moose.Table('/xrec') - moose.connect(x_rec, 'requestOut', input_x, 'getOutputValue') - y_rec = moose.Table('/yrec') - moose.connect(y_rec, 'requestOut', input_y, 'getOutputValue') - - dt = simtime/nsteps - for ii in range(32): - moose.setClock(ii, dt) - moose.reinit() - moose.start(simtime) - - # Uncomment the following lines and the import matplotlib.pyplot as plt on top - # of this file to display the plot. - if plot_: - plt.plot(x_rec.vector, result.vector, 'r-', label='z = {}'.format(function.expr)) - plt.subplot(4,1,1) - z = function.c['c0'] * np.exp(function.c['c1'] * xarr) * np.cos(yarr) + np.sin(np.arange(len(xarr)) * dt) - zz = result.vector[1:] - err = z[1:] - zz[1:] - assert (np.abs(err) <= 0.05).all(), err - assert (np.mean(err) <= 0.001), np.mean(err) - - if plot_: - plt.plot(xarr, z, 'b--', label='numpy computed') - plt.xlabel('x') - plt.ylabel('z') - plt.legend() - - if plot_: - plt.subplot(4,1,2) - plt.plot(y_rec.vector, derivative.vector, 'r-', label='dz/dy0') - # derivatives computed by putting x values in the analytical formula - dzdy = function.c['c0'] * np.exp(function.c['c1'] * xarr) * (- np.sin(yarr)) - err = np.abs(dzdy - derivative.vector[1:]) - assert (err < 1e-2).all(), err - assert (np.mean(err) < 1e-3), np.mean(err) - - if plot_: - plt.plot(yarr, dzdy, 'b--', label='numpy computed') - plt.xlabel('y') - plt.ylabel('dz/dy') - plt.legend() - - if plot_: - plt.subplot(4,1,3) - # *** BEWARE *** The first two entries are spurious. Entry 0 is - # *** from reinit sending out the defaults. Entry 2 is because - # *** there is no lastValue for computing real forward difference. - plt.plot(np.arange(2, len(rate.vector), 1) * dt, rate.vector[2:], 'r-', label='dz/dt') - dzdt = np.diff(z)/dt - plt.plot(np.arange(0, len(dzdt), 1.0) * dt, dzdt, 'b--', label='numpy computed') - plt.xlabel('t') - plt.ylabel('dz/dt') - plt.legend() - plt.tight_layout() - plt.show() - -if __name__ == '__main__': - example() diff --git a/tests/python/chem_models/00001-sbml-l3v1.xml b/tests/data/00001-sbml-l3v1.xml similarity index 100% rename from tests/python/chem_models/00001-sbml-l3v1.xml rename to tests/data/00001-sbml-l3v1.xml diff --git a/tests/python/chem_models/19085.cspace b/tests/data/19085.cspace similarity index 100% rename from tests/python/chem_models/19085.cspace rename to tests/data/19085.cspace diff --git a/tests/python/chem_models/Anno_acc2.g b/tests/data/Anno_acc2.g similarity index 100% rename from tests/python/chem_models/Anno_acc2.g rename to tests/data/Anno_acc2.g diff --git a/tests/python/genesis/acc11.g b/tests/data/acc11.g similarity index 100% rename from tests/python/genesis/acc11.g rename to tests/data/acc11.g diff --git a/tests/data/acc27.g b/tests/data/acc27.g deleted file mode 100644 index c2105ce7..00000000 --- a/tests/data/acc27.g +++ /dev/null @@ -1,325 +0,0 @@ -//genesis -// kkit Version 8 flat dumpfile - -// Saved on Tue Jan 22 17:41:13 2002 - -include kkit {argv 1} - -FASTDT = 5e-05 -SIMDT = 0.005 -CONTROLDT = 10 -PLOTDT = 5 -MAXTIME = 6000 -TRANSIENT_TIME = 2 -VARIABLE_DT_FLAG = 1 -DEFAULT_VOL = 1.6667e-21 -VERSION = 8.0 -setfield /file/modpath value /home2/bhalla/scripts/modules -kparms - -//genesis - -initdump -version 3 -ignoreorphans 1 -simobjdump table input output alloced step_mode stepsize x y z -simobjdump xtree path script namemode sizescale -simobjdump xcoredraw xmin xmax ymin ymax -simobjdump xtext editable -simobjdump xgraph xmin xmax ymin ymax overlay -simobjdump xplot pixflags script fg ysquish do_slope wy -simobjdump group xtree_fg_req xtree_textfg_req plotfield expanded movealone \ - link savename file version md5sum mod_save_flag x y z -simobjdump kpool CoTotal CoInit Co n nInit nTotal nMin vol slave_enable notes \ - xtree_fg_req xtree_textfg_req x y z -simobjdump kreac kf kb notes xtree_fg_req xtree_textfg_req x y z -simobjdump kenz CoComplexInit CoComplex nComplexInit nComplex vol k1 k2 k3 \ - keepconc usecomplex notes xtree_fg_req xtree_textfg_req link x y z -simobjdump stim level1 width1 delay1 level2 width2 delay2 baselevel trig_time \ - trig_mode notes xtree_fg_req xtree_textfg_req is_running x y z -simobjdump xtab input output alloced step_mode stepsize notes editfunc \ - xtree_fg_req xtree_textfg_req baselevel last_x last_y is_running x y z -simobjdump kchan perm gmax Vm is_active use_nernst notes xtree_fg_req \ - xtree_textfg_req x y z -simobjdump proto x y z -simobjdump linkinfo xtree_fg_req xtree_textfg_req uplink downlink x y z -simobjdump uplink xtree_fg_req xtree_textfg_req x y z -simobjdump downlink xtree_fg_req xtree_textfg_req x y z -simobjdump mirror notes xtree_fg_req x y z -simundump group /kinetics/MAPK 0 yellow black x 0 0 "" MAPK \ - /home2/bhalla/scripts/modules/MAPK_0.g 0 0 0 1 10 0 -simundump kpool /kinetics/MAPK/MAPK 0 1 0.3 0.3 0.3 0.3 1 0 1 0 "" 35 yellow \ - -8 -7 0 -simundump kpool /kinetics/MAPK/MKKK 0 0.1 0.1 0.1 0.1 0.1 0.1 0 1 0 "" 16 \ - yellow -8 5 0 -simundump kpool /kinetics/MAPK/MKK 0 0.3 0.3 0.3 0.3 0.3 0.3 0 1 0 "" 60 \ - yellow -8 -1 0 -simundump kpool /kinetics/MAPK/int1 0 1 0.001 0.001 0.001 0.001 1 0 1 0 "" 30 \ - yellow -4 4 0 -simundump kenz /kinetics/MAPK/int1/2 0 0 0 0 0 0.001 156.25 1 0.25 0 1 "" red \ - 30 "" -4 5 0 -simundump kpool /kinetics/MAPK/MKKK-P 0 0.05 0 0 0 0 0.05 0 1 0 "" 51 yellow \ - 0 5 0 -simundump kenz /kinetics/MAPK/MKKK-P/3 0 0 0 0 0 0.001 8.3333 0.1 0.025 0 1 \ - "" red 51 "" -4 2 0 -simundump kenz /kinetics/MAPK/MKKK-P/4 0 0 0 0 0 0.001 8.3333 0.1 0.025 0 1 \ - "" red 51 "" 4 2 0 -simundump kpool /kinetics/MAPK/int3 0 1 0.001 0.001 0.001 0.001 1 0 1 0 "" \ - blue yellow -4 -2 0 -simundump kenz /kinetics/MAPK/int3/6 0 0 0 0 0 0.001 250 3 0.75 0 1 "" red \ - blue "" -4 -1 0 -simundump kpool /kinetics/MAPK/int5 0 1 0.001 0.001 0.001 0.001 1 0 1 0 "" 1 \ - yellow -4 -8 0 -simundump kenz /kinetics/MAPK/int5/10 0 0 0 0 0 0.001 166.67 2 0.5 0 1 "" red \ - 1 "" -4 -7 0 -simundump kpool /kinetics/MAPK/MKK-P 0 0.1 0 0 0 0 0.1 0 1 0 "" 5 yellow 0 -1 \ - 0 -simundump kpool /kinetics/MAPK/MAPK-P 0 0.1 0 0 0 0 0.1 0 1 0 "" 55 yellow 0 \ - -7 0 -simundump kpool /kinetics/MAPK/int2 0 1 0.001 0.001 0.001 0.001 1 0 1 0 "" 2 \ - yellow 4 -2 0 -simundump kenz /kinetics/MAPK/int2/5 0 0 0 0 0 0.001 250 3 0.75 0 1 "" red 2 \ - "" 4 -1 0 -simundump kpool /kinetics/MAPK/int4 0 1 0.001 0.001 0.001 0.001 1 0 1 0 "" 17 \ - yellow 4 -8 0 -simundump kenz /kinetics/MAPK/int4/9 0 0 0 0 0 0.001 166.67 2 0.5 0 1 "" red \ - 17 "" 4 -7 0 -simundump kpool /kinetics/MAPK/Ras-MKKKK 0 0.1 0.001 0.001 0.001 0.001 0.1 0 \ - 1 0 "" 47 yellow 6 8 0 -simundump kenz /kinetics/MAPK/Ras-MKKKK/1 0 0 0 0 0 0.001 1250 10 2.5 0 1 "" \ - red 47 "" -4 8 0 -simundump kpool /kinetics/MAPK/inactiveRas-MKKK 0 0 0 0 0 0 0 0 1 0 "" 30 \ - yellow 11 8 0 -simundump kreac /kinetics/MAPK/Neg_feedback 0 1 0.009 "" white yellow 11 2 0 -simundump kpool /kinetics/MAPK/MKK-PP 0 0.1 0 0 0 0 0.1 0 1 0 "" 60 yellow 8 \ - -1 0 -simundump kenz /kinetics/MAPK/MKK-PP/7 0 0 0 0 0 0.001 8.3333 0.1 0.025 0 1 \ - "" red 60 "" -4 -4 0 -simundump kenz /kinetics/MAPK/MKK-PP/8 0 0 0 0 0 0.001 8.3333 0.1 0.025 0 1 \ - "" red 60 "" 4 -4 0 -simundump kpool /kinetics/MAPK/MAPK-PP 0 0.1 0 0 0 0 0.1 0 1 0 "" 46 yellow 8 \ - -7 0 -simundump xgraph /graphs/conc1 0 0 6000 0 0.3 0 -simundump xgraph /graphs/conc2 0 0 6000 4.5157e-05 0.3 0 -simundump xplot /graphs/conc1/MAPK-PP.Co 3 524288 \ - "delete_plot.w ; edit_plot.D " 46 0 0 1 -simundump xplot /graphs/conc1/MAPK.Co 3 524288 \ - "delete_plot.w ; edit_plot.D " 35 0 0 1 -simundump xplot /graphs/conc2/Ras-MKKKK.Co 3 524288 \ - "delete_plot.w ; edit_plot.D " 47 0 0 1 -simundump xplot /graphs/conc2/MAPK.Co 3 524288 \ - "delete_plot.w ; edit_plot.D " 35 0 0 1 -simundump xplot /graphs/conc2/MKKK.Co 3 524288 \ - "delete_plot.w ; edit_plot.D " 16 0 0 1 -simundump xplot /graphs/conc2/MKK.Co 3 524288 \ - "delete_plot.w ; edit_plot.D " 60 0 0 1 -simundump xgraph /moregraphs/conc3 0 0 6000 0 1 0 -simundump xgraph /moregraphs/conc4 0 0 6000 0 1 0 -simundump xcoredraw /edit/draw 0 -6.5262 17.834 -8.7578 11.542 -simundump xtree /edit/draw/tree 0 \ - /kinetics/#[],/kinetics/#[]/#[],/kinetics/#[]/#[]/#[][TYPE!=proto],/kinetics/#[]/#[]/#[][TYPE!=linkinfo]/##[] \ - "edit_elm.D ; drag_from_edit.w " auto 0.6 -simundump xtext /file/notes 0 1 -xtextload /file/notes \ -"22 Jan 2002" \ -" " \ -" This model is based on Kholodenko, B.N." \ -" Eur. J. Biochem. 267, 1583-1588(2000)" \ -"" -addmsg /kinetics/MAPK/MKK-PP/7 /kinetics/MAPK/MAPK REAC sA B -addmsg /kinetics/MAPK/int5/10 /kinetics/MAPK/MAPK MM_PRD pA -addmsg /kinetics/MAPK/Ras-MKKKK/1 /kinetics/MAPK/MKKK REAC sA B -addmsg /kinetics/MAPK/int1/2 /kinetics/MAPK/MKKK MM_PRD pA -addmsg /kinetics/MAPK/MKKK-P/3 /kinetics/MAPK/MKK REAC sA B -addmsg /kinetics/MAPK/int3/6 /kinetics/MAPK/MKK MM_PRD pA -addmsg /kinetics/MAPK/int1 /kinetics/MAPK/int1/2 ENZYME n -addmsg /kinetics/MAPK/MKKK-P /kinetics/MAPK/int1/2 SUBSTRATE n -addmsg /kinetics/MAPK/Ras-MKKKK/1 /kinetics/MAPK/MKKK-P MM_PRD pA -addmsg /kinetics/MAPK/int1/2 /kinetics/MAPK/MKKK-P REAC sA B -addmsg /kinetics/MAPK/MKKK-P /kinetics/MAPK/MKKK-P/3 ENZYME n -addmsg /kinetics/MAPK/MKK /kinetics/MAPK/MKKK-P/3 SUBSTRATE n -addmsg /kinetics/MAPK/MKKK-P /kinetics/MAPK/MKKK-P/4 ENZYME n -addmsg /kinetics/MAPK/MKK-P /kinetics/MAPK/MKKK-P/4 SUBSTRATE n -addmsg /kinetics/MAPK/int3 /kinetics/MAPK/int3/6 ENZYME n -addmsg /kinetics/MAPK/MKK-P /kinetics/MAPK/int3/6 SUBSTRATE n -addmsg /kinetics/MAPK/int5 /kinetics/MAPK/int5/10 ENZYME n -addmsg /kinetics/MAPK/MAPK-P /kinetics/MAPK/int5/10 SUBSTRATE n -addmsg /kinetics/MAPK/MKKK-P/4 /kinetics/MAPK/MKK-P REAC sA B -addmsg /kinetics/MAPK/MKKK-P/3 /kinetics/MAPK/MKK-P MM_PRD pA -addmsg /kinetics/MAPK/int3/6 /kinetics/MAPK/MKK-P REAC sA B -addmsg /kinetics/MAPK/int2/5 /kinetics/MAPK/MKK-P MM_PRD pA -addmsg /kinetics/MAPK/MKK-PP/8 /kinetics/MAPK/MAPK-P REAC sA B -addmsg /kinetics/MAPK/MKK-PP/7 /kinetics/MAPK/MAPK-P MM_PRD pA -addmsg /kinetics/MAPK/int5/10 /kinetics/MAPK/MAPK-P REAC sA B -addmsg /kinetics/MAPK/int4/9 /kinetics/MAPK/MAPK-P MM_PRD pA -addmsg /kinetics/MAPK/int2 /kinetics/MAPK/int2/5 ENZYME n -addmsg /kinetics/MAPK/MKK-PP /kinetics/MAPK/int2/5 SUBSTRATE n -addmsg /kinetics/MAPK/int4 /kinetics/MAPK/int4/9 ENZYME n -addmsg /kinetics/MAPK/MAPK-PP /kinetics/MAPK/int4/9 SUBSTRATE n -addmsg /kinetics/MAPK/Neg_feedback /kinetics/MAPK/Ras-MKKKK REAC A B -addmsg /kinetics/MAPK/Ras-MKKKK /kinetics/MAPK/Ras-MKKKK/1 ENZYME n -addmsg /kinetics/MAPK/MKKK /kinetics/MAPK/Ras-MKKKK/1 SUBSTRATE n -addmsg /kinetics/MAPK/Neg_feedback /kinetics/MAPK/inactiveRas-MKKK REAC B A -addmsg /kinetics/MAPK/MAPK-PP /kinetics/MAPK/Neg_feedback SUBSTRATE n -addmsg /kinetics/MAPK/Ras-MKKKK /kinetics/MAPK/Neg_feedback SUBSTRATE n -addmsg /kinetics/MAPK/inactiveRas-MKKK /kinetics/MAPK/Neg_feedback PRODUCT n -addmsg /kinetics/MAPK/MKKK-P/4 /kinetics/MAPK/MKK-PP MM_PRD pA -addmsg /kinetics/MAPK/int2/5 /kinetics/MAPK/MKK-PP REAC sA B -addmsg /kinetics/MAPK/MKK-PP /kinetics/MAPK/MKK-PP/7 ENZYME n -addmsg /kinetics/MAPK/MAPK /kinetics/MAPK/MKK-PP/7 SUBSTRATE n -addmsg /kinetics/MAPK/MKK-PP /kinetics/MAPK/MKK-PP/8 ENZYME n -addmsg /kinetics/MAPK/MAPK-P /kinetics/MAPK/MKK-PP/8 SUBSTRATE n -addmsg /kinetics/MAPK/MKK-PP/8 /kinetics/MAPK/MAPK-PP MM_PRD pA -addmsg /kinetics/MAPK/int4/9 /kinetics/MAPK/MAPK-PP REAC sA B -addmsg /kinetics/MAPK/Neg_feedback /kinetics/MAPK/MAPK-PP REAC A B -addmsg /kinetics/MAPK/MAPK-PP /graphs/conc1/MAPK-PP.Co PLOT Co *MAPK-PP.Co *46 -addmsg /kinetics/MAPK/MAPK /graphs/conc1/MAPK.Co PLOT Co *MAPK.Co *35 -addmsg /kinetics/MAPK/Ras-MKKKK /graphs/conc2/Ras-MKKKK.Co PLOT Co *Ras-MKKKK.Co *47 -addmsg /kinetics/MAPK/MAPK /graphs/conc2/MAPK.Co PLOT Co *MAPK.Co *35 -addmsg /kinetics/MAPK/MKKK /graphs/conc2/MKKK.Co PLOT Co *MKKK.Co *16 -addmsg /kinetics/MAPK/MKK /graphs/conc2/MKK.Co PLOT Co *MKK.Co *60 -enddump -// End of dump - -call /kinetics/MAPK/notes LOAD \ -"This is the oscillatory MAPK model from Kholodenko 2000" \ -"Eur J. Biochem 267:1583-1588" \ -"The original model is formulated in terms of idealized" \ -"Michaelis-Menten enzymes and the enzyme-substrate complex" \ -"concentrations are therefore assumed negligible. The" \ -"current implementation of the model uses explicit enzyme" \ -"reactions involving substrates and is therefore an" \ -"approximation to the Kholodenko model. The approximation is" \ -"greatly improved if the enzyme is flagged as Available" \ -"which is an option in Kinetikit. This flag means that the" \ -"enzyme protein concentration is not reduced even when it" \ -"is involved in a complex. However, the substrate protein" \ -"continues to participate in enzyme-substrate complexes" \ -"and its concentration is therefore affected. Overall," \ -"this model works almost the same as the Kholodenko model" \ -"but the peak MAPK-PP amplitudes are a little reduced and" \ -"the period of oscillations is about 10% longer." \ -"If the enzymes are not flagged as Available then the" \ -"oscillations commence only when the Km for enzyme 1" \ -"is set to 0.1 uM." -call /kinetics/MAPK/MAPK/notes LOAD \ -"The total concn. of MAPK is 300nM " \ -"from" \ -"Kholodenko, 2000." -call /kinetics/MAPK/MKKK/notes LOAD \ -"The total concn. of MKKK is 100nM " \ -"from" \ -"Kholodenko, 2000" -call /kinetics/MAPK/MKK/notes LOAD \ -"The total concn. of MKK is 300nM " \ -"from" \ -"Kholodenko,2000" -call /kinetics/MAPK/int1/notes LOAD \ -"This is the intermediate enzyme which catalyses the " \ -"dephosphorylation of MKKK-P to MKKK. The concentration" \ -"is set to 1 nM based on" \ -"from" \ -"Kholodenko, 2000" -call /kinetics/MAPK/int1/2/notes LOAD \ -"Km is 8nM and Vmax is 0.25nM.s-1 " \ -"from" \ -"Kholodenko, 2000." -call /kinetics/MAPK/MKKK-P/notes LOAD \ -"This is the phosphorylated form of MKKK which converts MKK" \ -"to MKK-P and then to MKK-PP" \ -"from" \ -"Kholodenko, 2000." -call /kinetics/MAPK/MKKK-P/3/notes LOAD \ -"Km is 15 nM and Vmax is 0.025s-1" \ -"from" \ -"Kholodenko, 2000" -call /kinetics/MAPK/MKKK-P/4/notes LOAD \ -"Km is 15nM and Vmax is 0.025s-1" \ -"from " \ -"Kholodenko, 2000." -call /kinetics/MAPK/int3/notes LOAD \ -"This intermediate enzyme catalyses the dephosphorylation of" \ -"MKK-P to MKK. The concentration is 1nM" \ -"from" \ -"Kholodenko, 2000" -call /kinetics/MAPK/int3/6/notes LOAD \ -"The Km is 15nM and the Vmax is 0.75nM.s-1" \ -"from" \ -"Kholodenko 2000." -call /kinetics/MAPK/int5/notes LOAD \ -"This catalyses the conversion of MAPK-P to MAPK. The " \ -"concenration is 1nM." \ -"from" \ -"Kholodenko, 2000" -call /kinetics/MAPK/int5/10/notes LOAD \ -"The Km is 15nM and Vmax is 0.5nM.s-1" \ -"from" \ -"Kholodenko, 2000" -call /kinetics/MAPK/MKK-P/notes LOAD \ -"This is the single phoshorylated form of MKK." \ -"from" \ -"Kholodenko, 2000." -call /kinetics/MAPK/MAPK-P/notes LOAD \ -"This is the single phopshorylated form of MAPK" \ -"from" \ -"Kholodenko, 2000." -call /kinetics/MAPK/int2/notes LOAD \ -"This intermediate enzyme which catalyses the dephosphorylation of" \ -"MKK-PP to MKK-P. The concentration is 1nM." \ -"from" \ -"Kholodenko, 2000" -call /kinetics/MAPK/int2/5/notes LOAD \ -"The Km is 15nM and Vmax is 0.75nM.s-1 " \ -"from" \ -"Kholodenko, 2000" \ -"" -call /kinetics/MAPK/int4/notes LOAD \ -"This intermediate enzyme catalyses the dephosphorylation of" \ -"MAPK-PP to MAPK-P. The concentration is 1nM." \ -"from" \ -"Kholodenko, 2000" -call /kinetics/MAPK/int4/9/notes LOAD \ -"The Km is 15nM and Vmax is 0.5nM.s-1 " \ -"from" \ -"Kholodenko, 2000" -call /kinetics/MAPK/Ras-MKKKK/notes LOAD \ -"The concn. of Ras-MKKKK* is set to 1 nM implicitly" \ -"from" \ -"Kholodenko, 2000" -call /kinetics/MAPK/Ras-MKKKK/1/notes LOAD \ -"The Km is 10nM and Vmax is 2.5nM sec^-1. We assume that" \ -"there is 1 nM of the Ras-MKKKK." \ -"From Kholodenko, 2000." \ -"" \ -"If the enzymes are not flagged as Available, then this" \ -"Km should be set to 0.1 to obtain oscillations." -call /kinetics/MAPK/inactiveRas-MKKK/notes LOAD \ -"This is the inactive form of Ras-MKKK. Based on the" \ -"reaction scheme from Kholodenko 2000, this is equivalent" \ -"to a binding of the MAPK-PP to the Ras. The amount of" \ -"Ras in the model is small enough that negligible amounts" \ -"of MAPK are involved in this reaction. So it is a fair" \ -"approximation to the negative feedback mechanism from" \ -"Kholodenko, 2000." -call /kinetics/MAPK/Neg_feedback/notes LOAD \ -"From Kholodenko, 2000 Eur J Biochem 267" \ -"the Kd is 9 nM. We use a rather fast Kf of 1/sec/uM" \ -"so that equilibrium is maintained." \ -"" -call /kinetics/MAPK/MKK-PP/notes LOAD \ -"This is the double phosphorylated and active form of MKK" \ -"from" \ -"Kholodenko, 2000" -call /kinetics/MAPK/MKK-PP/7/notes LOAD \ -"The Km is 15nM which is 0.015uM Vmax is 0.025s-1" \ -"from" \ -"Kholodenko, 2000." \ -"" -call /kinetics/MAPK/MKK-PP/8/notes LOAD \ -"The Km is 15nM which is 0.015uM and Vmax is 0.025s-1" \ -"from" \ -"Kholodenko, 2000" \ -"" -call /kinetics/MAPK/MAPK-PP/notes LOAD \ -"This is the double phosphorylated and active form of MAPK." \ -"from" \ -"Kholodenko, 2000." -complete_loading diff --git a/tests/data/c_m.xml b/tests/data/c_m.xml new file mode 100644 index 00000000..67f79aff --- /dev/null +++ b/tests/data/c_m.xml @@ -0,0 +1,6225 @@ + + + + + + 100.0 + gsl + 0.1 + 1.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CubeMesh + False + + + + + + + + + 82.054808474 + 780.640187987 + 27 + black + 0.0 + 0.0 + + + + + + + We should note that binding to IBAR halts PIP2 lateral diffusion +Zhao et al., Cell reports, 2013 + + + + + 84.6967031645 + 581.30346608 + 55 + black + 0.0 + 0.0 + + + + + + + 252.577668365 + 586.881444698 + 7 + black + 0.0 + 0.0 + + + + + + + 60.4976451174 + 542.257615756 + (210, 180, 140, 255) + black + 0.0 + 0.0 + + + + + + + This should have diffusion proportional to the curvature formed. + + + + + 178.265340304 + 575.210832186 + (127, 255, 0, 255) + black + 0.0 + 0.0 + + + + + + + 269.52753387 + 560.143225794 + (0, 250, 154, 255) + black + 0.0 + 0.0 + + + + + + + 271.308751511 + 508.385926879 + (255, 192, 203, 255) + black + 0.0 + 0.0 + + + + + + + 100.342714 + 718.331969586 + (169, 169, 169, 255) + black + 0.0 + 0.0 + + + + + + + 21.5810650017 + 738.468217562 + (255, 140, 0, 255) + black + 0.0 + 0.0 + + + + + + + 195.311383016 + 793.060718711 + (238, 130, 238, 255) + black + 0.0 + 0.0 + + + + + + + 119.289422948 + 618.620804733 + (124, 252, 0, 255) + black + 0.0 + 0.0 + + + + + + + 308.003574477 + 697.371847707 + (255, 69, 0, 255) + black + 0.0 + 0.0 + + + + + + + 239.721918778 + 740.275856684 + (128, 128, 128, 255) + black + 0.0 + 0.0 + + + + + + + 262.243128562 + 472.093702675 + (186, 85, 211, 255) + black + 0.0 + 0.0 + + + + + + + 50.5585828495 + 467.373564681 + (250, 164, 96, 255) + black + 0.0 + 0.0 + + + + + + + 861.789008537 + 303.904974141 + 23 + black + 0.0 + 0.0 + + + + + + + 563.247908285 + 285.873177048 + 47 + black + 0.0 + 0.0 + + + + + + + Basal CaMKII is set to zero here. + + + + + 943.450846241 + 367.267861833 + blue + black + 0.0 + 0.0 + + + + + + + 575.775841171 + 14.675557689 + 47 + black + 0.0 + 0.0 + + + + + + + 558.305223613 + 92.9823140887 + 50 + black + 0.0 + 0.0 + + + + + + + 714.653016471 + 0.0 + 57 + black + 0.0 + 0.0 + + + + + + + 925.057551214 + 116.576217615 + 62 + black + 0.0 + 0.0 + + + + + + + 938.174718849 + 257.316211323 + 30 + black + 0.0 + 0.0 + + + + + + + 811.348343649 + 195.98790117 + 0 + black + 0.0 + 0.0 + + + + + + + 941.770653792 + 60.4464082609 + blue + black + 0.0 + 0.0 + + + + + + + 783.453261365 + 252.333812963 + 12 + black + 0.0 + 0.0 + + + + + + + Guanine nucleotide exchange factor. This activates raf by exchanging bound GDP with GTP. I have left the GDP/GTP out of this reaction, it would be trivial to put them in. See Boguski _and McCormick. Possible candidate molecules: RasGRF, smgGDS, Vav (in dispute). rasGRF: Kcat= 1.2/min Km = 680 nM smgGDS: Kcat: 0.37 /min, Km = 220 nM. vav: Turnover up over baseline by 10X, + + + + + 893.312460133 + 490.139103064 + hotpink + black + 0.0 + 0.0 + + + + + + + Assume that SoS is present only at 50 nM. Revised to 100 nM to get equil to experimentally known levels. + + + + + 722.639329571 + 483.73672973 + hotpink + black + 0.0 + 0.0 + + + + + + + phosphorylated and thereby activated form of GEF. See, e.g. Orita et al JBC 268:34 25542-25546 1993, Gulbins et al. It is not clear whether there is major specificity for tyr or ser/thr. + + + + + 830.118679379 + 668.640050125 + hotpink + black + 0.0 + 0.0 + + + + + + + Only a very small fraction (7% unstim, 15% stim) of ras is GTP-bound. Gibbs et al JBC 265(33) 20437 + + + + + 728.054699509 + 619.416298407 + orange + black + 0.0 + 0.0 + + + + + + + GDP bound form. See Rosen et al Neuron 12 1207-1221 June 1994. the activation loop is based on Boguski and McCormick Nature 366 643-654 93 Assume Ras is present at about the same level as craf-1, 0.2 uM. Hallberg et al JBC 269:6 3913-3916 1994 estimate upto 5-10% of cellular Raf is assoc with Ras. Given that only 5-10% of Ras is GTP-bound, we need similar amounts of Ras as Raf. + + + + + 826.746248119 + 609.197165775 + pink + black + 0.0 + 0.0 + + + + + + + 941.375174316 + 604.040730637 + red + black + 0.0 + 0.0 + + + + + + + GTPase-activating proteins. See Boguski and McCormick. Turn off Ras by helping to hydrolyze bound GTP. This one is probably NF1, ie., Neurofibromin as it is inhibited by AA and lipids, and expressed in neural cells. p120-GAP is also a possible candidate, but is less regulated. Both may exist at similar levels. See Eccleston et al JBC 268(36) pp27012-19 Level=.002 + + + + + 937.082206049 + 641.3947714 + red + black + 0.0 + 0.0 + + + + + + + Phosphorylation-inactivated form of GEF. See Hordijk et al JBC 269:5 3534-3538 1994 and Buregering et al EMBO J 12:11 4211-4220 1993 + + + + + 906.400382324 + 532.443935453 + hotpink + black + 0.0 + 0.0 + + + + + + + See Farnsworth et al Nature 376 524-527 1995 + + + + + 686.128924867 + 670.840957124 + pink + black + 0.0 + 0.0 + + + + + + + There is a LOT of this in the cell: upto 1% of total protein mass. (Alberts et al) Say 25 uM. Meyer et al Science 256 1199-1202 1992 refer to studies saying it is comparable to CaMK levels. + + + + + 263.339129214 + 382.042765024 + pink + black + 0.0 + 0.0 + + + + + + + 336.15293842 + 382.042765024 + hotpink + black + 0.0 + 0.0 + + + + + + + This is the intermediate where the TR2 end (the high-affinity end) has bound the Ca but the TR1 end has not. + + + + + 311.881668685 + 382.042765024 + pink + black + 0.0 + 0.0 + + + + + + + This is the intermediate where the TR2 end (the high-affinity end) has bound the Ca but the TR1 end has not. + + + + + 287.61039895 + 382.042765024 + pink + black + 0.0 + 0.0 + + + + + + + 445.697693906 + 330.103849468 + blue + black + 0.0 + 0.0 + + + + + + + 214.796589742 + 440.17414941 + blue + black + 0.0 + 0.0 + + + + + + + 509.789964318 + 444.314617139 + 29 + black + 0.0 + 0.0 + + + + + + + 384.470852393 + 251.039430664 + 59 + black + 0.0 + 0.0 + + + + + + + 203.497351617 + 340.458112177 + 1 + black + 0.0 + 0.0 + + + + + + + Strack et al JBC 1997 show that PP2A is the primary phosphatase acting on CaMKII in the bulk. + + + + + 258.102904559 + 119.06166857 + 62 + black + 0.0 + 0.0 + + + + + + + 63.1507545838 + 265.347792649 + 1 + black + 0.0 + 0.0 + + + + + + + 129.880212794 + 265.347792649 + blue + black + 0.0 + 0.0 + + + + + + + 331.723084488 + 11.1452450929 + red + black + 0.0 + 0.0 + + + + + + + 178.995167287 + 84.6949116062 + (0, 128, 0, 255) + black + 0.0 + 0.0 + + + + + + + 66.5452425339 + 83.1804198323 + (222, 184, 135, 255) + black + 0.0 + 0.0 + + + + + + + 187.140890711 + 206.24855269 + (255, 165, 0, 255) + black + 0.0 + 0.0 + + + + + + + 73.6425565344 + 202.924356376 + (0, 139, 139, 255) + black + 0.0 + 0.0 + + + + + + + 391.729242315 + 488.47079276 + (75, 0, 130, 255) + black + 0.0 + 0.0 + + + + + + + 726.614566544 + 194.712247731 + red + black + 0.0 + 0.0 + + + + + + + 114.524249357 + 8.82869365086 + (222, 184, 135, 255) + black + 0.0 + 0.0 + + + + + + + 580.844700833 + 557.082234455 + #005500 + black + 0.0 + 0.0 + + + + + + + compared with AKT in Tolias, 2005. Conc of AKT is given as 0.2 uM in Docqs. + + + + + 470.236830911 + 586.716836678 + (216, 191, 216, 255) + black + 0.0 + 0.0 + + + + + + + 527.21621877 + 760.21030932 + (219, 112, 147, 255) + black + 0.0 + 0.0 + + + + + + + 3.6797727292 + 650.898253291 + (0, 255, 255, 255) + black + 0.0 + 0.0 + + + + + + + 465.964109171 + 544.365064857 + (169, 169, 169, 255) + black + 0.0 + 0.0 + + + + + + + 195.069471089 + 661.469128367 + (128, 0, 128, 255) + black + 0.0 + 0.0 + + + + + + + 124.615314557 + 459.544033601 + (221, 160, 221, 255) + black + 0.0 + 0.0 + + + + + + + 316.688004514 + 521.237002317 + (255, 20, 147, 255) + black + 0.0 + 0.0 + + + + + + + 256.889860357 + 791.59312537 + (34, 139, 34, 255) + black + 0.0 + 0.0 + + + + + + + 300.0 + 673.110285006 + (205, 92, 92, 255) + black + 0.0 + 0.0 + + + + + + + 17.3816589648 + 787.371370077 + (0, 255, 0, 255) + black + 0.0 + 0.0 + + + + + + + 634.0 + 743.494423792 + (178, 34, 34, 255) + black + 0.0 + 0.0 + + + + + + + 1.03331842624 + 549.47967556 + (32, 178, 170, 255) + black + 0.0 + 0.0 + + + + + + + 47.9149166959 + 507.0 + (199, 21, 133, 255) + black + 0.0 + 0.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CaMKII_thr286_503_0_ + CaMKII_p_p_p_509_0_ + basal_CaMKII_497_0_ + + + + + + + + actCaMKII_513_0_ + CaMKII_505_0_ + CaMKII_thr305_507_0_ + + + + + + + + CaMKII_thr286_CaM_499_0_ + CaMKII_thr286_503_0_ + + + + + + + + CaMKII_thr286_CaM_499_0_ + CaMKII_CaM_501_0_ + + + + + + + + CaMKII_thr286_CaM_499_0_ + CaMKII_CaM_501_0_ + tot_auto_545_0_ + + + + + + + + + sudhaharan et al., Kd + + + + + 53.4186504553 + 701.950479714 + white + black + + + + + + + + + + + + + dend_455_0_ * Reac_663_0__Kf * IRSp53_dimer_463_0_*Cdc42_479_0_^2-dend_455_0_ * Reac_663_0__Kb * IRSp53_a_477_0_ + + + + + + + + dend_455_0_ + Reac_663_0__Kf + IRSp53_dimer_463_0_ + + + Cdc42_479_0_ + 2 + + + + + dend_455_0_ + Reac_663_0__Kb + IRSp53_a_477_0_ + + + + + + + + + + + + + 221.970563695 + 632.076688463 + white + black + + + + + + + + + + + + dend_455_0_ * mod_sort_665_0__Kf * IRSp53_m_483_0_-dend_455_0_ * mod_sort_665_0__Kb * curv_IRSp53_471_0_ + + + + + + + + dend_455_0_ + mod_sort_665_0__Kf + IRSp53_m_483_0_ + + + + dend_455_0_ + mod_sort_665_0__Kb + curv_IRSp53_471_0_ + + + + + + + + + + + + + 114.300206695 + 515.373143756 + white + black + + + + + + + + + + + + dend_455_0_ * mod_detach_667_0__Kf * curv_IRSp53_471_0_-dend_455_0_ * mod_detach_667_0__Kb * IRSp53_m_483_0_ + + + + + + + + dend_455_0_ + mod_detach_667_0__Kf + curv_IRSp53_471_0_ + + + + dend_455_0_ + mod_detach_667_0__Kb + IRSp53_m_483_0_ + + + + + + + + + + + + + Use K3 = 21.5 uM here from Stemmer and Klee table 3. kb/kf =21.5 * 6e5 so kf = 7.75e-7, kb = 10 + + + + + 348.321640413 + 323.695278837 + white + black + + + + + + + + + + + + + dend_455_0_ * CaM_Ca3_bind_Ca_669_0__Kf * Ca_557_0_*CaM_Ca3_535_0_-dend_455_0_ * CaM_Ca3_bind_Ca_669_0__Kb * CaM_Ca4_541_0_ + + + + + + + + dend_455_0_ + CaM_Ca3_bind_Ca_669_0__Kf + Ca_557_0_ + CaM_Ca3_535_0_ + + + + dend_455_0_ + CaM_Ca3_bind_Ca_669_0__Kb + CaM_Ca4_541_0_ + + + + + + + + + + + + + Lets use the fast rate consts here. Since the rates are so different, I am not sure whether the order is relevant. These correspond to the TR2C fragment. We use the Martin et al rates here, plus the Drabicowski binding consts. All are scaled by 3X to cell temp. kf = 2e-10 kb = 72 Stemmer _and Klee: K1=.9, K2=1.1. Assume 1.0uM for both. kb/kf=3.6e11. If kb=72, kf = 2e-10 (Exactly the same !) 19 May 2006. Splitting the old CaM-TR2-bind-Ca reaction into two steps, each binding 1 Ca. This improves numerical stability and is conceptually better too. Overall rates are the same, so each kf and kb is the square root of the earlier ones. So kf = 1.125e-4, kb = 8.4853 + + + + + 275.507831206 + 323.695278837 + white + black + + + + + + + + + + + + + dend_455_0_ * CaM_bind_Ca_671_0__Kf * CaM_533_0_*Ca_557_0_-dend_455_0_ * CaM_bind_Ca_671_0__Kb * CaM_Ca_539_0_ + + + + + + + + dend_455_0_ + CaM_bind_Ca_671_0__Kf + CaM_533_0_ + Ca_557_0_ + + + + dend_455_0_ + CaM_bind_Ca_671_0__Kb + CaM_Ca_539_0_ + + + + + + + + + + + + + K3 = 21.5, K4 = 2.8. Assuming that the K4 step happens first, we get kb/kf = 2.8 uM = 1.68e6 so kf =6e-6 assuming kb = 10 + + + + + 324.050370677 + 323.695278837 + white + black + + + + + + + + + + + + + dend_455_0_ * CaM_Ca2_bind_Ca_673_0__Kf * CaM_Ca2_537_0_*Ca_557_0_-dend_455_0_ * CaM_Ca2_bind_Ca_673_0__Kb * CaM_Ca3_535_0_ + + + + + + + + dend_455_0_ + CaM_Ca2_bind_Ca_673_0__Kf + CaM_Ca2_537_0_ + Ca_557_0_ + + + + dend_455_0_ + CaM_Ca2_bind_Ca_673_0__Kb + CaM_Ca3_535_0_ + + + + + + + + + + + + + Lets use the fast rate consts here. Since the rates are so different, I am not sure whether the order is relevant. These correspond to the TR2C fragment. We use the Martin et al rates here, plus the Drabicowski binding consts. All are scaled by 3X to cell temp. kf = 2e-10 kb = 72 Stemmer _and Klee: K1=.9, K2=1.1. Assume 1.0uM for both. kb/kf=3.6e11. If kb=72, kf = 2e-10 (Exactly the same !) 19 May 2006. Splitting the old CaM-TR2-bind-Ca reaction into two steps, each binding 1 Ca. This improves numerical stability and is conceptually better too. Overall rates are the same, so each kf and kb is the square root of the earlier ones. So kf = 1.125e-4, kb = 8.4853 + + + + + 299.779100941 + 323.695278837 + white + black + + + + + + + + + + + + + dend_455_0_ * CaM_Ca_bind_Ca_675_0__Kf * CaM_Ca_539_0_*Ca_557_0_-dend_455_0_ * CaM_Ca_bind_Ca_675_0__Kb * CaM_Ca2_537_0_ + + + + + + + + dend_455_0_ + CaM_Ca_bind_Ca_675_0__Kf + CaM_Ca_539_0_ + Ca_557_0_ + + + + dend_455_0_ + CaM_Ca_bind_Ca_675_0__Kb + CaM_Ca2_537_0_ + + + + + + + + + + + + + 320.77426687 + 420.42993495 + white + black + + + + + + + + + + + + dend_455_0_ * CaM_x2_677_0__Kf * CaM_533_0_-dend_455_0_ * CaM_x2_677_0__Kb * CaM_xchange_543_0_ + + + + + + + + dend_455_0_ + CaM_x2_677_0__Kf + CaM_533_0_ + + + + dend_455_0_ + CaM_x2_677_0__Kb + CaM_xchange_543_0_ + + + + + + + + + + + + + Same values as for the main compartment Can the main compartment pool of Ca/CaM be used? + + + + + 669.404809786 + 168.318084139 + white + black + + + + + + + + + + + + + dend_455_0_ * CaMKII_thr286_bind_CaM_679_0__Kf * CaM_Ca4_541_0_*CaMKII_thr286_503_0_-dend_455_0_ * CaMKII_thr286_bind_CaM_679_0__Kb * CaMKII_thr286_CaM_499_0_ + + + + + + + + dend_455_0_ + CaMKII_thr286_bind_CaM_679_0__Kf + CaM_Ca4_541_0_ + CaMKII_thr286_503_0_ + + + + dend_455_0_ + CaMKII_thr286_bind_CaM_679_0__Kb + CaMKII_thr286_CaM_499_0_ + + + + + + + + + + + + + 736.134267995 + 168.318084139 + white + black + + + + + + + + + + + + + dend_455_0_ * CaMKII_bind_CaM_681_0__Kf * CaMKII_505_0_*CaM_Ca4_541_0_-dend_455_0_ * CaMKII_bind_CaM_681_0__Kb * CaMKII_CaM_501_0_ + + + + + + + + dend_455_0_ + CaMKII_bind_CaM_681_0__Kf + CaMKII_505_0_ + CaM_Ca4_541_0_ + + + + dend_455_0_ + CaMKII_bind_CaM_681_0__Kb + CaMKII_CaM_501_0_ + + + + + + + + + + + + + 1000.0 + 6.16624828141 + white + black + + + + + + + + + + + + dend_455_0_ * CaMKII_x2_683_0__Kf * CaMKII_505_0_-dend_455_0_ * CaMKII_x2_683_0__Kb * CaMKII_xchange_511_0_ + + + + + + + + dend_455_0_ + CaMKII_x2_683_0__Kf + CaMKII_505_0_ + + + + dend_455_0_ + CaMKII_x2_683_0__Kb + CaMKII_xchange_511_0_ + + + + + + + + + + + + + From Quintana et al 2005 + + + + + 178.422752263 + 401.275825285 + white + black + + + + + + + + + + + + + dend_455_0_ * CaM_Bind_CaN_685_0__Kf * CaM_Ca2_537_0_*Ca2_CaN_555_0_-dend_455_0_ * CaM_Bind_CaN_685_0__Kb * CaM_CaN_549_0_ + + + + + + + + dend_455_0_ + CaM_Bind_CaN_685_0__Kf + CaM_Ca2_537_0_ + Ca2_CaN_555_0_ + + + + dend_455_0_ + CaM_Bind_CaN_685_0__Kb + CaM_CaN_549_0_ + + + + + + + + + + + + + 87.4220243191 + 401.275825285 + white + black + + + + + + + + + + + + + dend_455_0_ * Ca_bind_CaN_687_0__Kf * CaN_553_0_*Ca_557_0_^2-dend_455_0_ * Ca_bind_CaN_687_0__Kb * Ca2_CaN_555_0_ + + + + + + + + dend_455_0_ + Ca_bind_CaN_687_0__Kf + CaN_553_0_ + + + Ca_557_0_ + 2 + + + + + dend_455_0_ + Ca_bind_CaN_687_0__Kb + Ca2_CaN_555_0_ + + + + + + + + + + + + + 144.037626781 + 42.6460993987 + white + black + + + + + + + + + + + + + dend_455_0_ * Reac_duplicated_689_0__Kf * I1_p_563_0_*PP1_active_559_0_-dend_455_0_ * Reac_duplicated_689_0__Kb * PP1_I1_p_561_0_ + + + + + + + + dend_455_0_ + Reac_duplicated_689_0__Kf + I1_p_563_0_ + PP1_active_559_0_ + + + + dend_455_0_ + Reac_duplicated_689_0__Kb + PP1_I1_p_561_0_ + + + + + + + + + + + + + 176.335798821 + 308.155281775 + white + black + + + + + + + + + + + + + dend_455_0_ * dissoc_PP1_I1_691_0__Kf * PP1_I1_571_0_ + + + + + + dend_455_0_ + dissoc_PP1_I1_691_0__Kf + PP1_I1_571_0_ + + + + + + + + + + + SoS/GEF is present at 50 nM ie 3e4/cell. BetaGamma maxes out at 9e4. Assume we have 1/3 of the GEF active when the BetaGamma is 1.5e4. so 1e4 * kb = 2e4 * 1.5e4 * kf, so kf/kb = 3e-5. The rate of this equil should be reasonably fast, say 1/sec + + + + + 846.127982974 + 488.845517753 + white + black + + + + + + + + + + + + dend_455_0_ * bg_act_GEF_693_0__Kf * inact_GEF_517_0_-dend_455_0_ * bg_act_GEF_693_0__Kb * GEF_Gprot_bg_515_0_ + + + + + + + + dend_455_0_ + bg_act_GEF_693_0__Kf + inact_GEF_517_0_ + + + + dend_455_0_ + bg_act_GEF_693_0__Kb + GEF_Gprot_bg_515_0_ + + + + + + + + + + + + + 858.584686638 + 638.230110666 + white + black + + + + + + + + + + + + dend_455_0_ * dephosph_GEF_695_0__Kf * GEF_p_519_0_ + + + + + + dend_455_0_ + dephosph_GEF_695_0__Kf + GEF_p_519_0_ + + + + + + + + + + + This is extremely slow (1e-4), but it is significant as so little GAP actually gets complexed with it that the total GTP turnover rises only by 2-3 X (see Gibbs et al, JBC 265(33) 20437-20422) and Eccleston et al JBC 268(36) 27012-27019 kf = 1e-4 + + + + + 808.649818128 + 532.24000464 + white + black + + + + + + + + + + + + dend_455_0_ * Ras_intrinsic_GTPase_697_0__Kf * GTP_Ras_521_0_ + + + + + + dend_455_0_ + Ras_intrinsic_GTPase_697_0__Kf + GTP_Ras_521_0_ + + + + + + + + + + + Assume a reasonably good rate for dephosphorylating it, 1/sec + + + + + 960.957313755 + 423.32250519 + white + black + + + + + + + + + + + + dend_455_0_ * dephosph_GAP_699_0__Kf * GAP_p_525_0_ + + + + + + dend_455_0_ + dephosph_GAP_699_0__Kf + GAP_p_525_0_ + + + + + + + + + + + We have no numbers for this. It is probably between the two extremes represented by the CaMKII phosph states, and I have used guesses based on this. kf=1e-4 kb=1 The reaction is based on Farnsworth et al Nature 376 524-527 1995 + + + + + 935.017900393 + 681.343856218 + white + black + + + + + + + + + + + + + dend_455_0_ * CaM_GEF1_Reac_701_0__Kf * inact_GEF_517_0_*CaM_Ca4_541_0_-dend_455_0_ * CaM_GEF1_Reac_701_0__Kb * CaM_GEF_531_0_ + + + + + + + + dend_455_0_ + CaM_GEF1_Reac_701_0__Kf + inact_GEF_517_0_ + CaM_Ca4_541_0_ + + + + dend_455_0_ + CaM_GEF1_Reac_701_0__Kb + CaM_GEF_531_0_ + + + + + + + + + + + + + 855.237955446 + 550.651557157 + white + black + + + + + + + + + + + + dend_455_0_ * dephosph_inact_GEF_p_703_0__Kf * inact_GEF_p_529_0_ + + + + + + dend_455_0_ + dephosph_inact_GEF_p_703_0__Kf + inact_GEF_p_529_0_ + + + + + + + + + + + K inhib = 1nM from Cohen Ann Rev Bioch 1989, 4 nM from Foukes et al Assume 2 nM. kf /kb = 8.333e-4 + + + + + 473.620791824 + 209.805307835 + white + black + + + + + + + + + + + + + dend_455_0_ * Inact_PP1_705_0__Kf * I1_p_563_0_*PP1_active_559_0_-dend_455_0_ * Inact_PP1_705_0__Kb * PP1_I1_p_561_0_ + + + + + + + + dend_455_0_ + Inact_PP1_705_0__Kf + I1_p_563_0_ + PP1_active_559_0_ + + + + dend_455_0_ + Inact_PP1_705_0__Kb + PP1_I1_p_561_0_ + + + + + + + + + + + + + 472.867704723 + 703.503683429 + white + black + + + + + + + + + + + + + dend_455_0_ * Rac_Tiam_Reac_707_0__Kf * Rac_GTP_577_0_^2*IRSp53_dimer_463_0_-dend_455_0_ * Rac_Tiam_Reac_707_0__Kb * IRSp53_a_477_0_ + + + + + + + + dend_455_0_ + Rac_Tiam_Reac_707_0__Kf + + + Rac_GTP_577_0_ + 2 + + IRSp53_dimer_463_0_ + + + + dend_455_0_ + Rac_Tiam_Reac_707_0__Kb + IRSp53_a_477_0_ + + + + + + + + + + + + + 142.268106818 + 669.273467277 + white + black + + + + + + + + + + + + + dend_455_0_ * IRa_IRm_Reac_709_0__Kf * Eps8_481_0_^2*IRSp53_a_477_0_-dend_455_0_ * IRa_IRm_Reac_709_0__Kb * IRSp53_m_483_0_ + + + + + + + + dend_455_0_ + IRa_IRm_Reac_709_0__Kf + + + Eps8_481_0_ + 2 + + IRSp53_a_477_0_ + + + + dend_455_0_ + IRa_IRm_Reac_709_0__Kb + IRSp53_m_483_0_ + + + + + + + + + + + + + 186.0 + 522.428748451 + white + black + + + + + + + + + + + + dend_455_0_ * detach_attach_711_0__Kf * curv_IRSp53_471_0_ + + + + + + dend_455_0_ + detach_attach_711_0__Kf + curv_IRSp53_471_0_ + + + + + + + + + + + 673.772770514 + 502.89531814 + white + black + + + + + + + + + + + + + dend_455_0_ * CaM_GEF2_Reac_713_0__Kf * GEF_Gprot_bg_515_0_*CaM_Ca4_541_0_-dend_455_0_ * CaM_GEF2_Reac_713_0__Kb * CaM_GEF_531_0_ + + + + + + + + dend_455_0_ + CaM_GEF2_Reac_713_0__Kf + GEF_Gprot_bg_515_0_ + CaM_Ca4_541_0_ + + + + dend_455_0_ + CaM_GEF2_Reac_713_0__Kb + CaM_GEF_531_0_ + + + + + + + + + + + + + 673.386385257 + 525.549269975 + white + black + + + + + + + + + + + + + dend_455_0_ * CaM_GEF3_Reac_715_0__Kf * inact_GEF_517_0_*CaM_Ca4_541_0_-dend_455_0_ * CaM_GEF3_Reac_715_0__Kb * CaM_GEF_531_0_ + + + + + + + + dend_455_0_ + CaM_GEF3_Reac_715_0__Kf + inact_GEF_517_0_ + CaM_Ca4_541_0_ + + + + dend_455_0_ + CaM_GEF3_Reac_715_0__Kb + CaM_GEF_531_0_ + + + + + + + + + + + + + 11.0 + 702.850061958 + white + black + + + + + + + + + + + + dend_455_0_ * Cdc42_GTP_GDP_Reac_717_0__Kf * Cdc42_479_0_ + + + + + + dend_455_0_ + Cdc42_GTP_GDP_Reac_717_0__Kf + Cdc42_479_0_ + + + + + + + + + + + 539.0 + 650.309789343 + white + black + + + + + + + + + + + + dend_455_0_ * Rac_GTP_GDP_Reac_719_0__Kf * Rac_GTP_577_0_ + + + + + + dend_455_0_ + Rac_GTP_GDP_Reac_719_0__Kf + Rac_GTP_577_0_ + + + + + + + + + + + 218.121621357 + 500.827654274 + white + black + + + + + + + + + + + + dend_455_0_ * to_tube_Reac_721_0__Kf * curv_IRSp53_471_0_-dend_455_0_ * to_tube_Reac_721_0__Kb * tube_IRSp53_585_0_ + + + + + + + + dend_455_0_ + to_tube_Reac_721_0__Kf + curv_IRSp53_471_0_ + + + + dend_455_0_ + to_tube_Reac_721_0__Kb + tube_IRSp53_585_0_ + + + + + + + + + + + + + 420.0 + 559.107806691 + white + black + + + + + + + + + + + + dend_455_0_ * Tiam_Rev_Reac_723_0__Kf * Tiam1_575_0_-dend_455_0_ * Tiam_Rev_Reac_723_0__Kb * Tiam_inact_581_0_ + + + + + + + + dend_455_0_ + Tiam_Rev_Reac_723_0__Kf + Tiam1_575_0_ + + + + dend_455_0_ + Tiam_Rev_Reac_723_0__Kb + Tiam_inact_581_0_ + + + + + + + + + + + + + 343.0 + 572.986369269 + white + black + + + + + + + + + + + + dend_455_0_ * Metab_Reac_725_0__Kf * Cdc42_479_0_ + + + + + + dend_455_0_ + Metab_Reac_725_0__Kf + Cdc42_479_0_ + + + + + + + + + + + 437.413897715 + 642.530036097 + white + black + + + + + + + + + + + + dend_455_0_ * Metab_Reac_Rac_727_0__Kf * Rac_GTP_577_0_ + + + + + + dend_455_0_ + Metab_Reac_Rac_727_0__Kf + Rac_GTP_577_0_ + + + + + + + + + + + 458.0 + 779.182156134 + white + black + + + + + + + + + + + + dend_455_0_ * Metab_Tiam_act_Reac_729_0__Kf * Tiam1_575_0_ + + + + + + dend_455_0_ + Metab_Tiam_act_Reac_729_0__Kf + Tiam1_575_0_ + + + + + + + + + + + 398.280737429 + 754.179192932 + white + black + + + + + + + + + + + + dend_455_0_ * Metab_Tiam_inact_Reac_731_0__Kf * Tiam_inact_581_0_-dend_455_0_ * Metab_Tiam_inact_Reac_731_0__Kb * Metabolism_Tiam_inact_591_0_ + + + + + + + + dend_455_0_ + Metab_Tiam_inact_Reac_731_0__Kf + Tiam_inact_581_0_ + + + + dend_455_0_ + Metab_Tiam_inact_Reac_731_0__Kb + Metabolism_Tiam_inact_591_0_ + + + + + + + + + + + + + + + + + + + + dend_455_0_ * Metab_Cdc_GDP_Reac_733_0__Kf * Cdc42_GDP_579_0_-dend_455_0_ * Metab_Cdc_GDP_Reac_733_0__Kb * Metabolism_587_0_ + + + + + + + + dend_455_0_ + Metab_Cdc_GDP_Reac_733_0__Kf + Cdc42_GDP_579_0_ + + + + dend_455_0_ + Metab_Cdc_GDP_Reac_733_0__Kb + Metabolism_587_0_ + + + + + + + + + + + + + 458.621575481 + 392.657360103 + white + black + + + + + + + + + + + + dend_455_0_ * Metab_Rac_GDP_Reac_735_0__Kf * Rac_GDP_573_0_-dend_455_0_ * Metab_Rac_GDP_Reac_735_0__Kb * Metabolism_587_0_ + + + + + + + + dend_455_0_ + Metab_Rac_GDP_Reac_735_0__Kf + Rac_GDP_573_0_ + + + + dend_455_0_ + Metab_Rac_GDP_Reac_735_0__Kb + Metabolism_587_0_ + + + + + + + + + + + + + 628.0 + 800.0 + white + black + + + + + + + + + + + + dend_455_0_ * c_m_Rac_Reac_737_0__Kf * Rac_GTP_577_0_-dend_455_0_ * c_m_Rac_Reac_737_0__Kb * Rac_m_595_0_ + + + + + + + + dend_455_0_ + c_m_Rac_Reac_737_0__Kf + Rac_GTP_577_0_ + + + + dend_455_0_ + c_m_Rac_Reac_737_0__Kb + Rac_m_595_0_ + + + + + + + + + + + + + 100.511262476 + 666.83907117 + white + black + + + + + + + + + + + + dend_455_0_ * c_m_Cdc_Reac_739_0__Kf * Cdc42_479_0_-dend_455_0_ * c_m_Cdc_Reac_739_0__Kb * Cdc42_m_593_0_ + + + + + + + + dend_455_0_ + c_m_Cdc_Reac_739_0__Kf + Cdc42_479_0_ + + + + dend_455_0_ + c_m_Cdc_Reac_739_0__Kb + Cdc42_m_593_0_ + + + + + + + + + + + + + 10.0 + 492.0 + white + black + + + + + + + + + + + + dend_455_0_ * GF_Reac_741_0__Kf * Gactin_491_0_-dend_455_0_ * GF_Reac_741_0__Kb * Factin_649_0_ + + + + + + + + dend_455_0_ + GF_Reac_741_0__Kf + Gactin_491_0_ + + + + dend_455_0_ + GF_Reac_741_0__Kb + Factin_649_0_ + + + + + + + + + + + + + 8.03382906582 + 604.959866104 + white + black + + + + + + + + + + + + + dend_455_0_ * IR_F_Reac_743_0__Kf * Factin_649_0_*IRSp53_m_483_0_-dend_455_0_ * IR_F_Reac_743_0__Kb * IR_actin_651_0_ + + + + + + + + dend_455_0_ + IR_F_Reac_743_0__Kf + Factin_649_0_ + IRSp53_m_483_0_ + + + + dend_455_0_ + IR_F_Reac_743_0__Kb + IR_actin_651_0_ + + + + + + + + + + + + + tot_auto_545_0_ + CaMKII_505_0_ + auton_autoph_cplx_746_0_ + auton_autoph_745_0_ + 1 + 487.864907828 + 71.0722738271 + red + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * tot_auto_545_0_*CaMKII_505_0_ - k2 * auton_autoph_cplx_746_0_ ) + + + + + + dend_455_0_ + + + + + k1 + tot_auto_545_0_ + CaMKII_505_0_ + + + + k2 + auton_autoph_cplx_746_0_ + + + + + + + + + + + + + + auton_autoph_cplx_746_0_ + tot_auto_545_0_ + CaMKII_thr286_503_0_ + auton_autoph_745_0_ + 2 + 487.864907828 + 71.0722738271 + red + black + + + + + + + + + + + + + dend_455_0_ * k3*auton_autoph_cplx_746_0_ + + + + + + dend_455_0_ + k3 + auton_autoph_cplx_746_0_ + + + + + + + + + + + tot_auto_545_0_ + CaMKII_CaM_501_0_ + auton_286_cplx_749_0_ + auton_286_748_0_ + 1 + 387.411565445 + 11.5718279133 + red + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * tot_auto_545_0_*CaMKII_CaM_501_0_ - k2 * auton_286_cplx_749_0_ ) + + + + + + dend_455_0_ + + + + + k1 + tot_auto_545_0_ + CaMKII_CaM_501_0_ + + + + k2 + auton_286_cplx_749_0_ + + + + + + + + + + + + + + auton_286_cplx_749_0_ + tot_auto_545_0_ + CaMKII_thr286_CaM_499_0_ + auton_286_748_0_ + 2 + 387.411565445 + 11.5718279133 + red + black + + + + + + + + + + + + + dend_455_0_ * k3*auton_286_cplx_749_0_ + + + + + + dend_455_0_ + k3 + auton_286_cplx_749_0_ + + + + + + + + + + + tot_auto_545_0_ + CaMKII_thr286_503_0_ + auton_305_cplx_752_0_ + auton_305_751_0_ + 1 + 524.238745307 + 71.0722738271 + red + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * tot_auto_545_0_*CaMKII_thr286_503_0_ - k2 * auton_305_cplx_752_0_ ) + + + + + + dend_455_0_ + + + + + k1 + tot_auto_545_0_ + CaMKII_thr286_503_0_ + + + + k2 + auton_305_cplx_752_0_ + + + + + + + + + + + + + + auton_305_cplx_752_0_ + tot_auto_545_0_ + CaMKII_p_p_p_509_0_ + auton_305_751_0_ + 2 + 524.238745307 + 71.0722738271 + red + black + + + + + + + + + + + + + dend_455_0_ * k3*auton_305_cplx_752_0_ + + + + + + dend_455_0_ + k3 + auton_305_cplx_752_0_ + + + + + + + + + + + tot_CaM_CaMKII_495_0_ + CaMKII_505_0_ + CaM_act_autoph_cplx_755_0_ + CaM_act_autoph_754_0_ + 1 + 778.592456469 + 12.9408894412 + red + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * CaMKII_505_0_*tot_CaM_CaMKII_495_0_ - k2 * CaM_act_autoph_cplx_755_0_ ) + + + + + + dend_455_0_ + + + + + k1 + CaMKII_505_0_ + tot_CaM_CaMKII_495_0_ + + + + k2 + CaM_act_autoph_cplx_755_0_ + + + + + + + + + + + + + + CaM_act_autoph_cplx_755_0_ + tot_CaM_CaMKII_495_0_ + CaMKII_thr286_503_0_ + CaM_act_autoph_754_0_ + 2 + 778.592456469 + 12.9408894412 + red + black + + + + + + + + + + + + + dend_455_0_ * k3*CaM_act_autoph_cplx_755_0_ + + + + + + dend_455_0_ + k3 + CaM_act_autoph_cplx_755_0_ + + + + + + + + + + + tot_CaM_CaMKII_495_0_ + CaMKII_thr286_503_0_ + CaM_act_305_cplx_758_0_ + CaM_act_305_757_0_ + 1 + 814.966293949 + 12.9408894412 + red + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * CaMKII_thr286_503_0_*tot_CaM_CaMKII_495_0_ - k2 * CaM_act_305_cplx_758_0_ ) + + + + + + dend_455_0_ + + + + + k1 + CaMKII_thr286_503_0_ + tot_CaM_CaMKII_495_0_ + + + + k2 + CaM_act_305_cplx_758_0_ + + + + + + + + + + + + + + CaM_act_305_cplx_758_0_ + tot_CaM_CaMKII_495_0_ + CaMKII_p_p_p_509_0_ + CaM_act_305_757_0_ + 2 + 814.966293949 + 12.9408894412 + red + black + + + + + + + + + + + + + dend_455_0_ * k3*CaM_act_305_cplx_758_0_ + + + + + + dend_455_0_ + k3 + CaM_act_305_cplx_758_0_ + + + + + + + + + + + tot_CaM_CaMKII_495_0_ + CaMKII_CaM_501_0_ + CaM_act_286_cplx_761_0_ + CaM_act_286_760_0_ + 1 + 705.778647264 + 12.9408894412 + red + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * CaMKII_CaM_501_0_*tot_CaM_CaMKII_495_0_ - k2 * CaM_act_286_cplx_761_0_ ) + + + + + + dend_455_0_ + + + + + k1 + CaMKII_CaM_501_0_ + tot_CaM_CaMKII_495_0_ + + + + k2 + CaM_act_286_cplx_761_0_ + + + + + + + + + + + + + + CaM_act_286_cplx_761_0_ + tot_CaM_CaMKII_495_0_ + CaMKII_thr286_CaM_499_0_ + CaM_act_286_760_0_ + 2 + 705.778647264 + 12.9408894412 + red + black + + + + + + + + + + + + + dend_455_0_ * k3*CaM_act_286_cplx_761_0_ + + + + + + dend_455_0_ + k3 + CaM_act_286_cplx_761_0_ + + + + + + + + + + + PP2A_551_0_ + CaMKII_thr286_CaM_499_0_ + Deph_thr286_cplx_764_0_ + Deph_thr286_763_0_ + 1 + 421.135449618 + 109.970597953 + red + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * CaMKII_thr286_CaM_499_0_*PP2A_551_0_ - k2 * Deph_thr286_cplx_764_0_ ) + + + + + + dend_455_0_ + + + + + k1 + CaMKII_thr286_CaM_499_0_ + PP2A_551_0_ + + + + k2 + Deph_thr286_cplx_764_0_ + + + + + + + + + + + + + + Deph_thr286_cplx_764_0_ + PP2A_551_0_ + CaMKII_CaM_501_0_ + Deph_thr286_763_0_ + 2 + 421.135449618 + 109.970597953 + red + black + + + + + + + + + + + + + dend_455_0_ * k3*Deph_thr286_cplx_764_0_ + + + + + + dend_455_0_ + k3 + Deph_thr286_cplx_764_0_ + + + + + + + + + + + PP2A_551_0_ + CaMKII_thr286_503_0_ + Deph_thr286b_cplx_767_0_ + Deph_thr286b_766_0_ + 1 + 481.780556831 + 109.970597953 + red + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * CaMKII_thr286_503_0_*PP2A_551_0_ - k2 * Deph_thr286b_cplx_767_0_ ) + + + + + + dend_455_0_ + + + + + k1 + CaMKII_thr286_503_0_ + PP2A_551_0_ + + + + k2 + Deph_thr286b_cplx_767_0_ + + + + + + + + + + + + + + Deph_thr286b_cplx_767_0_ + PP2A_551_0_ + CaMKII_505_0_ + Deph_thr286b_766_0_ + 2 + 481.780556831 + 109.970597953 + red + black + + + + + + + + + + + + + dend_455_0_ * k3*Deph_thr286b_cplx_767_0_ + + + + + + dend_455_0_ + k3 + Deph_thr286b_cplx_767_0_ + + + + + + + + + + + PP2A_551_0_ + CaMKII_p_p_p_509_0_ + Deph_thr305_cplx_770_0_ + Deph_thr305_769_0_ + 1 + 524.238745307 + 109.970597953 + red + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * CaMKII_p_p_p_509_0_*PP2A_551_0_ - k2 * Deph_thr305_cplx_770_0_ ) + + + + + + dend_455_0_ + + + + + k1 + CaMKII_p_p_p_509_0_ + PP2A_551_0_ + + + + k2 + Deph_thr305_cplx_770_0_ + + + + + + + + + + + + + + Deph_thr305_cplx_770_0_ + PP2A_551_0_ + CaMKII_thr286_503_0_ + Deph_thr305_769_0_ + 2 + 524.238745307 + 109.970597953 + red + black + + + + + + + + + + + + + dend_455_0_ * k3*Deph_thr305_cplx_770_0_ + + + + + + dend_455_0_ + k3 + Deph_thr305_cplx_770_0_ + + + + + + + + + + + PP2A_551_0_ + CaMKII_p_p_p_509_0_ + Deph_thr286c_cplx_773_0_ + Deph_thr286c_772_0_ + 1 + 660.327879743 + 148.92478462 + red + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * CaMKII_p_p_p_509_0_*PP2A_551_0_ - k2 * Deph_thr286c_cplx_773_0_ ) + + + + + + dend_455_0_ + + + + + k1 + CaMKII_p_p_p_509_0_ + PP2A_551_0_ + + + + k2 + Deph_thr286c_cplx_773_0_ + + + + + + + + + + + + + + Deph_thr286c_cplx_773_0_ + PP2A_551_0_ + CaMKII_thr305_507_0_ + Deph_thr286c_772_0_ + 2 + 660.327879743 + 148.92478462 + red + black + + + + + + + + + + + + + dend_455_0_ * k3*Deph_thr286c_cplx_773_0_ + + + + + + dend_455_0_ + k3 + Deph_thr286c_cplx_773_0_ + + + + + + + + + + + PP2A_551_0_ + CaMKII_thr305_507_0_ + Deph_thr305a_cplx_776_0_ + Deph_thr305a_775_0_ + 1 + 604.987451791 + 152.87665863 + red + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * CaMKII_thr305_507_0_*PP2A_551_0_ - k2 * Deph_thr305a_cplx_776_0_ ) + + + + + + dend_455_0_ + + + + + k1 + CaMKII_thr305_507_0_ + PP2A_551_0_ + + + + k2 + Deph_thr305a_cplx_776_0_ + + + + + + + + + + + + + + Deph_thr305a_cplx_776_0_ + PP2A_551_0_ + CaMKII_505_0_ + Deph_thr305a_775_0_ + 2 + 604.987451791 + 152.87665863 + red + black + + + + + + + + + + + + + dend_455_0_ * k3*Deph_thr305a_cplx_776_0_ + + + + + + dend_455_0_ + k3 + Deph_thr305a_cplx_776_0_ + + + + + + + + + + + CaM_CaN_549_0_ + I1_p_563_0_ + Enz_cplx_779_0_ + dephosph_inhib1_778_0_ + 1 + 259.683385861 + 247.294730666 + #8fbc8f + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * I1_p_563_0_*CaM_CaN_549_0_ - k2 * Enz_cplx_779_0_ ) + + + + + + dend_455_0_ + + + + + k1 + I1_p_563_0_ + CaM_CaN_549_0_ + + + + k2 + Enz_cplx_779_0_ + + + + + + + + + + + + + + Enz_cplx_779_0_ + CaM_CaN_549_0_ + I1_565_0_ + dephosph_inhib1_778_0_ + 2 + 259.683385861 + 247.294730666 + #8fbc8f + black + + + + + + + + + + + + + dend_455_0_ * k3*Enz_cplx_779_0_ + + + + + + dend_455_0_ + k3 + Enz_cplx_779_0_ + + + + + + + + + + + PKA_active_567_0_ + I1_565_0_ + Enz_cplx_782_0_ + Enz_781_0_ + 1 + 124.390761516 + 155.20157349 + #adff2f + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * I1_565_0_*PKA_active_567_0_ - k2 * Enz_cplx_782_0_ ) + + + + + + dend_455_0_ + + + + + k1 + I1_565_0_ + PKA_active_567_0_ + + + + k2 + Enz_cplx_782_0_ + + + + + + + + + + + + + + Enz_cplx_782_0_ + PKA_active_567_0_ + I1_p_563_0_ + Enz_781_0_ + 2 + 124.390761516 + 155.20157349 + #adff2f + black + + + + + + + + + + + + + dend_455_0_ * k3*Enz_cplx_782_0_ + + + + + + dend_455_0_ + k3 + Enz_cplx_782_0_ + + + + + + + + + + + PP2A_551_0_ + I1_p_563_0_ + Enz_cplx_785_0_ + PP2A_dephosph_I1_784_0_ + 1 + 137.835991264 + 190.494759476 + #ff00ff + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * I1_p_563_0_*PP2A_551_0_ - k2 * Enz_cplx_785_0_ ) + + + + + + dend_455_0_ + + + + + k1 + I1_p_563_0_ + PP2A_551_0_ + + + + k2 + Enz_cplx_785_0_ + + + + + + + + + + + + + + Enz_cplx_785_0_ + PP2A_551_0_ + I1_565_0_ + PP2A_dephosph_I1_784_0_ + 2 + 137.835991264 + 190.494759476 + #ff00ff + black + + + + + + + + + + + + + dend_455_0_ * k3*Enz_cplx_785_0_ + + + + + + dend_455_0_ + k3 + Enz_cplx_785_0_ + + + + + + + + + + + CaM_CaN_549_0_ + PP1_I1_p_561_0_ + Enz1_cplx_788_0_ + dephosph_PP1_I_p_787_0_ + 1 + 95.3994848694 + 47.1161914179 + #ffdab9 + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * PP1_I1_p_561_0_*CaM_CaN_549_0_ - k2 * Enz1_cplx_788_0_ ) + + + + + + dend_455_0_ + + + + + k1 + PP1_I1_p_561_0_ + CaM_CaN_549_0_ + + + + k2 + Enz1_cplx_788_0_ + + + + + + + + + + + + + + Enz1_cplx_788_0_ + CaM_CaN_549_0_ + PP1_I1_571_0_ + dephosph_PP1_I_p_787_0_ + 2 + 95.3994848694 + 47.1161914179 + #ffdab9 + black + + + + + + + + + + + + + dend_455_0_ * k3*Enz1_cplx_788_0_ + + + + + + dend_455_0_ + k3 + Enz1_cplx_788_0_ + + + + + + + + + + + PP1_active_559_0_ + CaMKII_thr286_CaM_499_0_ + Enz_cplx_791_0_ + Deph_thr286_790_0_ + 1 + 178.16353342 + 145.194731034 + #808080 + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * CaMKII_thr286_CaM_499_0_*PP1_active_559_0_ - k2 * Enz_cplx_791_0_ ) + + + + + + dend_455_0_ + + + + + k1 + CaMKII_thr286_CaM_499_0_ + PP1_active_559_0_ + + + + k2 + Enz_cplx_791_0_ + + + + + + + + + + + + + + Enz_cplx_791_0_ + PP1_active_559_0_ + CaMKII_CaM_501_0_ + Deph_thr286_790_0_ + 2 + 178.16353342 + 145.194731034 + #808080 + black + + + + + + + + + + + + + dend_455_0_ * k3*Enz_cplx_791_0_ + + + + + + dend_455_0_ + k3 + Enz_cplx_791_0_ + + + + + + + + + + + PP1_active_559_0_ + CaMKII_thr286_503_0_ + Enz_cplx_794_0_ + Deph_thr286b_793_0_ + 1 + 302.960219114 + 184.980199164 + #8a2be2 + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * CaMKII_thr286_503_0_*PP1_active_559_0_ - k2 * Enz_cplx_794_0_ ) + + + + + + dend_455_0_ + + + + + k1 + CaMKII_thr286_503_0_ + PP1_active_559_0_ + + + + k2 + Enz_cplx_794_0_ + + + + + + + + + + + + + + Enz_cplx_794_0_ + PP1_active_559_0_ + CaMKII_505_0_ + Deph_thr286b_793_0_ + 2 + 302.960219114 + 184.980199164 + #8a2be2 + black + + + + + + + + + + + + + dend_455_0_ * k3*Enz_cplx_794_0_ + + + + + + dend_455_0_ + k3 + Enz_cplx_794_0_ + + + + + + + + + + + PP1_active_559_0_ + CaMKII_p_p_p_509_0_ + Enz_cplx_797_0_ + Deph_thr305_796_0_ + 1 + 222.161143707 + 192.100915547 + #ffb6c1 + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * CaMKII_p_p_p_509_0_*PP1_active_559_0_ - k2 * Enz_cplx_797_0_ ) + + + + + + dend_455_0_ + + + + + k1 + CaMKII_p_p_p_509_0_ + PP1_active_559_0_ + + + + k2 + Enz_cplx_797_0_ + + + + + + + + + + + + + + Enz_cplx_797_0_ + PP1_active_559_0_ + CaMKII_thr286_503_0_ + Deph_thr305_796_0_ + 2 + 222.161143707 + 192.100915547 + #ffb6c1 + black + + + + + + + + + + + + + dend_455_0_ * k3*Enz_cplx_797_0_ + + + + + + dend_455_0_ + k3 + Enz_cplx_797_0_ + + + + + + + + + + + PP1_active_559_0_ + CaMKII_p_p_p_509_0_ + Enz_cplx_800_0_ + Deph_thr286c_799_0_ + 1 + 239.84891172 + 197.467710478 + #98fb98 + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * CaMKII_p_p_p_509_0_*PP1_active_559_0_ - k2 * Enz_cplx_800_0_ ) + + + + + + dend_455_0_ + + + + + k1 + CaMKII_p_p_p_509_0_ + PP1_active_559_0_ + + + + k2 + Enz_cplx_800_0_ + + + + + + + + + + + + + + Enz_cplx_800_0_ + PP1_active_559_0_ + CaMKII_thr305_507_0_ + Deph_thr286c_799_0_ + 2 + 239.84891172 + 197.467710478 + #98fb98 + black + + + + + + + + + + + + + dend_455_0_ * k3*Enz_cplx_800_0_ + + + + + + dend_455_0_ + k3 + Enz_cplx_800_0_ + + + + + + + + + + + PP1_active_559_0_ + CaMKII_thr305_507_0_ + Enz_cplx_803_0_ + Deph_thr305a_802_0_ + 1 + 309.262670559 + 229.096681644 + #7b68ee + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * CaMKII_thr305_507_0_*PP1_active_559_0_ - k2 * Enz_cplx_803_0_ ) + + + + + + dend_455_0_ + + + + + k1 + CaMKII_thr305_507_0_ + PP1_active_559_0_ + + + + k2 + Enz_cplx_803_0_ + + + + + + + + + + + + + + Enz_cplx_803_0_ + PP1_active_559_0_ + CaMKII_505_0_ + Deph_thr305a_802_0_ + 2 + 309.262670559 + 229.096681644 + #7b68ee + black + + + + + + + + + + + + + dend_455_0_ * k3*Enz_cplx_803_0_ + + + + + + dend_455_0_ + k3 + Enz_cplx_803_0_ + + + + + + + + + + + PKC_active_569_0_ + GAP_527_0_ + PKC_inact_GAP_cplx_806_0_ + PKC_inact_GAP_805_0_ + 1 + 775.934154173 + 404.291023961 + red + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * PKC_active_569_0_*GAP_527_0_ - k2 * PKC_inact_GAP_cplx_806_0_ ) + + + + + + dend_455_0_ + + + + + k1 + PKC_active_569_0_ + GAP_527_0_ + + + + k2 + PKC_inact_GAP_cplx_806_0_ + + + + + + + + + + + + + + PKC_inact_GAP_cplx_806_0_ + PKC_active_569_0_ + GAP_p_525_0_ + PKC_inact_GAP_805_0_ + 2 + 775.934154173 + 404.291023961 + red + black + + + + + + + + + + + + + dend_455_0_ * k3*PKC_inact_GAP_cplx_806_0_ + + + + + + dend_455_0_ + k3 + PKC_inact_GAP_cplx_806_0_ + + + + + + + + + + + PKC_active_569_0_ + inact_GEF_517_0_ + PKC_act_GEF_cplx_809_0_ + PKC_act_GEF_808_0_ + 1 + 726.668993872 + 238.537527527 + red + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * PKC_active_569_0_*inact_GEF_517_0_ - k2 * PKC_act_GEF_cplx_809_0_ ) + + + + + + dend_455_0_ + + + + + k1 + PKC_active_569_0_ + inact_GEF_517_0_ + + + + k2 + PKC_act_GEF_cplx_809_0_ + + + + + + + + + + + + + + PKC_act_GEF_cplx_809_0_ + PKC_active_569_0_ + GEF_p_519_0_ + PKC_act_GEF_808_0_ + 2 + 726.668993872 + 238.537527527 + red + black + + + + + + + + + + + + + dend_455_0_ * k3*PKC_act_GEF_cplx_809_0_ + + + + + + dend_455_0_ + k3 + PKC_act_GEF_cplx_809_0_ + + + + + + + + + + + GEF_Gprot_bg_515_0_ + GDP_Ras_523_0_ + GEF_bg_act_Ras_cplx_812_0_ + GEF_bg_act_Ras_811_0_ + 1 + 701.351701649 + 536.176611181 + red + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * GDP_Ras_523_0_*GEF_Gprot_bg_515_0_ - k2 * GEF_bg_act_Ras_cplx_812_0_ ) + + + + + + dend_455_0_ + + + + + k1 + GDP_Ras_523_0_ + GEF_Gprot_bg_515_0_ + + + + k2 + GEF_bg_act_Ras_cplx_812_0_ + + + + + + + + + + + + + + GEF_bg_act_Ras_cplx_812_0_ + GEF_Gprot_bg_515_0_ + GTP_Ras_521_0_ + GEF_bg_act_Ras_811_0_ + 2 + 701.351701649 + 536.176611181 + red + black + + + + + + + + + + + + + dend_455_0_ * k3*GEF_bg_act_Ras_cplx_812_0_ + + + + + + dend_455_0_ + k3 + GEF_bg_act_Ras_cplx_812_0_ + + + + + + + + + + + inact_GEF_517_0_ + GDP_Ras_523_0_ + basal_GEF_activity_cplx_815_0_ + basal_GEF_activity_814_0_ + 1 + 727.372533039 + 514.86921992 + hotpink + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * GDP_Ras_523_0_*inact_GEF_517_0_ - k2 * basal_GEF_activity_cplx_815_0_ ) + + + + + + dend_455_0_ + + + + + k1 + GDP_Ras_523_0_ + inact_GEF_517_0_ + + + + k2 + basal_GEF_activity_cplx_815_0_ + + + + + + + + + + + + + + basal_GEF_activity_cplx_815_0_ + inact_GEF_517_0_ + GTP_Ras_521_0_ + basal_GEF_activity_814_0_ + 2 + 727.372533039 + 514.86921992 + hotpink + black + + + + + + + + + + + + + dend_455_0_ * k3*basal_GEF_activity_cplx_815_0_ + + + + + + dend_455_0_ + k3 + basal_GEF_activity_cplx_815_0_ + + + + + + + + + + + GEF_p_519_0_ + GDP_Ras_523_0_ + GEF_p_act_Ras_cplx_818_0_ + GEF_p_act_Ras_817_0_ + 1 + 786.409717341 + 660.498321744 + red + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * GDP_Ras_523_0_*GEF_p_519_0_ - k2 * GEF_p_act_Ras_cplx_818_0_ ) + + + + + + dend_455_0_ + + + + + k1 + GDP_Ras_523_0_ + GEF_p_519_0_ + + + + k2 + GEF_p_act_Ras_cplx_818_0_ + + + + + + + + + + + + + + GEF_p_act_Ras_cplx_818_0_ + GEF_p_519_0_ + GTP_Ras_521_0_ + GEF_p_act_Ras_817_0_ + 2 + 786.409717341 + 660.498321744 + red + black + + + + + + + + + + + + + dend_455_0_ * k3*GEF_p_act_Ras_cplx_818_0_ + + + + + + dend_455_0_ + k3 + GEF_p_act_Ras_cplx_818_0_ + + + + + + + + + + + GAP_527_0_ + GTP_Ras_521_0_ + GAP_inact_Ras_cplx_821_0_ + GAP_inact_Ras_820_0_ + 1 + 860.531941507 + 580.727190183 + red + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * GTP_Ras_521_0_*GAP_527_0_ - k2 * GAP_inact_Ras_cplx_821_0_ ) + + + + + + dend_455_0_ + + + + + k1 + GTP_Ras_521_0_ + GAP_527_0_ + + + + k2 + GAP_inact_Ras_cplx_821_0_ + + + + + + + + + + + + + + GAP_inact_Ras_cplx_821_0_ + GAP_527_0_ + GDP_Ras_523_0_ + GAP_inact_Ras_820_0_ + 2 + 860.531941507 + 580.727190183 + red + black + + + + + + + + + + + + + dend_455_0_ * k3*GAP_inact_Ras_cplx_821_0_ + + + + + + dend_455_0_ + k3 + GAP_inact_Ras_cplx_821_0_ + + + + + + + + + + + CaM_GEF_531_0_ + GDP_Ras_523_0_ + CaM_GEF_act_Ras_cplx_824_0_ + CaM_GEF_act_Ras_823_0_ + 1 + 677.977910319 + 571.528911555 + red + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * GDP_Ras_523_0_*CaM_GEF_531_0_ - k2 * CaM_GEF_act_Ras_cplx_824_0_ ) + + + + + + dend_455_0_ + + + + + k1 + GDP_Ras_523_0_ + CaM_GEF_531_0_ + + + + k2 + CaM_GEF_act_Ras_cplx_824_0_ + + + + + + + + + + + + + + CaM_GEF_act_Ras_cplx_824_0_ + CaM_GEF_531_0_ + GTP_Ras_521_0_ + CaM_GEF_act_Ras_823_0_ + 2 + 677.977910319 + 571.528911555 + red + black + + + + + + + + + + + + + dend_455_0_ * k3*CaM_GEF_act_Ras_cplx_824_0_ + + + + + + dend_455_0_ + k3 + CaM_GEF_act_Ras_cplx_824_0_ + + + + + + + + + + + PKA_active_567_0_ + inact_GEF_517_0_ + PKA_phosph_GEF_cplx_827_0_ + PKA_phosph_GEF_826_0_ + 1 + 541.126442191 + 369.192454756 + red + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * inact_GEF_517_0_*PKA_active_567_0_ - k2 * PKA_phosph_GEF_cplx_827_0_ ) + + + + + + dend_455_0_ + + + + + k1 + inact_GEF_517_0_ + PKA_active_567_0_ + + + + k2 + PKA_phosph_GEF_cplx_827_0_ + + + + + + + + + + + + + + PKA_phosph_GEF_cplx_827_0_ + PKA_active_567_0_ + inact_GEF_p_529_0_ + PKA_phosph_GEF_826_0_ + 2 + 541.126442191 + 369.192454756 + red + black + + + + + + + + + + + + + dend_455_0_ * k3*PKA_phosph_GEF_cplx_827_0_ + + + + + + dend_455_0_ + k3 + PKA_phosph_GEF_cplx_827_0_ + + + + + + + + + + + PKA_active_567_0_ + I1_565_0_ + PKA_phosph_I1_cplx_830_0_ + PKA_phosph_I1_829_0_ + 1 + 503.014024394 + 482.348063904 + red + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * I1_565_0_*PKA_active_567_0_ - k2 * PKA_phosph_I1_cplx_830_0_ ) + + + + + + dend_455_0_ + + + + + k1 + I1_565_0_ + PKA_active_567_0_ + + + + k2 + PKA_phosph_I1_cplx_830_0_ + + + + + + + + + + + + + + PKA_phosph_I1_cplx_830_0_ + PKA_active_567_0_ + I1_p_563_0_ + PKA_phosph_I1_829_0_ + 2 + 503.014024394 + 482.348063904 + red + black + + + + + + + + + + + + + dend_455_0_ * k3*PKA_phosph_I1_cplx_830_0_ + + + + + + dend_455_0_ + k3 + PKA_phosph_I1_cplx_830_0_ + + + + + + + + + + + PP2A_551_0_ + I1_p_563_0_ + PP2A_dephospho_I1_cplx_833_0_ + PP2A_dephospho_I1_832_0_ + 1 + 386.145680614 + 305.811197065 + red + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * I1_p_563_0_*PP2A_551_0_ - k2 * PP2A_dephospho_I1_cplx_833_0_ ) + + + + + + dend_455_0_ + + + + + k1 + I1_p_563_0_ + PP2A_551_0_ + + + + k2 + PP2A_dephospho_I1_cplx_833_0_ + + + + + + + + + + + + + + PP2A_dephospho_I1_cplx_833_0_ + PP2A_551_0_ + I1_565_0_ + PP2A_dephospho_I1_832_0_ + 2 + 386.145680614 + 305.811197065 + red + black + + + + + + + + + + + + + dend_455_0_ * k3*PP2A_dephospho_I1_cplx_833_0_ + + + + + + dend_455_0_ + k3 + PP2A_dephospho_I1_cplx_833_0_ + + + + + + + + + + + PP2A_551_0_ + PP1_I1_p_561_0_ + PP2A_dephospho_PP1_I_p_cplx_836_0_ + PP2A_dephospho_PP1_I_p_835_0_ + 1 + 190.370662051 + 5.77901740624 + red + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * PP1_I1_p_561_0_*PP2A_551_0_ - k2 * PP2A_dephospho_PP1_I_p_cplx_836_0_ ) + + + + + + dend_455_0_ + + + + + k1 + PP1_I1_p_561_0_ + PP2A_551_0_ + + + + k2 + PP2A_dephospho_PP1_I_p_cplx_836_0_ + + + + + + + + + + + + + + PP2A_dephospho_PP1_I_p_cplx_836_0_ + PP2A_551_0_ + PP1_I1_571_0_ + PP2A_dephospho_PP1_I_p_835_0_ + 2 + 190.370662051 + 5.77901740624 + red + black + + + + + + + + + + + + + dend_455_0_ * k3*PP2A_dephospho_PP1_I_p_cplx_836_0_ + + + + + + dend_455_0_ + k3 + PP2A_dephospho_PP1_I_p_cplx_836_0_ + + + + + + + + + + + Tiam1_575_0_ + Rac_GDP_573_0_ + Enz1_cplx_839_0_ + Enz1_838_0_ + 1 + 561.047656362 + 607.414313378 + #cd853f + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * Rac_GDP_573_0_*Tiam1_575_0_ - k2 * Enz1_cplx_839_0_ ) + + + + + + dend_455_0_ + + + + + k1 + Rac_GDP_573_0_ + Tiam1_575_0_ + + + + k2 + Enz1_cplx_839_0_ + + + + + + + + + + + + + + Enz1_cplx_839_0_ + Tiam1_575_0_ + Rac_GTP_577_0_ + Enz1_838_0_ + 2 + 561.047656362 + 607.414313378 + #cd853f + black + + + + + + + + + + + + + dend_455_0_ * k3*Enz1_cplx_839_0_ + + + + + + dend_455_0_ + k3 + Enz1_cplx_839_0_ + + + + + + + + + + + Tiam1_575_0_ + Cdc42_GDP_579_0_ + Enz_cplx_842_0_ + Enz_Cdc42_GDP_GTP_841_0_ + 1 + 393.202317783 + 603.012494675 + #ff00ff + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * Cdc42_GDP_579_0_*Tiam1_575_0_ - k2 * Enz_cplx_842_0_ ) + + + + + + dend_455_0_ + + + + + k1 + Cdc42_GDP_579_0_ + Tiam1_575_0_ + + + + k2 + Enz_cplx_842_0_ + + + + + + + + + + + + + + Enz_cplx_842_0_ + Tiam1_575_0_ + Cdc42_479_0_ + Enz_Cdc42_GDP_GTP_841_0_ + 2 + 393.202317783 + 603.012494675 + #ff00ff + black + + + + + + + + + + + + + dend_455_0_ * k3*Enz_cplx_842_0_ + + + + + + dend_455_0_ + k3 + Enz_cplx_842_0_ + + + + + + + + + + + CaM_GEF_531_0_ + Rac_GDP_573_0_ + Enz_cplx_845_0_ + CaM_GEF_RAC_GDP_GTP_enz_844_0_ + 1 + 681.835897892 + 614.851869117 + #708090 + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * CaM_GEF_531_0_*Rac_GDP_573_0_ - k2 * Enz_cplx_845_0_ ) + + + + + + dend_455_0_ + + + + + k1 + CaM_GEF_531_0_ + Rac_GDP_573_0_ + + + + k2 + Enz_cplx_845_0_ + + + + + + + + + + + + + + Enz_cplx_845_0_ + CaM_GEF_531_0_ + Rac_GTP_577_0_ + CaM_GEF_RAC_GDP_GTP_enz_844_0_ + 2 + 681.835897892 + 614.851869117 + #708090 + black + + + + + + + + + + + + + dend_455_0_ * k3*Enz_cplx_845_0_ + + + + + + dend_455_0_ + k3 + Enz_cplx_845_0_ + + + + + + + + + + + CaMKII_thr286_503_0_ + Tiam_inact_581_0_ + Enz_cplx_848_0_ + thr_286_enz_847_0_ + 1 + 545.383150949 + 529.319978115 + #40e0d0 + black + + + + + + + + + + + + + dend_455_0_ * ( k1 * Tiam_inact_581_0_*CaMKII_thr286_503_0_ - k2 * Enz_cplx_848_0_ ) + + + + + + dend_455_0_ + + + + + k1 + Tiam_inact_581_0_ + CaMKII_thr286_503_0_ + + + + k2 + Enz_cplx_848_0_ + + + + + + + + + + + + + + Enz_cplx_848_0_ + CaMKII_thr286_503_0_ + Tiam1_575_0_ + thr_286_enz_847_0_ + 2 + 545.383150949 + 529.319978115 + #40e0d0 + black + + + + + + + + + + + + + dend_455_0_ * k3*Enz_cplx_848_0_ + + + + + + dend_455_0_ + k3 + Enz_cplx_848_0_ + + + + + + + + + + + + + dend_455_0_ + dend_455_0_ + white + + + + + + + + + + + + + + + + + + + + + + + + + + + dend_455_0_ + dend_455_0_ + white + + + + + + + + + + + + + + + + + + + + + + + + + + + + + dend_455_0_ + dend_455_0_ + white + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/python/genesis/kkit_objects_example.g b/tests/data/kkit_objects_example.g similarity index 100% rename from tests/python/genesis/kkit_objects_example.g rename to tests/data/kkit_objects_example.g diff --git a/tests/python/chem_models/mkp1_feedback_effects_acc4.g b/tests/data/mkp1_feedback_effects_acc4.g similarity index 100% rename from tests/python/chem_models/mkp1_feedback_effects_acc4.g rename to tests/data/mkp1_feedback_effects_acc4.g diff --git a/tests/python/chem_models/mkp1_feedback_effects_acc4.xml b/tests/data/mkp1_feedback_effects_acc4.xml similarity index 100% rename from tests/python/chem_models/mkp1_feedback_effects_acc4.xml rename to tests/data/mkp1_feedback_effects_acc4.xml diff --git a/tests/data/prot_wt.xml b/tests/data/prot_wt.xml new file mode 100644 index 00000000..61c209c6 --- /dev/null +++ b/tests/data/prot_wt.xml @@ -0,0 +1 @@ +tot_CaMKII 650tot_CaM_CaMKII 650basal_CaMKII 650CaMKII_thr286_CaM 650CaMKII_CaM 650CaMKII_thr286 650CaMKII 650CaMKII_thr305 650CaMKII_p_p_p 650CaMKII_xchange 650actCaMKII 650GEF_Gprot_bg 150inact_GEF 150GEF_p 150GTP_Ras 22GDP_Ras 22GAP_p 200GAP 200inact_GEF_p 150CaM_GEF 200CaM 17CaM_Ca3 17CaM_Ca2 17CaM_Ca 17CaM_Ca4 17CaM_xchange 17tot_auto 50<_286P>_286P 50CaM_CaN 87PP2A 36CaN 58Ca2_CaN 58Ca 0.04PP1_active 38PP1_I1_p 65I1_p 27I1 27PKA_active 45PKC_active 84PP1_I1 65Rac_GDP 22Tiam1 177Rac_GTP 22Cdc42_GDP 22Tiam_inact 177IRSp53_Rac_a 82IRSp53_dimer 60IP_clx 60IRSp53 60Rad 0curv_IRSp53 0Ipool 60sort 0IRSp53_a 60Cdc42 22Eps8 80IRSp53_m 60sort_func 0detach 0VASP 42Gactin 0conv 0Rac_inact 22Cdc42_inact 22Rac_pool 22Cdc42_pool 22 diff --git a/tests/issues/issue_69.py b/tests/issues/issue_69.py deleted file mode 100644 index 93388421..00000000 --- a/tests/issues/issue_69.py +++ /dev/null @@ -1,15 +0,0 @@ -# -*- coding: utf-8 -*- -# Github issue #69, Also BhallaLab/moose-gui#3. - -import moose -print( '[INFO] Importing moose from %s' % moose.__file__ ) -print( '[INFO] Version : %s' % moose.__version__ ) -moose.loadModel('../data/acc27.g','/acc27_1',"gsl") -compts = moose.wildcardFind('/acc27_1/##[ISA=ChemCompt]') -for compt in compts: - if moose.exists(compt.path+'/stoich'): - st = moose.element(compt.path+'/stoich') - #print " stoich ksolve ",st.ksolve.path - if moose.exists((st.ksolve).path): - moose.delete(st.ksolve) - moose.delete(st) diff --git a/tests/python/OSC_diff_vols.g b/tests/py_moose/OSC_diff_vols.g similarity index 100% rename from tests/python/OSC_diff_vols.g rename to tests/py_moose/OSC_diff_vols.g diff --git a/tests/python/benchmark.py b/tests/py_moose/benchmark.py similarity index 100% rename from tests/python/benchmark.py rename to tests/py_moose/benchmark.py diff --git a/tests/python/chan_proto.py b/tests/py_moose/chan_proto.py similarity index 100% rename from tests/python/chan_proto.py rename to tests/py_moose/chan_proto.py diff --git a/tests/python/models.py b/tests/py_moose/models.py similarity index 100% rename from tests/python/models.py rename to tests/py_moose/models.py diff --git a/tests/python/param_chan.py b/tests/py_moose/param_chan.py similarity index 100% rename from tests/python/param_chan.py rename to tests/py_moose/param_chan.py diff --git a/tests/python/params.py b/tests/py_moose/params.py similarity index 100% rename from tests/python/params.py rename to tests/py_moose/params.py diff --git a/tests/python/run_mumble.sh b/tests/py_moose/run_mumble.sh similarity index 100% rename from tests/python/run_mumble.sh rename to tests/py_moose/run_mumble.sh diff --git a/tests/python/soma.p b/tests/py_moose/soma.p similarity index 100% rename from tests/python/soma.p rename to tests/py_moose/soma.p diff --git a/tests/python/streamer.py b/tests/py_moose/streamer.py similarity index 100% rename from tests/python/streamer.py rename to tests/py_moose/streamer.py diff --git a/tests/python/test_GraupnerBrunel2012_STDPfromCaPlasticity.py b/tests/py_moose/test_GraupnerBrunel2012_STDPfromCaPlasticity.py similarity index 99% rename from tests/python/test_GraupnerBrunel2012_STDPfromCaPlasticity.py rename to tests/py_moose/test_GraupnerBrunel2012_STDPfromCaPlasticity.py index b01a3408..598eb5a7 100644 --- a/tests/python/test_GraupnerBrunel2012_STDPfromCaPlasticity.py +++ b/tests/py_moose/test_GraupnerBrunel2012_STDPfromCaPlasticity.py @@ -14,7 +14,7 @@ moose.seed( 10 ) -def main(): +def test_GB2012_STDP(): """ Simulate a pseudo-STDP protocol and plot the STDP kernel that emerges from Ca plasticity of Graupner and Brunel 2012. @@ -222,5 +222,8 @@ def make_neuron_spike(nrnidx,I=1e-7,duration=1e-3): expNew = (0.014485615086785508, 0.16206703949072981) assert np.isclose(got, expNew).all(), 'Expected: %s, Got: %s' % (str(expNew), str(got)) +def main(): + test_GB2012_STDP() + if __name__ == '__main__': main() diff --git a/tests/python/test_Xchan1.py b/tests/py_moose/test_Xchan1.py similarity index 97% rename from tests/python/test_Xchan1.py rename to tests/py_moose/test_Xchan1.py index d1eb3511..53320fe4 100644 --- a/tests/python/test_Xchan1.py +++ b/tests/py_moose/test_Xchan1.py @@ -24,7 +24,6 @@ ## ######################################################################### - import math import numpy as np import moose @@ -63,7 +62,7 @@ def makeModel(): s.concInit = 0.001 chanPool.nInit = 1000.0 # Flux (mM/s) = permeability * N * (conc_out - conc_in ) - chan.permeability = 0.1 * chanPool.volume * 6.022e23 *0.001 / chanPool.nInit + chan.permeability = 0.1 * chanPool.volume * 6.022e23 / chanPool.nInit ##################################################################### fixXreacs.fixXreacs( '/model' ) @@ -111,7 +110,7 @@ def almostEq( a, b ): #print a, b, (a-b)/(a+b) return abs(a-b)/(a+b) < 5e-5 -def main( standalone = False ): +def test_xchan( standalone = False ): runtime = 100 displayInterval = 2 makeModel() @@ -150,4 +149,4 @@ def main( standalone = False ): # Run the 'main' if this script is executed standalone. if __name__ == '__main__': - main( standalone = True ) + test_xchan( standalone = True ) diff --git a/tests/python/test_Xdiff1.py b/tests/py_moose/test_Xdiff1.py similarity index 99% rename from tests/python/test_Xdiff1.py rename to tests/py_moose/test_Xdiff1.py index 6a7545c9..f1239baf 100644 --- a/tests/python/test_Xdiff1.py +++ b/tests/py_moose/test_Xdiff1.py @@ -124,6 +124,9 @@ def main( standalone = False ): assert almostEq( 2 * s.conc, es.conc ), "%g=?%g" % (2*s.conc, es.conc) moose.delete( '/model' ) +def test_xdiff1(): + main() + # Run the 'main' if this script is executed standalone. if __name__ == '__main__': - main( standalone = True ) + main() diff --git a/tests/python/test_Xenz1.py b/tests/py_moose/test_Xenz1.py similarity index 96% rename from tests/python/test_Xenz1.py rename to tests/py_moose/test_Xenz1.py index 13b7d4b8..194a296c 100644 --- a/tests/python/test_Xenz1.py +++ b/tests/py_moose/test_Xenz1.py @@ -100,11 +100,10 @@ def almostEq( a, b ): #print a, b, (a-b)/(a+b) return abs(a-b)/(a+b) < 5e-5 -def main( standalone = False ): +def test_xreac1(): for i in range( 10, 18 ): moose.setClock( i, 0.001 ) runtime = 100 - displayInterval = 2 makeModel() moose.reinit() moose.start( runtime ) @@ -112,6 +111,5 @@ def main( standalone = False ): moose.element( '/model/endo/sub' ).n ) ) moose.delete( '/model' ) -# Run the 'main' if this script is executed standalone. if __name__ == '__main__': - main( standalone = True ) + test_xreac1() diff --git a/tests/python/test_Xreacs2.py b/tests/py_moose/test_Xreacs2.py similarity index 96% rename from tests/python/test_Xreacs2.py rename to tests/py_moose/test_Xreacs2.py index c02a2cc3..9673362c 100644 --- a/tests/python/test_Xreacs2.py +++ b/tests/py_moose/test_Xreacs2.py @@ -11,7 +11,7 @@ def countCrossings( plot, thresh ): # print (vec[:-1] <= thresh) return sum( (vec[:-1] < thresh) * (vec[1:] >= thresh ) ) -def main( standalone = False ): +def test_xreac2(): mfile = os.path.join( os.path.dirname( __file__), 'OSC_diff_vols.g' ) runtime = 4000.0 modelId = moose.loadModel( mfile, 'model', 'ee' ) @@ -48,6 +48,9 @@ def main( standalone = False ): assert( nCrossings == 4 ), "Expected 4, got %d" % nCrossings moose.delete( '/model' ) +def main(): + test_xreac2() + # Run the 'main' if this script is executed standalone. if __name__ == '__main__': - main( standalone = True ) + main() diff --git a/tests/python/test_Xreacs3.py b/tests/py_moose/test_Xreacs3.py similarity index 98% rename from tests/python/test_Xreacs3.py rename to tests/py_moose/test_Xreacs3.py index 889e0b1c..410bdc5c 100644 --- a/tests/python/test_Xreacs3.py +++ b/tests/py_moose/test_Xreacs3.py @@ -93,7 +93,7 @@ def makeModel(): def almostEq( a, b ): return abs(a-b)/(a+b) < 5e-5 -def main( standalone = False ): +def test_xreac3(): runtime = 100 makeModel() moose.reinit() @@ -102,6 +102,9 @@ def main( standalone = False ): moose.element( '/model/endo/s' ).conc ) ) moose.delete( '/model' ) +def main(): + test_xreac3() + # Run the 'main' if this script is executed standalone. if __name__ == '__main__': - main( standalone = True ) + main() diff --git a/tests/python/test_Xreacs4.py b/tests/py_moose/test_Xreacs4.py similarity index 97% rename from tests/python/test_Xreacs4.py rename to tests/py_moose/test_Xreacs4.py index d96497b9..2a5083b6 100644 --- a/tests/python/test_Xreacs4.py +++ b/tests/py_moose/test_Xreacs4.py @@ -78,9 +78,8 @@ def makeModel(): def almostEq( a, b ): return abs(a-b)/(a+b) < 5e-5 -def main( standalone = False ): +def test_xreac4(): runtime = 100 - displayInterval = 2 makeModel() moose.reinit() moose.start( runtime ) @@ -88,6 +87,9 @@ def main( standalone = False ): moose.element( '/model/endo/s' ).conc ) ) moose.delete( '/model' ) +def main(): + test_xreac4() + # Run the 'main' if this script is executed standalone. if __name__ == '__main__': - main( standalone = True ) + main() diff --git a/tests/python/test_Xreacs4a.py b/tests/py_moose/test_Xreacs4a.py similarity index 95% rename from tests/python/test_Xreacs4a.py rename to tests/py_moose/test_Xreacs4a.py index ffad55b3..8ee25d88 100644 --- a/tests/python/test_Xreacs4a.py +++ b/tests/py_moose/test_Xreacs4a.py @@ -78,9 +78,8 @@ def makeModel(): def almostEq( a, b ): return abs(a-b)/(a+b) < 5e-5 -def main( standalone = False ): +def test_xreac4(): runtime = 200 - displayInterval = 2 makeModel() moose.reinit() moose.start( runtime ) @@ -88,7 +87,8 @@ def main( standalone = False ): moose.element( '/model/endo/s' ).conc ) ) moose.delete( '/model' ) +def main(): + test_xreac4() -# Run the 'main' if this script is executed standalone. if __name__ == '__main__': - main( standalone = True ) + main() diff --git a/tests/python/test_Xreacs5.py b/tests/py_moose/test_Xreacs5.py similarity index 98% rename from tests/python/test_Xreacs5.py rename to tests/py_moose/test_Xreacs5.py index 60acd3cf..eeee255b 100644 --- a/tests/python/test_Xreacs5.py +++ b/tests/py_moose/test_Xreacs5.py @@ -83,7 +83,7 @@ def almostEq( a, b ): #print a, b, (a-b)/(a+b) return abs(a-b)/(a+b) < 5e-5 -def main( standalone = False ): +def test_xreac5(): for i in range( 10, 18): moose.setClock( i, 0.001 ) runtime = 100 @@ -100,4 +100,4 @@ def main( standalone = False ): # Run the 'main' if this script is executed standalone. if __name__ == '__main__': - main( standalone = True ) + test_xreac5() diff --git a/tests/python/test_Xreacs5a.py b/tests/py_moose/test_Xreacs5a.py similarity index 85% rename from tests/python/test_Xreacs5a.py rename to tests/py_moose/test_Xreacs5a.py index 09a2c17e..631ea28b 100644 --- a/tests/python/test_Xreacs5a.py +++ b/tests/py_moose/test_Xreacs5a.py @@ -72,28 +72,23 @@ def makeModel(): edsolve.buildMeshJunctions( dsolve ) - plot1 = moose.Table2( '/model/plot1' ) - plot2 = moose.Table2( '/model/plot2' ) - moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) - moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) - plot3 = moose.Table2( '/model/plot3' ) - plot4 = moose.Table2( '/model/plot4' ) - moose.connect( '/model/plot3', 'requestOut', s, 'getConc' ) - moose.connect( '/model/plot4', 'requestOut', es, 'getConc' ) def almostEq( a, b ): return abs(a-b)/(a+b) < 5e-5 -def main( standalone = False ): +def test_xreac5a(): runtime = 200 - displayInterval = 2 makeModel() moose.reinit() moose.start( runtime ) assert( almostEq( 2.0 * moose.element( 'model/compartment/s' ).n, moose.element( '/model/endo/s' ).n ) ) - moose.delete( '/model' ) + + +def main(): + test_xreac5a() + # Run the 'main' if this script is executed standalone. if __name__ == '__main__': - main( standalone = True ) + main() diff --git a/tests/python/test_Xreacs6.py b/tests/py_moose/test_Xreacs6.py similarity index 97% rename from tests/python/test_Xreacs6.py rename to tests/py_moose/test_Xreacs6.py index 06695267..03bfe48d 100644 --- a/tests/python/test_Xreacs6.py +++ b/tests/py_moose/test_Xreacs6.py @@ -82,11 +82,10 @@ def almostEq( a, b ): #print a, b, (a-b)/(a+b) return abs(a-b)/(a+b) < 5e-5 -def main( standalone = False ): +def test_xreac6(): for i in range( 10, 18): moose.setClock( i, 0.01 ) runtime = 100 - displayInterval = 2 makeModel() moose.reinit() moose.start( runtime ) @@ -94,6 +93,9 @@ def main( standalone = False ): moose.element( '/model/endo/s' ).conc ) ) moose.delete( '/model' ) +def main(): + test_xreac6() + # Run the 'main' if this script is executed standalone. if __name__ == '__main__': - main( standalone = True ) + main() diff --git a/tests/python/test_Xreacs7.py b/tests/py_moose/test_Xreacs7.py similarity index 89% rename from tests/python/test_Xreacs7.py rename to tests/py_moose/test_Xreacs7.py index 5df168bc..59bf476f 100644 --- a/tests/python/test_Xreacs7.py +++ b/tests/py_moose/test_Xreacs7.py @@ -84,23 +84,22 @@ def makeModel(): plot1 = moose.Table2( '/model/plot1' ) plot2 = moose.Table2( '/model/plot2' ) plot3 = moose.Table2( '/model/plot3' ) - moose.connect( '/model/plot1', 'requestOut', u, 'getN' ) - moose.connect( '/model/plot2', 'requestOut', et, 'getN' ) - moose.connect( '/model/plot3', 'requestOut', es, 'getN' ) + moose.connect( plot1, 'requestOut', u, 'getN' ) + moose.connect( plot2, 'requestOut', et, 'getN' ) + moose.connect( plot3, 'requestOut', es, 'getN' ) plot4 = moose.Table2( '/model/plot4' ) plot5 = moose.Table2( '/model/plot5' ) plot6 = moose.Table2( '/model/plot6' ) - moose.connect( '/model/plot4', 'requestOut', u, 'getConc' ) - moose.connect( '/model/plot5', 'requestOut', et, 'getConc' ) - moose.connect( '/model/plot6', 'requestOut', es, 'getConc' ) + moose.connect( plot4, 'requestOut', u, 'getConc' ) + moose.connect( plot5, 'requestOut', et, 'getConc' ) + moose.connect( plot6, 'requestOut', es, 'getConc' ) def almostEq( a, b ): #print a, b, (a-b)/(a+b) return abs(a-b)/(a+b) < 5e-5 -def main( standalone = False ): +def test_xreacs7(): runtime = 100 - displayInterval = 2 makeModel() moose.reinit() moose.start( runtime ) @@ -111,4 +110,4 @@ def main( standalone = False ): # Run the 'main' if this script is executed standalone. if __name__ == '__main__': - main( standalone = True ) + test_xreacs7() diff --git a/tests/python/test_Xreacs8.py b/tests/py_moose/test_Xreacs8.py similarity index 80% rename from tests/python/test_Xreacs8.py rename to tests/py_moose/test_Xreacs8.py index d2ef6de3..12c55ead 100644 --- a/tests/python/test_Xreacs8.py +++ b/tests/py_moose/test_Xreacs8.py @@ -75,35 +75,23 @@ def makeModel(): estoich.dsolve = edsolve estoich.path = "/model/endo/##" assert( edsolve.numPools == 1 ) - edsolve.buildMeshJunctions( dsolve ) - plot1 = moose.Table2( '/model/plot1' ) - plot2 = moose.Table2( '/model/plot2' ) - plot3 = moose.Table2( '/model/plot3' ) - moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) - moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) - moose.connect( '/model/plot3', 'requestOut', '/model/compartment/s_xfer_endo', 'getN' ) - plot4 = moose.Table2( '/model/plot4' ) - plot5 = moose.Table2( '/model/plot5' ) - plot6 = moose.Table2( '/model/plot6' ) - moose.connect( '/model/plot4', 'requestOut', s, 'getConc' ) - moose.connect( '/model/plot5', 'requestOut', es, 'getConc' ) - moose.connect( '/model/plot6', 'requestOut', '/model/compartment/s_xfer_endo', 'getConc' ) - def almostEq( a, b ): return abs(a-b)/(a+b) < 5e-5 -def main( standalone = False ): +def test_xreac8(): runtime = 100 makeModel() moose.reinit() moose.start( runtime ) assert( almostEq( moose.element( 'model/compartment/s' ).conc, moose.element( '/model/endo/s' ).conc ) ) - moose.delete( '/model' ) + +def main(): + test_xreac8() # Run the 'main' if this script is executed standalone. if __name__ == '__main__': - main( standalone = True ) + main() diff --git a/tests/py_moose/test_accessing_existing_paths.py b/tests/py_moose/test_accessing_existing_paths.py new file mode 100644 index 00000000..f1f673af --- /dev/null +++ b/tests/py_moose/test_accessing_existing_paths.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +import moose +import re + +def fixPath(path): + path = re.sub(r'/+', '/', path) + return path + +def test_existing_path(): + paths = [ '/a' + , '//a' + , '/a/b' + , '/a/b/' + , '//a//b/////' + , '/a/./b' + , '///a/././b' + ] + expectedPath = [fixPath(p) for p in paths] + + expectedChanges = zip(paths, expectedPath) + + for p in expectedPath: + print( 'Accessing %s' % p ) + try: + moose.Neutral(p) + except Exception as e: + print( 'Same path access by element' ) + moose.element( p ) + + foundPath = [] + for p in moose.wildcardFind('/##'): + if "/a" in p.path: + foundPath.append(p.path) + + testFailed = False + for f in foundPath: + f = re.sub(r'\[\d+\]', '', f) + if f not in expectedPath: + testFailed = True + + assert not testFailed, "Test failed on paths" + +def main(): + test_existing_path() + +if __name__ == '__main__': + main() diff --git a/tests/python/test_connectionLists.py b/tests/py_moose/test_connectionLists.py similarity index 97% rename from tests/python/test_connectionLists.py rename to tests/py_moose/test_connectionLists.py index fcd77867..7441d7bf 100644 --- a/tests/python/test_connectionLists.py +++ b/tests/py_moose/test_connectionLists.py @@ -15,10 +15,7 @@ __email__ = "dilawars@ncbs.res.in" __status__ = "Development" -import sys -import os import moose -import numpy as np params = { 'Rm': 1e10, @@ -154,15 +151,15 @@ def makeRaster( network ): moose.connect(network, 'spikeOut', raster, 'spike', 'OneToOne') return raster -def main(): - mod = moose.Neutral( '/model' ) +def test_connection_list(): + moose.Neutral( '/model' ) inhib, output = makeGlobalBalanceNetwork() iraster = makeRaster( inhib ) - oraster = makeRaster( output ) + makeRaster( output ) moose.reinit() moose.start( params['runtime'] ) for i in range( len(iraster.vec) ): print( iraster.vec[i].vector ) if __name__ == '__main__': - main() + test_connection_list() diff --git a/tests/python/test_cylinder_diffusion_gsolve+dsolve.py b/tests/py_moose/test_cylinder_diffusion_gsolve+dsolve.py similarity index 98% rename from tests/python/test_cylinder_diffusion_gsolve+dsolve.py rename to tests/py_moose/test_cylinder_diffusion_gsolve+dsolve.py index db3dd773..7b09309c 100644 --- a/tests/python/test_cylinder_diffusion_gsolve+dsolve.py +++ b/tests/py_moose/test_cylinder_diffusion_gsolve+dsolve.py @@ -74,7 +74,7 @@ def makeModel(): for i in range( num ): d.vec[i].concInit = concA * 2 * i / num -def main(): +def test_diffusion_gsolve_dsolve(): """ This example illustrates how to set up a diffusion/transport model with a simple reaction-diffusion system in a tapering cylinder: @@ -141,6 +141,9 @@ def main(): rerror = np.abs( error ) / expected assert np.allclose(got, expected, atol=1e-3), "Got %s, expected %s" % (got, expected) +def main(): + test_diffusion_gsolve_dsolve() + # Run the 'main' if this script is executed standalone. if __name__ == '__main__': main() diff --git a/tests/python/test_difshells.py b/tests/py_moose/test_difshells.py similarity index 98% rename from tests/python/test_difshells.py rename to tests/py_moose/test_difshells.py index d9e29fe5..ff050bce 100644 --- a/tests/python/test_difshells.py +++ b/tests/py_moose/test_difshells.py @@ -119,7 +119,7 @@ def addOneChan(chanpath, gbar,comp): moose.connect(chan, "channelOut", comp, "handleChannel") return chan -if __name__ == '__main__': +def test_diffshell(): lib = moose.Neutral('/library') for tick in range(0, 7): moose.setClock(tick, dt) @@ -212,3 +212,8 @@ def addOneChan(chanpath, gbar,comp): header += ' difshell_' + str(i) + '_difbuff_' + str(j) np.savetxt(fname, res, header=header, comments='') +def main(): + test_diffshell() + +if __name__ == '__main__': + main() diff --git a/tests/python/test_docs.py b/tests/py_moose/test_docs.py similarity index 92% rename from tests/python/test_docs.py rename to tests/py_moose/test_docs.py index cd877d99..e437a965 100644 --- a/tests/python/test_docs.py +++ b/tests/py_moose/test_docs.py @@ -18,8 +18,11 @@ print( '[INFO] Using moose from %s' % moose.__file__ ) print( '[INFO] Version : %s' % moose.version( ) ) -def main( ): +def test_doc( ): moose.doc( 'Compartment' ) +def main(): + test_doc() + if __name__ == '__main__': main() diff --git a/tests/python/test_dose_response.py b/tests/py_moose/test_dose_response.py similarity index 94% rename from tests/python/test_dose_response.py rename to tests/py_moose/test_dose_response.py index 4a897301..be6132a6 100644 --- a/tests/python/test_dose_response.py +++ b/tests/py_moose/test_dose_response.py @@ -57,7 +57,7 @@ def getState( ksolve, state, vol): return state.stateType, state.solutionStatus, a, vector -def main(): +def test_dose_response(): # Setup parameters for simulation and plotting simdt= 1e-2 plotDt= 1 @@ -71,15 +71,15 @@ def main(): # Load Model and set up the steady state solver. # model = sys.argv[1] # To load model from a file. - model = os.path.join( sdir_, 'chem_models/19085.cspace' ) + model = os.path.join(sdir_, '..', 'data', '19085.cspace') modelPath, modelName, modelType = parseModelName(model) outputDir = modelPath modelId = moose.loadModel(model, 'model', 'ee') dosePath = '/model/kinetics/b/DabX' # The dose entity - ksolve, state = setupSteadyState( simdt, plotDt) - vol = moose.element( '/model/kinetics' ).volume + ksolve, state = setupSteadyState(simdt, plotDt) + vol = moose.element('/model/kinetics' ).volume iterInit = 100 solutionVector = [] factorArr = [] @@ -112,5 +112,8 @@ def main(): assert np.isclose(got, expected, atol=1e-2).all(), "Got %s, expected %s" % (got, expected) print( joint ) +def main(): + test_dose_response() + if __name__ == '__main__': main() diff --git a/tests/python/test_expr_parser.py b/tests/py_moose/test_expr_parser.py similarity index 99% rename from tests/python/test_expr_parser.py rename to tests/py_moose/test_expr_parser.py index fabbc28e..a2be0deb 100644 --- a/tests/python/test_expr_parser.py +++ b/tests/py_moose/test_expr_parser.py @@ -339,8 +339,11 @@ def run(): print('doty', doty ) print( '[INFO] Run is over') -if __name__ == '__main__': +def test_expr_parser(): moose.Neutral( '/library' ) moose.Neutral( '/model' ) run() print( 'All done' ) + +if __name__ == '__main__': + test_expr_parser() diff --git a/tests/python/test_function.py b/tests/py_moose/test_function.py similarity index 78% rename from tests/python/test_function.py rename to tests/py_moose/test_function.py index 79e94534..db66dcee 100644 --- a/tests/python/test_function.py +++ b/tests/py_moose/test_function.py @@ -24,7 +24,6 @@ def create_func( funcname, expr ): def test_var_order(): """The y values are one step behind the x values because of scheduling sequences""" - moose.delete( '/' ) nsteps = 5 simtime = nsteps dt = 1.0 @@ -39,21 +38,25 @@ def test_var_order(): x0.startTime = 0.0 x0.stopTime = simtime x0.stepPosition = 0.0 + print('x0', x0.vector) inputs /= 10 x1 = moose.StimulusTable('/x1') x1.vector = inputs x1.startTime = 0.0 x1.stopTime = simtime x1.stepPosition = 0.0 + print('x1', x1.vector) inputs /= 10 y0 = moose.StimulusTable('/y0') y0.vector = inputs y0.startTime = 0.0 y0.stopTime = simtime y0.stepPosition = 0.0 + print('y0', y0.vector) inputs /= 10 y1 = moose.StimulusTable('/y1') y1.vector = inputs + print('y1', y1.vector) y1.startTime = 0.0 y1.startTime = 0.0 y1.stopTime = simtime @@ -71,6 +74,8 @@ def test_var_order(): moose.reinit() moose.start(simtime) expected = [0, 1.1, 2.211, 3.322, 4.433, 5.544] + print('sum: ', x0.vector + x1.vector + y0.vector + y1.vector) + print('got', z1.vector) assert np.allclose(z1.vector, expected), "Excepted %s, got %s" % (expected, z1.vector ) print( 'Passed order vars' ) @@ -97,21 +102,25 @@ def test_rand( ): moose.seed( 10 ) f, t = create_func( 'random', 'rnd()') moose.reinit() - moose.start(1) - expected = [0.49458993, 0.44301495, 0.58332174, 0.70920801, 0.26360285, - 0.68381843, 0.33607158, 0.19812181, 0.87761494, 0.54088093, - 0.41366738] - assert np.isclose(t.vector, expected ).all(), t.vector - print( 'Passed test random' ) + moose.start(1000) + print(np.mean(t.vector), np.std(t.vector), 'xxx') + assert abs(np.mean(t.vector) - 0.5) < 0.01 + assert np.std(t.vector) < 0.3 +## expected = [0.29876116, 0.49458993, 0.83191136, 0.02517173, 0.26556613, +## 0.15037787, 0.81660184, 0.89081653, 0.03061665, 0.72743551, 0.13145815] +## assert np.isclose(t.vector, expected ).all(), "Expected %s, got %s" % ( +## expected, t.vector) +## print( 'Passed test random' ) def test_fmod( ): f, t = create_func( 'fmod', 'fmod(t, 2)' ) moose.reinit() - moose.start( 20 ) + moose.start(20) y = t.vector + print(y) assert (np.fmod(y, 2) == y).all() - assert(np.isclose(np.max(y), 1.9)), np.max(y) - assert(np.isclose(np.min(y), 0.0)), np.min(y) + assert(np.isclose(np.max(y), 1.9)), "Expected 1.9 got %s" % np.max(y) + assert(np.isclose(np.min(y), 0.0)), "Expected 0.0 got %s" % np.min(y) print('Passed fmod(t,2)') diff --git a/tests/python/test_function_chemsys.py b/tests/py_moose/test_function_chemsys.py similarity index 99% rename from tests/python/test_function_chemsys.py rename to tests/py_moose/test_function_chemsys.py index fabbc28e..305809d7 100644 --- a/tests/python/test_function_chemsys.py +++ b/tests/py_moose/test_function_chemsys.py @@ -339,8 +339,14 @@ def run(): print('doty', doty ) print( '[INFO] Run is over') -if __name__ == '__main__': +def test_function_chemsys(): moose.Neutral( '/library' ) moose.Neutral( '/model' ) run() print( 'All done' ) + +def main(): + test_function_chemsys() + +if __name__ == '__main__': + main() diff --git a/tests/python/test_function_controls_reac_rate.py b/tests/py_moose/test_function_controls_reac_rate.py similarity index 99% rename from tests/python/test_function_controls_reac_rate.py rename to tests/py_moose/test_function_controls_reac_rate.py index 0c885b38..aee588d8 100644 --- a/tests/python/test_function_controls_reac_rate.py +++ b/tests/py_moose/test_function_controls_reac_rate.py @@ -19,7 +19,6 @@ import numpy as np import moose -import pylab import rdesigneur as rd plot_ = False diff --git a/tests/py_moose/test_function_namedvars.py b/tests/py_moose/test_function_namedvars.py new file mode 100644 index 00000000..d0eccb91 --- /dev/null +++ b/tests/py_moose/test_function_namedvars.py @@ -0,0 +1,121 @@ +# -*- coding: utf-8 -*- +# Test moose.Function with namedvar and without wrapper. + +__author__ = "Dilawar Singh" +__copyright__ = "Copyright 2019-, Dilawar Singh" +__maintainer__ = "Dilawar Singh" +__email__ = "dilawars@ncbs.res.in" + +import numpy as np +import moose +print( "[INFO ] Using moose %s form %s" % (moose.version(), moose.__file__) ) + +def create_func( funcname, expr ): + f = moose.Function( funcname ) + f.expr = expr + t = moose.Table( funcname + 'tab' ) + t.connect('requestOut', f, 'getValue') + moose.setClock( f.tick, 0.1) + moose.setClock( t.tick, 0.1) + return f, t + +def test_var_order(): + nsteps = 5 + simtime = nsteps + dt = 1.0 + fn1 = moose.Function('/fn1') + fn1.expr = 'B+A+y0+y1' + inputs = np.arange(0, nsteps+1, 1.0) + x0 = moose.StimulusTable('/x0') + x0.vector = inputs + x0.startTime = 0.0 + x0.stopTime = simtime + x0.stepPosition = 0.0 + print('x0', x0.vector) + inputs /= 10 + x1 = moose.StimulusTable('/x1') + x1.vector = inputs + x1.startTime = 0.0 + x1.stopTime = simtime + x1.stepPosition = 0.0 + print('x1', x1.vector) + inputs /= 10 + y0 = moose.StimulusTable('/y0') + y0.vector = inputs + y0.startTime = 0.0 + y0.stopTime = simtime + y0.stepPosition = 0.0 + print('y0', y0.vector) + inputs /= 10 + y1 = moose.StimulusTable('/y1') + y1.vector = inputs + print('y1', y1.vector) + y1.startTime = 0.0 + y1.startTime = 0.0 + y1.stopTime = simtime + y1.stepPosition = 0.0 + moose.connect(x0, 'output', fn1['A'], 'input') + moose.connect(x1, 'output', fn1['B'], 'input') + moose.connect(fn1, 'requestOut', y0, 'getOutputValue') + moose.connect(fn1, 'requestOut', y1, 'getOutputValue') + + z1 = moose.Table('/z1') + moose.connect(z1, 'requestOut', fn1, 'getValue') + for ii in range(32): + moose.setClock(ii, dt) + moose.reinit() + moose.start(simtime) + expected = [0, 1.1, 2.211, 3.322, 4.433, 5.544] + assert np.allclose(z1.vector, expected), "Excepted %s, got %s" % (expected, z1.vector ) + print( 'Passed order vars' ) + +def test_t( ): + f, t = create_func( 'funct', 't/2.0') + moose.reinit() + moose.start(1) + y = t.vector + d = np.diff( y[1:] ) + assert np.mean(d) == d[0] + print( 'Passed t/2' ) + +def test_trig( ): + f, t = create_func('func2', '(sin(t)^2+cos(t)^2)-1') + moose.reinit() + moose.start( 1 ) + y = t.vector + print(y) + assert np.isclose(np.mean(y), 0.0), np.mean(y) + assert np.isclose(np.std(y), 0.0), np.std(y) + print( 'Passed sin^2 x + cos^x=1' ) + +def test_rand( ): + moose.seed( 10 ) + f, t = create_func( 'random', 'rnd()') + moose.reinit() + moose.start(1) + expected = [0.29876116, 0.49458993, 0.83191136, 0.02517173, 0.26556613, + 0.15037787, 0.81660184, 0.89081653, 0.03061665, 0.72743551, 0.13145815] + assert np.isclose(t.vector, expected ).all(), "Expected %s, got %s" % ( + expected, t.vector) + print( 'Passed test random' ) + +def test_fmod( ): + f, t = create_func( 'fmod', 'fmod(t, 2)' ) + moose.reinit() + moose.start(20) + y = t.vector + #print(y) + assert (np.fmod(y, 2) == y).all() + assert(np.isclose(np.max(y), 1.9)), "Expected 1.9 got %s" % np.max(y) + assert(np.isclose(np.min(y), 0.0)), "Expected 0.0 got %s" % np.min(y) + print('Passed fmod(t,2)') + +def main(): + test_var_order() + test_t() + test_trig() + test_rand() + test_fmod() + +if __name__ == '__main__': + main() diff --git a/tests/python/test_gsolve_parallel.py b/tests/py_moose/test_gsolve_parallel.py similarity index 94% rename from tests/python/test_gsolve_parallel.py rename to tests/py_moose/test_gsolve_parallel.py index 056762b4..667adf77 100644 --- a/tests/python/test_gsolve_parallel.py +++ b/tests/py_moose/test_gsolve_parallel.py @@ -10,7 +10,7 @@ def printCompt(compt): print( 'x0=%s, x1=%s, diffLength=%s, numDiffCompt=%d' % (compt.x0, compt.x1, compt.diffLength, compt.numDiffCompts)) -def main( nT ): +def test_gsolve_paralllel(nT=4): """ This example implements a reaction-diffusion like system which is bistable and propagates losslessly. It is based on the NEURON example @@ -44,10 +44,7 @@ def main( nT ): #Set up solvers ksolve = moose.Gsolve( '/cylinder/Gsolve' ) - try: - ksolve.numThreads = nT - except Exception as e: - print( 'OLD MOOSE. Does not support multithreading' ) + ksolve.numThreads = nT dsolve = moose.Dsolve( '/cylinder/dsolve' ) stoich = moose.Stoich( '/cylinder/stoich' ) @@ -93,10 +90,13 @@ def main( nT ): print("Time = ", time.time() - t1) assert np.isclose(res, expected, atol=1, rtol=1).all(), "Got %s, expected %s" % (res, expected) +def main(nT): + test_gsolve_paralllel(nT) + if __name__ == '__main__': import sys import multiprocessing - nT = int(multiprocessing.cpu_count() / 2) + nT = max(1, int(multiprocessing.cpu_count())) if len(sys.argv) > 1: nT = int(sys.argv[1]) main( nT ) diff --git a/tests/python/test_hsolve_externalCalcium.py b/tests/py_moose/test_hsolve_externalCalcium.py similarity index 96% rename from tests/python/test_hsolve_externalCalcium.py rename to tests/py_moose/test_hsolve_externalCalcium.py index f6e149f4..d1127333 100644 --- a/tests/python/test_hsolve_externalCalcium.py +++ b/tests/py_moose/test_hsolve_externalCalcium.py @@ -28,7 +28,7 @@ def assert_stat( vec, expected ): assert np.allclose( computed, expected ), \ "Got %s expected %s" % (computed, expected) -if __name__ =='__main__': +def test_hsolve_calcium(): for tick in range(0, 7): moose.setClock(tick,10e-6) moose.setClock(8, 0.005) @@ -78,3 +78,9 @@ def assert_stat( vec, expected ): assert_stat( vec2, [ 5.0e-5, 5.075007e-5, 5.036985e-5, 2.1950117e-7] ) assert len(np.where(sktab.vector<1e-19)[0]) == 2001 assert len(np.where(shelltab.vector>50e-6)[0]) == 2000 + +def main(): + test_hsolve_calcium() + +if __name__ == '__main__': + main() diff --git a/tests/py_moose/test_kkit.py b/tests/py_moose/test_kkit.py new file mode 100644 index 00000000..ec4bbb64 --- /dev/null +++ b/tests/py_moose/test_kkit.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +import numpy +import sys +import os +import moose + +scriptdir = os.path.dirname(os.path.realpath(__file__)) +print('Script dir %s' % scriptdir) + +def test_kkit(): + """This example illustrates loading, running, and saving a kinetic model + defined in kkit format. It uses a default kkit model but you can + specify another using the command line ``python filename runtime + solver``. We use the gsl solver here. The model already defines a + couple of plots and sets the runtime to 20 seconds. + """ + solver = "gsl" # Pick any of gsl, gssa, ee.. + mfile = os.path.join(scriptdir, '..', 'data', 'kkit_objects_example.g') + runtime = 20.0 + modelId = moose.loadModel(mfile, 'model') + moose.mooseAddChemSolver('model', solver) + moose.reinit() + moose.start(runtime) + + for x in moose.wildcardFind('/model/#graphs/conc#/#'): + t = numpy.arange(0, x.vector.size, 1) * x.dt + + vals = x.vector + stats = [vals.min(), vals.max(), vals.mean(), vals.std()] + expected = [0.0, 0.00040464, 0.0001444, 0.00013177] + assert numpy.allclose(stats, expected, + rtol=1e-4), 'Got %s expected %s' % (stats, expected) + +def main(): + test_kkit() + +# Run the 'main' if this script is executed standalone. +if __name__ == '__main__': + main() diff --git a/tests/py_moose/test_ksolve.py b/tests/py_moose/test_ksolve.py new file mode 100644 index 00000000..7e963fef --- /dev/null +++ b/tests/py_moose/test_ksolve.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +import sys +import numpy as np +import time +import moose + +print('Using moose from %s' % moose.__file__ ) + +def test_ksolve(): + compt = moose.CubeMesh( '/compt' ) + compt.volume = 1e-20 + + pools = [] + for r in range( 10 ): + a1 = moose.Pool( '/compt/a1%s' % r ) + a1.concInit = 10 + a2 = moose.Pool( '/compt/a2%s' % r ) + a2.concInit = 5 + b1 = moose.Pool( '/compt/b1%s' % r ) + b1.concInit = 0.054 + b2 = moose.Pool( '/compt/b2%s' % r ) + b2.concInit = 3.9 + r = moose.Reac( '/compt/reac%s'% r ) + moose.connect( r, 'sub', a1, 'reac' ) + moose.connect( r, 'sub', a2, 'reac' ) + moose.connect( r, 'prd', b1, 'reac' ) + moose.connect( r, 'prd', b2, 'reac' ) + r.Kf = 2.9 + r.Kb = 4.5 + pools += [ a1, a2, b1, b2 ] + + ksolve = moose.Ksolve( '/compt/ksolve' ) + stoich = moose.Stoich( '/compt/stoich' ) + stoich.compartment = compt + stoich.ksolve = ksolve + ksolve.numThreads = 2 + stoich.path = '/compt/##' + moose.reinit() + print( '[INFO] Using method = %s' % ksolve.method ) + t1 = time.time() + moose.start( 100 ) + print('[INFO] Time taken %s' % (time.time() - t1 )) + expected = [ 7.77859 , 2.77858 , 2.27541 , 6.12141 , 7.77858 , 2.77858 + , 2.27541 , 6.12141 , 7.77858 , 2.77858 , 2.27541 , 6.12141 , 7.77858 + , 2.77858 , 2.27541 , 6.12141 , 7.77858 , 2.77858 , 2.27541 , 6.12141 + , 7.77858 , 2.77858 , 2.27541 , 6.12141 , 7.77858 , 2.77858 , 2.27541 + , 6.12141 , 7.77858 , 2.77858 , 2.27541 , 6.12141 , 7.77858 , 2.77858 + , 2.27541 , 6.12141 , 7.77858 , 2.77858 , 2.27541 , 6.12141 + ] + concs = [ p.conc for p in pools ] + if(not np.isclose( concs, expected ).all() ): + print( " Expected %s" % expected ) + print( " Got %s" % concs ) + quit(1) + print( 'Test passed' ) + +if __name__ == '__main__': + test_ksolve() diff --git a/tests/python/test_ksolve_parallel.py b/tests/py_moose/test_ksolve_parallel.py similarity index 94% rename from tests/python/test_ksolve_parallel.py rename to tests/py_moose/test_ksolve_parallel.py index 72da77d7..afed7943 100644 --- a/tests/python/test_ksolve_parallel.py +++ b/tests/py_moose/test_ksolve_parallel.py @@ -5,7 +5,7 @@ import time os.environ['MOOSE_SHOW_PROFILING_INFO'] = '1' -def main( nthreads = 1 ): +def test_ksolver_parallel( nthreads = 4 ): """ This example implements a reaction-diffusion like system which is bistable and propagates losslessly. It is based on the NEURON example @@ -79,7 +79,6 @@ def main( nthreads = 1 ): moose.reinit() updateDt = 50 runtime = updateDt * 4 - # plt = pylab.plot( x, c.vec.n, label='t = 0 ') yvec = c.vec.n u1, m1 = np.mean( yvec ), np.std( yvec ) print( u1, m1 ) @@ -87,18 +86,19 @@ def main( nthreads = 1 ): t1 = time.time() for i, t in enumerate(range( 0, runtime-1, updateDt)): moose.start( updateDt ) - # plt = pylab.plot( x, c.vec.n, label='t = '+str(t + updateDt) ) yvec = c.vec.n u1, m1 = np.mean( yvec ), np.std( yvec ) print( u1, m1 ) np.isclose( (u1,m1), expected[i+1], atol=1e-5 ).all(), expected[i+1] return time.time() - t1 +def main(nT): + return test_ksolver_parallel(nT) if __name__ == '__main__': import multiprocessing import sys - nT = int(multiprocessing.cpu_count()/2) + nT = max(1, int(multiprocessing.cpu_count())) if len(sys.argv) > 1: nT = int(sys.argv[1]) t2 = main( nT ) diff --git a/tests/python/test_moose_attribs.py b/tests/py_moose/test_moose_attribs.py similarity index 80% rename from tests/python/test_moose_attribs.py rename to tests/py_moose/test_moose_attribs.py index 3c8746b7..5be8ed11 100644 --- a/tests/python/test_moose_attribs.py +++ b/tests/py_moose/test_moose_attribs.py @@ -24,7 +24,7 @@ 'HHGate2D', 'HSolve', 'INFINITE', 'IntFire', 'IntFireBase', 'Interpol', 'Interpol2D', 'IzhIF', 'IzhikevichNrn', 'Ksolve', 'LIF', 'Leakage', 'LookupField', 'MMPump', 'MMenz', 'MarkovChannel' , - # 'MarkovGslSolver', # This is GSL specific. + 'MarkovOdeSolver', 'MarkovRateTable', 'MarkovSolver', 'MarkovSolverBase', 'MeshEntry', 'MgBlock', 'Msg', 'Mstring', 'NMDAChan', 'Nernst', 'NeuroMesh', 'Neuron', 'Neutral', 'OneToAllMsg', 'OneToOneDataIndexMsg', @@ -33,35 +33,33 @@ 'Reac', 'ReacBase', 'SBML', 'STDPSynHandler', 'STDPSynapse', 'SeqSynHandler', 'Shell', 'SimpleSynHandler', 'SingleMsg', 'SparseMsg', 'Species', 'SpikeGen', 'SpikeStats', 'Spine', 'SpineMesh', 'Stats', - 'SteadyState', 'StimulusTable', 'Stoich', 'Streamer', 'StringIO', + 'SteadyState', 'StimulusTable', 'Stoich', 'Streamer', 'SymCompartment', 'SynChan', 'SynHandlerBase', 'Synapse', 'Table', 'Table2', 'TableBase', 'TimeTable', 'VClamp', 'VERSION', 'Variable', 'VectorTable', 'ZombieBufPool', 'ZombieCaConc', 'ZombieCompartment', 'ZombieEnz', 'ZombieFunction', 'ZombieHHChannel', 'ZombieMMenz', 'ZombiePool', 'ZombieReac', '_moose', - 'append_finfodocs', 'ce', 'chemMerge', + 'ce', 'chemMerge', 'chemUtil', 'closing', 'connect', 'copy', 'delete', 'division', 'doc', 'element', 'exists', 'finfotypes', 'fixXreacs', 'genesis', 'getCwe', - 'getField', 'getFieldDict', 'getFieldNames', 'getfielddoc', - 'getmoosedoc', 'isRunning', - 'known_types', 'le', 'listmsg', 'loadModelInternal', 'melement', + 'getField', 'getFieldDict', 'getFieldNames', 'getFieldDoc', 'isRunning', + 'le', 'listmsg', 'loadModelInternal', 'melement', 'mergeChemModel', 'moose', 'mooseAddChemSolver', 'mooseDeleteChemSolver', 'mooseReadNML2', 'mooseReadSBML', 'mooseWriteKkit', 'mooseWriteNML2', 'mooseWriteSBML', - 'moose_constants', 'moose_test', 'move', - 'nml2Import_', 'pager', 'print_utils', + 'moose_constants', 'moose_test', 'move', 'nml2Import_', 'print_utils', 'pwe', 'pydoc', 'rand', 'reinit', - 'seed', 'sequence_types', 'setClock', 'setCwe', 'showfield', + 'seed', 'setClock', 'setCwe', 'showfield', 'showfields', 'showmsg', 'start', 'stop', 'syncDataHandler', - 'test', 'testSched', 'toUnicode', 'useClock', 'utils', 'vec', 'version', + 'test', 'testSched', 'useClock', 'utils', 'vec', 'version', 'warnings', 'wildcardFind'] -def main(): +def test_attribs(): global attribs for at in attribs: + print( "\tTesting for attrib %s" % at ) assert hasattr( moose, at ), 'Attrib %s not found' % at - print( getattr(moose, at ) ) if __name__ == '__main__': - main() + test_attribs() diff --git a/tests/py_moose/test_moose_paths.py b/tests/py_moose/test_moose_paths.py new file mode 100644 index 00000000..78715c46 --- /dev/null +++ b/tests/py_moose/test_moose_paths.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +import moose +import re + +def fixPath(path): + path = re.sub(r'/+', '/', path) + return path + +def test_path(): + paths = [ '/a' + , '//a' + , '/a/b' + , '/a/b/' + , '//a//b/////' + , '/a/./b' + , '///a/././b' + ] + + expectedPath = set([fixPath(p) for p in paths]) + print(expectedPath) + + for p in paths: + print(moose.Neutral(p)) + + foundPath = [] + for p in moose.wildcardFind('/##'): + if "/a" in p.path: + foundPath.append(p.path) + + testFailed = False + for f in foundPath: + f = re.sub(r'\[\d+\]', '', f) + if f not in expectedPath: + testFailed = True + + assert not testFailed, "Test failed" + + +def main(): + test_path() + +if __name__ == '__main__': + main() diff --git a/tests/python/test_negative_value_flag.py b/tests/py_moose/test_negative_value_flag.py similarity index 53% rename from tests/python/test_negative_value_flag.py rename to tests/py_moose/test_negative_value_flag.py index 70861540..9fe77568 100644 --- a/tests/python/test_negative_value_flag.py +++ b/tests/py_moose/test_negative_value_flag.py @@ -11,9 +11,10 @@ import sys import os -scriptDir = os.path.dirname( os.path.realpath( __file__ ) ) +scriptDir = os.path.dirname(os.path.realpath(__file__)) -def main(): + +def test_neg_value_flag(): """ This example illustrates loading, running, and saving a kinetic model defined in kkit format. It uses a default kkit model but @@ -23,49 +24,46 @@ def main(): The model already defines a couple of plots and sets the runtime 20 secs. """ + global scriptDir + solver = "gsl" # Pick any of gsl, gssa, ee.. - mfile = os.path.join( scriptDir, './genesis/acc11.g' ) + mfile = os.path.join(scriptDir, '..', 'data', 'acc11.g') + assert os.path.isfile(mfile) runtime = 1000.0 - if ( len( sys.argv ) >= 3 ): - if sys.argv[1][0] == '/': - mfile = sys.argv[1] - else: - mfile = sys.argv[1] - runtime = float( sys.argv[2] ) - if ( len( sys.argv ) == 4 ): - solver = sys.argv[3] - - modelId = moose.loadModel( mfile, 'model') - moose.mooseAddChemSolver('model',solver) - moose.element( '/model/kinetics/neuroNOS/nNOS.arg' ).concInit = 0.1 + modelId = moose.loadModel(mfile, 'model') + moose.mooseAddChemSolver('model', solver) + moose.element('/model/kinetics/neuroNOS/nNOS.arg').concInit = 0.1 moose.reinit() - moose.start( runtime ) + moose.start(runtime) # Display all plots. - for x in moose.wildcardFind( '/model/#graphs/conc#/#' ): - t = np.arange( 0, x.vector.size, 1 ) * x.dt - print( x.vector ) + for x in moose.wildcardFind('/model/#graphs/conc#/#'): + t = np.arange(0, x.vector.size, 1) * x.dt + print(x.vector) if x.vector.size > 0: - assert min( x.vector ) >= 0.0, min(x.vector) + assert min(x.vector) >= 0.0, min(x.vector) assert x.vector.size in [0, 10001], x.vector.size ######################################################## # Run it again with negative values allowed - moose.element( '/model/kinetics/stoich' ).allowNegative = True + moose.element('/model/kinetics/stoich').allowNegative = True moose.reinit() - moose.start( runtime ) + moose.start(runtime) oneValIsBelowZero = False - allVals = [ ] - for x in moose.wildcardFind( '/model/#graphs/conc#/#' ): - t = np.arange( 0, x.vector.size, 1 ) * x.dt + allVals = [] + for x in moose.wildcardFind('/model/#graphs/conc#/#'): + t = np.arange(0, x.vector.size, 1) * x.dt if x.vector.size > 0: - allVals.append( min( x.vector ) ) - if min( x.vector ) <= 0.0: + allVals.append(min(x.vector)) + if min(x.vector) <= 0.0: oneValIsBelowZero = True if allVals: - assert oneValIsBelowZero, "No value is negative: %s" % allVals + assert oneValIsBelowZero, "No value is negative: %s" % allVals assert x.vector.size in [0, 10001], x.vector.size +def main(): + test_neg_value_flag() + if __name__ == '__main__': main() diff --git a/tests/python/test_pymoose.py b/tests/py_moose/test_pymoose_1.py similarity index 71% rename from tests/python/test_pymoose.py rename to tests/py_moose/test_pymoose_1.py index 903b4199..91b295c3 100644 --- a/tests/python/test_pymoose.py +++ b/tests/py_moose/test_pymoose_1.py @@ -1,10 +1,8 @@ # -*- coding: utf-8 -*- -from __future__ import print_function +from __future__ import print_function, division, absolute_import + import sys -try: - import unittest2 as unittest -except: - import unittest +import unittest import uuid import platform @@ -12,6 +10,7 @@ class TestVec(unittest.TestCase): """Test pymoose basics""" + def testCreate(self): em = moose.vec('/test', 10, 0, 'Neutral') self.assertEqual(em.path, '/test') @@ -114,9 +113,6 @@ def testPath(self): def testName(self): self.assertEqual(self.b.name, 'b') - def testPathEndingWithSlash(self): - self.assertRaises(ValueError, moose.Neutral, 'test/') - def testNonExistentPath(self): self.assertRaises(ValueError, moose.Neutral, '/nonexistent_parent/invalid_child') @@ -161,7 +157,7 @@ def testRename(self): class TestWildcardFind(unittest.TestCase): def setUp(self): self.x = moose.Neutral('/x', 10) - self.y = moose.IntFire('/x[5]/y', 10) + self.y = moose.IntFire('/x[5]/y', 10) self.z = moose.PulseGen('/x[5]/z', 3) self.u = moose.IntFire('/x[5]/z[2]/u', 10) @@ -192,36 +188,6 @@ def testLessThan(self): yless = moose.wildcardFind('/x[]/##[FIELD(Vm)<0]') self.assertEqual(set(yless), set(self.y.vec[:5])) - -# class TestPyMooseGlobals(unittest.TestCase): -# def setUp(self): -# path1 = 'neutral%d' % (uuid.uuid4().int) -# path2 = 'neutral%d' % (uuid.uuid4().int) -# self.src1 = moose.Id(path1, 1, 'Neutral') -# self.dest1 = moose.Id(path2, 1, 'Neutral') - -# def testCopy(self): -# print 'Testing copy ...', -# newname = 'neutral%d' % (uuid.uuid4().int) -# new_id = moose.copy(self.src1, self.dest1, newname, 3, toGlobal=False) -# self.assertEqual(len(new_id), 3) -# self.assertEqual(new_obj.path, self.dest1.path + "/" + newname + '[0]') -# print 'OK' - -# def testElement(self): -# print 'Testing element() ...' -# x = moose.element(self.src1.path) -# self.assertTrue(isinstance(x, moose.Neutral)) -# self.assertEqual(x.path, self.src1.path) -# x = moose.element(self.src1.vec) -# self.assertTrue(isinstance(x, moose.Neutral)) -# self.assertEqual(x.path, self.src1.path) -# x = moose.element(self.src1[0].oid_) -# self.assertTrue(isinstance(x, moose.Neutral)) -# self.assertEqual(x.path, self.src1.path) -# self.assertRaises(NameError, moose.element, 'abracadabra') - - class TestMessages(unittest.TestCase): def setUp(self): path1 = '/comp%d' % (uuid.uuid4().int) @@ -242,9 +208,9 @@ def testConnect(self): destFieldsOnE2 = outmsgs_src[ii].getField('destFieldsOnE2') self.assertEqual(destFieldsOnE2[0], 'handleRaxial') print('OK') - + print('Testing delete ...') def testDelete(self): - print('Testing delete ...', end=' ') + print('Testing delete ...') msg = self.src1.connect('raxial', self.dest1, 'axial') src2 = moose.PulseGen('/pulsegen') msg2 = moose.connect(src2, 'output', self.dest1, 'injectMsg') @@ -254,29 +220,6 @@ def testDelete(self): p = msg.path p = msg2.path # this should not raise any error - # def test_getInMessageDict(self): - # print 'Testing getInMessageDict ...', - # indict = self.src1.getInMessageDict() - # self.assertTrue('parentMsg' in indict) - - -# class TestNeighbors(unittest.TestCase): -# def setUp(self): -# self.pulsegen = moose.PulseGen('pulsegen') -# self.compartment = moose.Compartment('compartment') -# self.table = moose.Table('table') -# moose.connect(self.table, 'requestData', self.compartment, 'get_Im') -# moose.connect(self.pulsegen, 'output', self.compartment, 'injectMsg') - -# def testNeighborDict(self): -# print 'Testing neighbour dict ...' -# neighbors = self.compartment.neighborDict -# self.assertTrue(self.pulsegen.oid_ in [ n.oid_ for n in neighbors['injectMsg']]) -# self.assertTrue(self.table.oid_ in [n.oid_ for n in neighbors['get_Im']]) -# self.assertTrue(self.compartment.oid_ in [n.oid_ for n in self.pulsegen.neighborDict['output']]) -# self.assertTrue(self.compartment.oid_ in [n.oid_ for n in self.table.neighborDict['requestData']]) -# print 'OK' - class TestDelete(unittest.TestCase): def setUp(self): self.oid = moose.Neutral('testDelete') @@ -293,25 +236,6 @@ def testGetField(self): class TestFieldAccess(unittest.TestCase): def testSetGet(self): pass - # a = moose.IntFire('TestFieldAccess_IntFire', g=0) - # print 'a:', a - # sys.stdout.flush() - # print 'Vm=', - # print a.Vm - # a.Vm = 2.0 - # self.assertAlmostEqual(a.Vm, 2.0) - -# class TestValueFieldTypes(unittest.TestCase): -# def setUp(self): -# self.id_ = uuid.uuid4().int -# self.container = moose.Neutral('/test%d' % (self.id_)) -# cwe = moose.getCwe() -# self.model = moose.loadModel('../Demos/Genesis_files/Kholodenko.g', '%s/kholodenko' % (self.container.path)) -# moose.setCwe(cwe) - -# def testVecUnsigned(self): -# x = moose.element('%s/kinetics' % (self.model.path)) -# self.assertTrue(len(x.meshToSpace) > 0) if __name__ == '__main__': print('PyMOOSE Regression Tests:') diff --git a/tests/py_moose/test_pymoose_2.py b/tests/py_moose/test_pymoose_2.py new file mode 100644 index 00000000..2eca7bd1 --- /dev/null +++ b/tests/py_moose/test_pymoose_2.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Script to test all import modules. + +import moose + +try: + import libsbml +except ImportError: + pass + +def library1(): + import moose.genesis + import moose.SBML + import moose.chemMerge + import moose.utils + import moose.network_utils + print('done') + + p1 = moose.le() + a = moose.Pool('/a') + for i in range(10): + moose.Pool('/a/p%d'%i) + p2 = moose.le() + assert set(p2) - set(p1) == set(['/a']) + aa = moose.le(a) + assert len(aa) == 10 + + try: + moose.syncDataHandler('/a') + except NotImplementedError: + pass + + try: + moose.showfield('/x') + except ValueError: + pass + + moose.showfield('/a') + moose.showfields('/a') + +def library_doc(): + print("=== Testing documents.") + d1 = moose.getFieldDoc(('Pool', 'conc')) + d2 = moose.getFieldDoc(('Ksolve', 'numThreads')) + assert d1 + assert d1 != d2 + moose.doc(('Ksolve.numThreads')) + moose.doc('Ksolve') + + +def test_library(): + library1() + library_doc() + + +def main(): + test_library() + +if __name__ == '__main__': + main() diff --git a/tests/python/test_random_gen.sh b/tests/py_moose/test_random_gen.sh similarity index 100% rename from tests/python/test_random_gen.sh rename to tests/py_moose/test_random_gen.sh diff --git a/tests/python/test_random_num.py b/tests/py_moose/test_random_num.py similarity index 90% rename from tests/python/test_random_num.py rename to tests/py_moose/test_random_num.py index 9be47e93..a525e25a 100644 --- a/tests/python/test_random_num.py +++ b/tests/py_moose/test_random_num.py @@ -19,9 +19,9 @@ reload except NameError: # Python 3 - from imp import reload + from importlib import reload -def unequal(): +def test_unequal(): rand1, rand2 = [], [] N = 10 for i in range( N ): @@ -34,7 +34,7 @@ def unequal(): assert not np.equal( rand1, rand2 ).all() -def equal(): +def test_equal(): rand1, rand2 = [], [] N = 10 moose.seed( 10 ) @@ -51,8 +51,8 @@ def equal(): assert np.equal( rand1, rand2 ).all() def main( ): - unequal() - equal() + test_unequal() + test_equal() if __name__ == '__main__': main() diff --git a/tests/python/test_rdesigneur.py b/tests/py_moose/test_rdesigneur.py similarity index 92% rename from tests/python/test_rdesigneur.py rename to tests/py_moose/test_rdesigneur.py index 2972a3c0..2e51659a 100644 --- a/tests/python/test_rdesigneur.py +++ b/tests/py_moose/test_rdesigneur.py @@ -15,7 +15,7 @@ import moose import rdesigneur as rd -def test2( ): +def test_rdes2(): if moose.exists( '/model' ): moose.delete( '/model' ) @@ -27,14 +27,14 @@ def test2( ): moose.reinit() moose.start( 0.3 ) -def test1( ): +def test_rdes1(): rdes = rd.rdesigneur() rdes.buildModel() moose.showfields( rdes.soma ) def main( ): - test1() - test2( ) + test_rdes1() + test_rdes2() if __name__ == '__main__': main() diff --git a/tests/py_moose/test_rdesigneur_random_syn_input.py b/tests/py_moose/test_rdesigneur_random_syn_input.py new file mode 100644 index 00000000..2b0d8e1e --- /dev/null +++ b/tests/py_moose/test_rdesigneur_random_syn_input.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +from __future__ import print_function, division + +# This example demonstrates random (Poisson) synaptic input to a cell. +# Copyright (C) Upinder S. Bhalla NCBS 2018 +# Released under the terms of the GNU Public License V3. No warranty. +# Changelog: +# Thursday 20 September 2018 09:53:27 AM IST +# - Turned into a test script. Dilawar Singh + +import moose +import numpy as np + +moose.seed( 100 ) + +try: + import matplotlib +except Exception as e: + print( "[INFO ] matplotlib is not found. This test wont run." ) + quit() + +import rdesigneur as rd + +def test_rdes(): + rdes = rd.rdesigneur( + cellProto = [['somaProto', 'soma', 20e-6, 200e-6]], + chanProto = [['make_glu()', 'glu']], + chanDistrib = [['glu', 'soma', 'Gbar', '1' ]], + stimList = [['soma', '0.5', 'glu', 'randsyn', '50' ]], + # Deliver stimulus to glu synapse on soma, at mean 50 Hz Poisson. + plotList = [['soma', '1', '.', 'Vm', 'Soma membrane potential']] + ) + rdes.buildModel() + moose.reinit() + moose.start( 0.3 ) + tables = moose.wildcardFind( '/##[TYPE=Table]' ) + res = [ ] + for t in tables: + y = t.vector + u, s = np.mean(y), np.std(y) + res.append( (u,s) ) + + + # Got these values from version compiled on Sep 20, 2018 with moose.seed + # set to 100. + expected = [(-0.051218660048699974, 0.01028490481294165)] + assert np.isclose( expected, res, atol=1e-5).all(), "Expected %s, got %s" %(expected,res) + +def main(): + test_rdes() + +if __name__ == '__main__': + main() diff --git a/tests/python/test_steady_state_solver.py b/tests/py_moose/test_steady_state_solver.py similarity index 99% rename from tests/python/test_steady_state_solver.py rename to tests/py_moose/test_steady_state_solver.py index fd3e13e1..cdc099c5 100644 --- a/tests/python/test_steady_state_solver.py +++ b/tests/py_moose/test_steady_state_solver.py @@ -15,7 +15,7 @@ import moose print( "[INFO ] Using moose from %s" % moose.__file__ ) -def main(): +def test_SS_solver(): compartment = makeModel() ksolve = moose.Ksolve( '/model/compartment/ksolve' ) stoich = moose.Stoich( '/model/compartment/stoich' ) @@ -88,7 +88,6 @@ def main(): expected = 0.216, 0.03752 assert np.isclose(got, expected, atol = 1e-4).all(), "Got %s, expected %s" % (got, expected) print( "[INFO ] Test 3 PASSED" ) - quit() def makeModel(): """ This function creates a bistable reaction system using explicit @@ -147,6 +146,9 @@ def makeModel(): return compartment +def main(): + test_SS_solver() + # Run the 'main' if this script is executed standalone. if __name__ == '__main__': main() diff --git a/tests/python/test_streamer.py b/tests/py_moose/test_streamer.py similarity index 97% rename from tests/python/test_streamer.py rename to tests/py_moose/test_streamer.py index 3136ec24..ca51659d 100644 --- a/tests/python/test_streamer.py +++ b/tests/py_moose/test_streamer.py @@ -25,7 +25,7 @@ all_done_ = False # Poll the file to see that we are really writing to it. -def sanity_test( ): +def test_sanity( ): a = moose.Table( '/t1' ) b = moose.Table( '/t1/t1' ) c = moose.Table( '/t1/t1/t1' ) @@ -66,7 +66,7 @@ def sanity_test( ): st.removeTables( [a, a, c] ) assert st.numTables == 1 -def test( ): +def test_streamer( ): compt = moose.CubeMesh( '/compt' ) assert compt r = moose.Reac( '/compt/r' ) @@ -127,10 +127,9 @@ def test( ): return 0 def main( ): - sanity_test( ) - test( ) + test_sanity( ) + test_streamer( ) print( '[INFO] All tests passed' ) - if __name__ == '__main__': main() diff --git a/tests/py_moose/test_switch_solvers.py b/tests/py_moose/test_switch_solvers.py new file mode 100644 index 00000000..17b69ca7 --- /dev/null +++ b/tests/py_moose/test_switch_solvers.py @@ -0,0 +1,146 @@ +######################################################################### +## This program is part of 'MOOSE', the +## Messaging Object Oriented Simulation Environment. +## Copyright (C) 2014 Upinder S. Bhalla. and NCBS +## It is made available under the terms of the +## GNU Lesser General Public License version 2.1 +## See the file COPYING.LIB for the full notice. +######################################################################### + +import os +import moose +print("[INFO ] using moose from %s" % moose.__file__) +import numpy as np + +sdir_ = os.path.dirname(os.path.realpath(__file__)) + + +def runAndSavePlots( name ): + runtime = 20.0 + moose.reinit() + moose.start( runtime ) + pa = moose.Neutral( '/model/graphs/' + name ) + for x in moose.wildcardFind( '/model/#graphs/conc#/#' ): + if ( x.tick != -1 ): + tabname = '/model/graphs/' + name + '/' + x.name + '.' + name + y = moose.Table( tabname ) + y.vector = x.vector + y.tick = -1 + +# Takes args ee, gsl, or gssa +def switchSolvers( solver ): + if ( moose.exists( 'model/kinetics/stoich' ) ): + moose.delete( '/model/kinetics/stoich' ) + moose.delete( '/model/kinetics/ksolve' ) + compt = moose.element( '/model/kinetics' ) + if ( solver == 'gsl' ): + ksolve = moose.Ksolve( '/model/kinetics/ksolve' ) + if ( solver == 'gssa' ): + ksolve = moose.Gsolve( '/model/kinetics/ksolve' ) + if ( solver != 'ee' ): + stoich = moose.Stoich( '/model/kinetics/stoich' ) + stoich.compartment = compt + stoich.ksolve = ksolve + stoich.path = "/model/kinetics/##" + +def test_switch_solvers(): + """ + At zero order, you can select the solver you want to use within the + function moose.loadModel( filename, modelpath, solver ). + Having loaded in the model, you can change the solver to use on it. + This example illustrates how to assign and change solvers for a + kinetic model. This process is necessary in two situations: + + * If we want to change the numerical method employed, for example, + from deterministic to stochastic. + * If we are already using a solver, and we have changed the reaction + network by adding or removing molecules or reactions. + + Note that we do not have to change the solvers if the volume or + reaction rates change. + In this example the model is loaded in with a gsl solver. The + sequence of solver calculations is: + + #. gsl + #. ee + #. gsl + #. gssa + #. gsl + + If you're removing the solvers, you just delete the stoichiometry + object and the associated ksolve/gsolve. Should there be diffusion + (a dsolve)then you should delete that too. If you're + building the solvers up again, then you must do the following + steps in order: + + #. build up the ksolve/gsolve and stoich (any order) + #. Assign stoich.ksolve + #. Assign stoich.path. + + See the Reaction-diffusion section should you want to do diffusion + as well. + + """ + + solver = "gsl" # Pick any of gsl, gssa, ee.. + mfile = os.path.join(sdir_, '../data/kkit_objects_example.g') + modelId = moose.loadModel( mfile, 'model', solver ) + # Increase volume so that the stochastic solver gssa + # gives an interesting output + compt = moose.element( '/model/kinetics' ) + compt.volume = 1e-19 + runAndSavePlots( 'gsl' ) + ######################################################### + switchSolvers( 'ee' ) + runAndSavePlots( 'ee' ) + ######################################################### + switchSolvers( 'gsl' ) + runAndSavePlots( 'gsl2' ) + ######################################################### + switchSolvers( 'gssa' ) + runAndSavePlots( 'gssa' ) + ######################################################### + switchSolvers( 'gsl' ) + runAndSavePlots( 'gsl3' ) + ######################################################### + + # Display all plots. + plotdt = moose.element( '/clock' ).tickDt[18] + conc = [] + for x in moose.wildcardFind( '/model/#graphs/conc#/#' ): + conc.append(x.vector) + conc = np.array(conc) + assert conc.mean() > 0.0 + + data = [] + for x in moose.wildcardFind( '/model/graphs/gsl/#' ): + data.append(x.vector) + gsl = np.array(data) + assert abs(conc - gsl).sum() < 0.25 + + data=[] + for x in moose.wildcardFind( '/model/graphs/ee/#' ): + data.append(x.vector) + ee = np.array(data) + assert abs(conc-ee).sum() < 0.2 + + data=[] + for x in moose.wildcardFind( '/model/graphs/gsl2/#' ): + data.append(x.vector) + gsl2 = np.array(data) + assert abs(conc-gsl2).sum() == 0.0 # these are the same. + + data=[] + for x in moose.wildcardFind( '/model/graphs/gssa/#' ): + data.append(x.vector) + gssa = np.array(data) + assert abs(conc - gssa).sum() < 0.15, (conc - gssa).sum() + assert gssa.shape == conc.shape == gsl.shape == ee.shape + + print('all done') + +def main(): + test_switch_solvers() + +if __name__ == '__main__': + main() diff --git a/tests/python/test_synchan.py b/tests/py_moose/test_synchan.py similarity index 98% rename from tests/python/test_synchan.py rename to tests/py_moose/test_synchan.py index 46e1206e..8e589c9a 100644 --- a/tests/python/test_synchan.py +++ b/tests/py_moose/test_synchan.py @@ -46,7 +46,7 @@ def make_synapse(path): m = moose.connect(spikegen, 'spikeOut', synH.synapse[0], 'addSpike') # this causes segfault return syn, spikegen -if __name__ == '__main__': +def test_synchan(): model = moose.Neutral('/model') syn, spikegen = make_synapse('/model/synchan') moose.setClock(0, 0.01) @@ -54,6 +54,9 @@ def make_synapse(path): moose.reinit() moose.start(100) +if __name__ == '__main__': + test_synchan() + # # test_synchan.py ends here diff --git a/tests/python/test_table_streaming_support.py b/tests/py_moose/test_table_streaming_support.py similarity index 100% rename from tests/python/test_table_streaming_support.py rename to tests/py_moose/test_table_streaming_support.py diff --git a/tests/py_moose/test_vec.py b/tests/py_moose/test_vec.py new file mode 100644 index 00000000..2717340b --- /dev/null +++ b/tests/py_moose/test_vec.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +import moose + +def test_vec(): + foo = moose.Pool('/foo1', 500) + bar = moose.vec('/foo1') + assert len(bar) == 500 + +if __name__ == '__main__': + test_vec() diff --git a/tests/py_moose/test_wrapper.py b/tests/py_moose/test_wrapper.py new file mode 100644 index 00000000..208c496d --- /dev/null +++ b/tests/py_moose/test_wrapper.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- + +__author__ = "Dilawar Singh" +__copyright__ = "Copyright 2019-, Dilawar Singh" +__maintainer__ = "Dilawar Singh" +__email__ = "dilawars@ncbs.res.in" + +import moose +import numpy as np +print( "[INFO ] Using moose %s form %s" % (moose.version(), moose.__file__) ) + +def create_func( funcname, expr ): + f = moose.Function( funcname ) + f.expr = expr + t = moose.Table( funcname + 'tab' ) + t.connect('requestOut', f, 'getValue') + moose.setClock( f.tick, 0.1) + moose.setClock( t.tick, 0.1) + return f, t + +def test_function(): + nsteps = 5 + simtime = nsteps + dt = 1.0 + fn1 = moose.Function('/fn1', expr = 'B+A+y0+y1') + inputs = np.arange(0, nsteps+1, 1.0) + x0 = moose.StimulusTable('/x0', vector=inputs, startTime = 0.0 + , stopTime = simtime, stepPosition = 0.0) + print('x0', x0.vector) + inputs /= 10 + x1 = moose.StimulusTable('/x1', vector=inputs, startTime=0.0 + , stopTime=simtime, stepPosition=0.0, k = 11) + print('x1', x1.vector) + inputs /= 10 + y0 = moose.StimulusTable('/y0', vector=inputs, startTime=0.0 + , stopTime=simtime, stepPosition=0.0) + print('y0', y0.vector) + inputs /= 10 + y1 = moose.StimulusTable('/y1', vector=inputs, startTime=0.0 + , stopTime=simtime, stepPosition=0.0) + print('y1', y1.vector) + x0.connect('output', fn1['A'], 'input') + x1.connect('output', fn1['B'], 'input') + fn1.connect('requestOut', y0, 'getOutputValue') + fn1.connect('requestOut', y1, 'getOutputValue') + + z1 = moose.Table('/z1') + z1.connect('requestOut', fn1, 'getValue') + for ii in range(32): + moose.setClock(ii, dt) + moose.reinit() + moose.start(simtime) + expected = [0, 1.1, 2.211, 3.322, 4.433, 5.544] + assert np.allclose(z1.vector, expected), "Excepted %s, got %s" % (expected, z1.vector ) + print( 'Passed order vars' ) + + +def test_creation(): + a1 = moose.Neutral('a') + a2 = moose.Neutral('//a') + a3 = moose.Neutral('/.//a/') + assert a1 == a2 == a3 + assert a1.path == a2.path == a3.path == '/a[0]', a1.path + a3 = moose.Neutral('a2') + assert a3 != a1 + +def test_print(): + a = moose.Function('f', expr='sqrt(sin(x0))+cos(x1)^2+ln(20+sin(t))') + # Get equivalent sympy expression. And do whatever you like with it. + try: + sympyExpr = a.sympyExpr() + print('Sympy expression is:', sympyExpr) + + # Or pretty-print using sympy + a.printUsingSympy() + except ImportError: + pass + +def test_basic(): + f = moose.Function('f1') + f.expr = 'A+B+sqrt(B)+zhadu(q)' + print(f) + +def main(): + test_function() + test_basic() + test_creation() + test_print() + +if __name__ == '__main__': + main() diff --git a/tests/py_rdesigneur/Na_Chan_Migliore2018_.py b/tests/py_rdesigneur/Na_Chan_Migliore2018_.py new file mode 100644 index 00000000..8c92e8c7 --- /dev/null +++ b/tests/py_rdesigneur/Na_Chan_Migliore2018_.py @@ -0,0 +1,80 @@ +# Na channel taken from mod files of Migliore2018: na3n.mod +# Problems: q10 same for both X and Y gates. + +import numpy as np +import moose + +SOMA_A = 3.14e-8 +F = 96485.3329 +R = 8.314 +celsius = 32 +dt = 0.05e-3 +ENa = 0.092 +EK = -0.100 +Eh = -0.030 +ECa = 0.140 +Em = -0.065 + +Vmin = -0.100 +Vmax = 0.100 +Vdivs = 3000 +v = np.linspace(Vmin,Vmax, Vdivs) +Camin = 1e-12 +Camax = 1 +Cadivs = 400 +ca = np.linspace(Camin,Camax, Cadivs) + +# original +Na_actA = -138.9 +Na_actB = -5.34 +Na_actC = 2.60187360e-05 +Na_actD = -7.05694169e+01 +Na_actE = 2.64467199e-02 +Na_actF = -1.02623323e+02 +Na_actG = 1.73923802e-05 + +Na_inactB = 12.5 +Na_inactC = 2.004014672869906e-09 +Na_inactD = -360.599 +Na_inactE = 1.866086164497956e-09 +Na_inactF = -454.5 +Na_inactG = 0.00047 + + +def Na_Chan(name): + Na = moose.HHChannel( '/library/' + name ) + Na.Ek = ENa + Na.Gbar = 300.0*SOMA_A + Na.Gk = 0.0 + Na.Xpower = 3.0 + Na.Ypower = 1 + Na.Zpower = 0 + + Na_inactA = 250 + + def trap0(v,th,a,q): + if np.abs(v*1e3-th) > 1e-6: + return a * (v*1e3 - th) / (1 - np.exp(-(v*1e3 - th)/q)) + else: + return a * q + + minf = 1/(1+np.exp(Na_actA*v+Na_actB)) + mtau=Na_actC*np.exp(Na_actD*v)/(1+Na_actE*np.exp(Na_actF*v)) + Na_actG + hinf = 1/(1+np.exp(Na_inactA*v+Na_inactB)) + htau=Na_inactC*np.exp(Na_inactD*v)/(1+Na_inactE*np.exp(Na_inactF*v)) + Na_inactG + + xgate = moose.element( Na.path + '/gateX' ) + xgate.min = Vmin + xgate.max = Vmax + xgate.divs = Vdivs + xgate.tableA = minf/mtau + xgate.tableB = 1.0/mtau + + ygate = moose.element( Na.path + '/gateY' ) + ygate.min = Vmin + ygate.max = Vmax + ygate.divs = Vdivs + ygate.tableA = hinf/htau + ygate.tableB = 1.0/htau + + return Na diff --git a/tests/py_rdesigneur/chem/CICRspineDend.g b/tests/py_rdesigneur/chem/CICRspineDend.g new file mode 100644 index 00000000..f57401f5 --- /dev/null +++ b/tests/py_rdesigneur/chem/CICRspineDend.g @@ -0,0 +1,332 @@ +//genesis +// kkit Version 11 flat dumpfile + +// Saved on Sat Feb 16 15:40:53 2019 + +include kkit {argv 1} + +FASTDT = 0.001 +SIMDT = 0.001 +CONTROLDT = 0.1 +PLOTDT = 0.1 +MAXTIME = 100 +TRANSIENT_TIME = 2 +VARIABLE_DT_FLAG = 0 +DEFAULT_VOL = 3.1e-18 +VERSION = 11.0 +setfield /file/modpath value ~/scripts/modules +kparms + +//genesis + +initdump -version 3 -ignoreorphans 1 +simobjdump doqcsinfo filename accessname accesstype transcriber developer \ + citation species tissue cellcompartment methodology sources \ + model_implementation model_validation x y z +simobjdump table input output alloced step_mode stepsize x y z +simobjdump xtree path script namemode sizescale +simobjdump xcoredraw xmin xmax ymin ymax +simobjdump xtext editable +simobjdump xgraph xmin xmax ymin ymax overlay +simobjdump xplot pixflags script fg ysquish do_slope wy +simobjdump group xtree_fg_req xtree_textfg_req plotfield expanded movealone \ + link savename file version md5sum mod_save_flag x y z +simobjdump geometry size dim shape outside xtree_fg_req xtree_textfg_req x y \ + z +simobjdump kpool DiffConst CoInit Co n nInit mwt nMin vol slave_enable \ + geomname xtree_fg_req xtree_textfg_req x y z +simobjdump kreac kf kb notes xtree_fg_req xtree_textfg_req x y z +simobjdump kenz CoComplexInit CoComplex nComplexInit nComplex vol k1 k2 k3 \ + keepconc usecomplex notes xtree_fg_req xtree_textfg_req link x y z +simobjdump stim level1 width1 delay1 level2 width2 delay2 baselevel trig_time \ + trig_mode notes xtree_fg_req xtree_textfg_req is_running x y z +simobjdump xtab input output alloced step_mode stepsize notes editfunc \ + xtree_fg_req xtree_textfg_req baselevel last_x last_y is_running x y z +simobjdump kchan perm gmax Vm is_active use_nernst notes xtree_fg_req \ + xtree_textfg_req x y z +simobjdump transport input output alloced step_mode stepsize dt delay clock \ + kf xtree_fg_req xtree_textfg_req x y z +simobjdump proto x y z +simobjdump text str +simundump geometry /kinetics/geometry 0 3.1115e-18 3 sphere "" white black 0 \ + 0 0 +simundump geometry /kinetics/geometry[1] 0 3.9e-19 3 sphere "" white black 0 \ + 0 0 +simundump geometry /kinetics/geometry[2] 0 1e-19 3 sphere "" white black 0 0 \ + 0 +simundump text /kinetics/notes 0 "" +call /kinetics/notes LOAD \ +"" +simundump text /kinetics/geometry/notes 0 "" +call /kinetics/geometry/notes LOAD \ +"" +simundump text /kinetics/geometry[1]/notes 0 "" +call /kinetics/geometry[1]/notes LOAD \ +"" +simundump text /kinetics/geometry[2]/notes 0 "" +call /kinetics/geometry[2]/notes LOAD \ +"" +simundump kpool /kinetics/phase 0 0.0 100 100 1.8669e+05 1.8669e+05 0 0 \ + 1866.9 0 /kinetics/geometry 49 black 9 9 0 +simundump text /kinetics/phase/notes 0 "" +call /kinetics/phase/notes LOAD \ +"" +simundump kpool /kinetics/CaIP3_3_R 0 0.0 0 0 0 0 0 0 1866.9 0 \ + /kinetics/geometry 20 black 4 7 0 +simundump text /kinetics/CaIP3_3_R/notes 0 "" +call /kinetics/CaIP3_3_R/notes LOAD \ +"" +simundump kpool /kinetics/Serca 0 0.0 1.9999 1.9999 3733.7 3733.7 0 0 1866.9 \ + 0 /kinetics/geometry 31 black 4 1 0 +simundump text /kinetics/Serca/notes 0 "" +call /kinetics/Serca/notes LOAD \ +"" +simundump kenz /kinetics/Serca/MMenz_SERCA 0 0 0 0 0 1866.9 0.14284 32 8 0 1 \ + "" black 42 "" 4 2 0 +simundump text /kinetics/Serca/MMenz_SERCA/notes 0 "" +call /kinetics/Serca/MMenz_SERCA/notes LOAD \ +"" +simundump kpool /kinetics/CaM 0 0.0 0 0 0 0 0 0 1866.9 0 /kinetics/geometry \ + 23 black 9 -1 0 +simundump text /kinetics/CaM/notes 0 "" +call /kinetics/CaM/notes LOAD \ +"" +simundump kpool /kinetics/CaMCa 0 0.0 0 0 0 0 0 0 1866.9 0 /kinetics/geometry \ + 23 black 9 0 0 +simundump text /kinetics/CaMCa/notes 0 "" +call /kinetics/CaMCa/notes LOAD \ +"" +simundump kpool /kinetics/CaMCa2 0 0.0 0 0 0 0 0 0 1866.9 0 \ + /kinetics/geometry 55 black 9 1 0 +simundump text /kinetics/CaMCa2/notes 0 "" +call /kinetics/CaMCa2/notes LOAD \ +"" +simundump kpool /kinetics/CaMCa3 0 0.0 0 0 0 0 0 0 1866.9 0 \ + /kinetics/geometry 27 black 9 2 0 +simundump text /kinetics/CaMCa3/notes 0 "" +call /kinetics/CaMCa3/notes LOAD \ +"" +simundump kpool /kinetics/CaMCa4 0 0.0 0 0 0 0 0 0 1866.9 0 \ + /kinetics/geometry 55 black 9 3 0 +simundump text /kinetics/CaMCa4/notes 0 "" +call /kinetics/CaMCa4/notes LOAD \ +"" +simundump kpool /kinetics/IP3_R 0 0.0 0.1 0.1 186.69 186.69 0 0 1866.9 0 \ + /kinetics/geometry 22 black 3 9 0 +simundump text /kinetics/IP3_R/notes 0 "" +call /kinetics/IP3_R/notes LOAD \ +"" +simundump kpool /kinetics/IP3_3_R 0 0.0 0 0 0 0 0 0 1866.9 0 \ + /kinetics/geometry 1 black 4 7 0 +simundump text /kinetics/IP3_3_R/notes 0 "" +call /kinetics/IP3_3_R/notes LOAD \ +"" +simundump kpool /kinetics/IP3 0 0.0 0.1 0.1 186.69 186.69 0 0 1866.9 4 \ + /kinetics/geometry 53 black 5 9 0 +simundump text /kinetics/IP3/notes 0 "" +call /kinetics/IP3/notes LOAD \ +"" +simundump kpool /kinetics/Ca2_IP3_3_R 0 0.0 0 0 0 0 0 0 1866.9 0 \ + /kinetics/geometry 25 black 7 9 0 +simundump text /kinetics/Ca2_IP3_3_R/notes 0 "" +call /kinetics/Ca2_IP3_3_R/notes LOAD \ +"" +simundump kpool /kinetics/Mirror_CaIP3_3_R 0 0.0 0 0 0 0 0 0 1866.9 0 \ + /kinetics/geometry 4 black -1 4 0 +simundump text /kinetics/Mirror_CaIP3_3_R/notes 0 "" +call /kinetics/Mirror_CaIP3_3_R/notes LOAD \ +"" +simundump kpool /kinetics/ActIP3R 0 0.0 0 0 0 0 0 0 1866.9 0 \ + /kinetics/geometry 8 black 2 1 0 +simundump text /kinetics/ActIP3R/notes 0 "" +call /kinetics/ActIP3R/notes LOAD \ +"" +simundump kchan /kinetics/ActIP3R/chan 0 8 0.1 0 1 0 "" brown 8 2 2 0 +simundump text /kinetics/ActIP3R/chan/notes 0 "" +call /kinetics/ActIP3R/chan/notes LOAD \ +"" +simundump kpool /kinetics/basal 0 0.0 0 0 0 0 0 0 1866.9 0 /kinetics/geometry \ + 8 black 2 -1 0 +simundump text /kinetics/basal/notes 0 "" +call /kinetics/basal/notes LOAD \ +"" +simundump kpool /kinetics/BufPool 0 0.0 0 0 0 0 0 0 1866.9 4 \ + /kinetics/geometry 26 black 1 9 0 +simundump text /kinetics/BufPool/notes 0 "" +call /kinetics/BufPool/notes LOAD \ +"" +simundump kreac /kinetics/CaMreac1 0 0.0045449 8.4853 "" white black 5 0 0 +simundump text /kinetics/CaMreac1/notes 0 "" +call /kinetics/CaMreac1/notes LOAD \ +"" +simundump kreac /kinetics/CaMreac2 0 0.0045449 8.4853 "" white black 6 1 0 +simundump text /kinetics/CaMreac2/notes 0 "" +call /kinetics/CaMreac2/notes LOAD \ +"" +simundump kreac /kinetics/CaMreac3 0 0.0019284 10 "" white black 7 2 0 +simundump text /kinetics/CaMreac3/notes 0 "" +call /kinetics/CaMreac3/notes LOAD \ +"" +simundump kreac /kinetics/CaMreac4 0 0.00096419 10 "" white black 8 3 0 +simundump text /kinetics/CaMreac4/notes 0 "" +call /kinetics/CaMreac4/notes LOAD \ +"" +simundump kreac /kinetics/Reac 0 0.0064279 8 "" white black 4 8 0 +simundump text /kinetics/Reac/notes 0 "" +call /kinetics/Reac/notes LOAD \ +"" +simundump kreac /kinetics/Reac2 0 0.0080348 1.65 "" white black 6 6 0 +simundump text /kinetics/Reac2/notes 0 "" +call /kinetics/Reac2/notes LOAD \ +"" +simundump kreac /kinetics/Reac4 0 0.00096422 0.21 "" white black 7 7 0 +simundump text /kinetics/Reac4/notes 0 "" +call /kinetics/Reac4/notes LOAD \ +"" +simundump kreac /kinetics/Reac1 0 0.0001492 5 "" white black 0 0 0 +simundump text /kinetics/Reac1/notes 0 "" +call /kinetics/Reac1/notes LOAD \ +"" +simundump group /kinetics/DEND 0 blue green x 0 0 "" DEND defaultfile.g 0 0 0 \ + 1 2 0 +simundump text /kinetics/DEND/notes 0 "" +call /kinetics/DEND/notes LOAD \ +"" +simundump group /kinetics/DEND_ER 0 26 black x 0 0 "" DEND_ER defaultfile.g 0 \ + 0 0 0 6 0 +simundump text /kinetics/DEND_ER/notes 0 "" +call /kinetics/DEND_ER/notes LOAD \ +"" +simundump kpool /kinetics/DEND_ER/CaER 0 0.0 408.59 408.59 95611 95611 0 0 \ + 234 0 /kinetics/geometry 0 26 2 5 0 +simundump text /kinetics/DEND_ER/CaER/notes 0 "" +call /kinetics/DEND_ER/CaER/notes LOAD \ +"" +simundump kpool /kinetics/DEND_ER/leakPool 0 0 1 1 234 234 0 0 234 0 \ + /kinetics/geometry[1] 45 26 4 4 0 +simundump text /kinetics/DEND_ER/leakPool/notes 0 "" +call /kinetics/DEND_ER/leakPool/notes LOAD \ +"" +simundump kchan /kinetics/DEND_ER/leakPool/leakChan 0 0.04 0.1 0 1 0 "" brown \ + 45 4 5 0 +simundump text /kinetics/DEND_ER/leakPool/leakChan/notes 0 "" +call /kinetics/DEND_ER/leakPool/leakChan/notes LOAD \ +"" +simundump kpool /kinetics/Ca 0 2e-11 0.079999 0.079999 149.35 149.35 0 0 \ + 1866.9 0 /kinetics/geometry 23 black 7 4 0 +simundump text /kinetics/Ca/notes 0 "" +call /kinetics/Ca/notes LOAD \ +"" +simundump group /kinetics/SPINE 0 yellow black x 0 0 "" SPINE defaultfile.g 0 \ + 0 0 0 11 0 +simundump text /kinetics/SPINE/notes 0 "" +call /kinetics/SPINE/notes LOAD \ +"" +simundump kpool /kinetics/SPINE/Ca 0 2e-11 0.08 0.08 4.8 4.8 0 0 60 0 \ + /kinetics/geometry[2] 25 yellow 4 11 0 +simundump text /kinetics/SPINE/Ca/notes 0 "" +call /kinetics/SPINE/Ca/notes LOAD \ +"" +simundump kpool /kinetics/CaExtracell 0 0.0 0.079999 0.079999 149.35 149.35 0 \ + 0 1866.9 4 /kinetics/geometry 61 black 9 4 0 +simundump text /kinetics/CaExtracell/notes 0 "" +call /kinetics/CaExtracell/notes LOAD \ +"" +simundump kreac /kinetics/Ca_regn 0 0.1 0.1 "" white black 8 5 0 +simundump text /kinetics/Ca_regn/notes 0 "" +call /kinetics/Ca_regn/notes LOAD \ +"" +simundump xgraph /graphs/conc1 0 0 100 0.001 0.999 0 +simundump xgraph /graphs/conc2 0 0 100 0 1 0 +simundump xplot /graphs/conc1/CaCyt.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " 23 0 0 1 +simundump xplot /graphs/conc1/ActIP3R.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " 8 0 0 1 +simundump xplot /graphs/conc1/CaIP3_3_R.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " 20 0 0 1 +simundump xplot /graphs/conc2/CaER.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " 0 0 0 1 +simundump xgraph /moregraphs/conc3 0 0 100 0 1 0 +simundump xgraph /moregraphs/conc4 0 0 100 0 1 0 +simundump xcoredraw /edit/draw 0 -3 11 -3 13 +simundump xtree /edit/draw/tree 0 \ + /kinetics/#[],/kinetics/#[]/#[],/kinetics/#[]/#[]/#[][TYPE!=proto],/kinetics/#[]/#[]/#[][TYPE!=linkinfo]/##[] \ + "edit_elm.D ; drag_from_edit.w " auto 0.6 +simundump xtext /file/notes 0 1 +addmsg /kinetics/Reac2 /kinetics/CaIP3_3_R REAC B A +addmsg /kinetics/Reac4 /kinetics/CaIP3_3_R REAC A B +addmsg /kinetics/Ca /kinetics/Serca/MMenz_SERCA SUBSTRATE n +addmsg /kinetics/Serca /kinetics/Serca/MMenz_SERCA ENZYME n +addmsg /kinetics/CaMreac1 /kinetics/CaM REAC A B +addmsg /kinetics/CaMreac1 /kinetics/CaMCa REAC B A +addmsg /kinetics/CaMreac2 /kinetics/CaMCa REAC A B +addmsg /kinetics/CaMreac2 /kinetics/CaMCa2 REAC B A +addmsg /kinetics/CaMreac3 /kinetics/CaMCa2 REAC A B +addmsg /kinetics/CaMreac3 /kinetics/CaMCa3 REAC B A +addmsg /kinetics/CaMreac4 /kinetics/CaMCa3 REAC A B +addmsg /kinetics/CaMreac4 /kinetics/CaMCa4 REAC B A +addmsg /kinetics/Reac /kinetics/IP3_R REAC A B +addmsg /kinetics/Reac /kinetics/IP3_3_R REAC B A +addmsg /kinetics/Reac2 /kinetics/IP3_3_R REAC A B +addmsg /kinetics/Reac /kinetics/IP3 REAC A B +addmsg /kinetics/Reac4 /kinetics/Ca2_IP3_3_R REAC B A +addmsg /kinetics/CaIP3_3_R /kinetics/Mirror_CaIP3_3_R SUMTOTAL n nInit +addmsg /kinetics/Reac1 /kinetics/Mirror_CaIP3_3_R REAC A B +addmsg /kinetics/Reac1 /kinetics/Mirror_CaIP3_3_R REAC A B +addmsg /kinetics/Reac1 /kinetics/Mirror_CaIP3_3_R REAC A B +addmsg /kinetics/Reac1 /kinetics/ActIP3R REAC B A +addmsg /kinetics/ActIP3R /kinetics/ActIP3R/chan NUMCHAN n +addmsg /kinetics/DEND_ER/CaER /kinetics/ActIP3R/chan SUBSTRATE n vol +addmsg /kinetics/Ca /kinetics/ActIP3R/chan PRODUCT n vol +addmsg /kinetics/Ca /kinetics/CaMreac1 SUBSTRATE n +addmsg /kinetics/CaM /kinetics/CaMreac1 SUBSTRATE n +addmsg /kinetics/CaMCa /kinetics/CaMreac1 PRODUCT n +addmsg /kinetics/CaMCa /kinetics/CaMreac2 SUBSTRATE n +addmsg /kinetics/Ca /kinetics/CaMreac2 SUBSTRATE n +addmsg /kinetics/CaMCa2 /kinetics/CaMreac2 PRODUCT n +addmsg /kinetics/Ca /kinetics/CaMreac3 SUBSTRATE n +addmsg /kinetics/CaMCa2 /kinetics/CaMreac3 SUBSTRATE n +addmsg /kinetics/CaMCa3 /kinetics/CaMreac3 PRODUCT n +addmsg /kinetics/Ca /kinetics/CaMreac4 SUBSTRATE n +addmsg /kinetics/CaMCa3 /kinetics/CaMreac4 SUBSTRATE n +addmsg /kinetics/CaMCa4 /kinetics/CaMreac4 PRODUCT n +addmsg /kinetics/IP3_R /kinetics/Reac SUBSTRATE n +addmsg /kinetics/IP3 /kinetics/Reac SUBSTRATE n +addmsg /kinetics/IP3_3_R /kinetics/Reac PRODUCT n +addmsg /kinetics/Ca /kinetics/Reac2 SUBSTRATE n +addmsg /kinetics/IP3_3_R /kinetics/Reac2 SUBSTRATE n +addmsg /kinetics/CaIP3_3_R /kinetics/Reac2 PRODUCT n +addmsg /kinetics/Ca /kinetics/Reac4 SUBSTRATE n +addmsg /kinetics/CaIP3_3_R /kinetics/Reac4 SUBSTRATE n +addmsg /kinetics/Ca2_IP3_3_R /kinetics/Reac4 PRODUCT n +addmsg /kinetics/Mirror_CaIP3_3_R /kinetics/Reac1 SUBSTRATE n +addmsg /kinetics/Mirror_CaIP3_3_R /kinetics/Reac1 SUBSTRATE n +addmsg /kinetics/Mirror_CaIP3_3_R /kinetics/Reac1 SUBSTRATE n +addmsg /kinetics/ActIP3R /kinetics/Reac1 PRODUCT n +addmsg /kinetics/Serca/MMenz_SERCA /kinetics/DEND_ER/CaER MM_PRD pA +addmsg /kinetics/DEND_ER/leakPool/leakChan /kinetics/DEND_ER/CaER REAC A B +addmsg /kinetics/ActIP3R/chan /kinetics/DEND_ER/CaER REAC A B +addmsg /kinetics/DEND_ER/leakPool /kinetics/DEND_ER/leakPool/leakChan NUMCHAN n +addmsg /kinetics/DEND_ER/CaER /kinetics/DEND_ER/leakPool/leakChan SUBSTRATE n vol +addmsg /kinetics/Ca /kinetics/DEND_ER/leakPool/leakChan PRODUCT n vol +addmsg /kinetics/CaMreac1 /kinetics/Ca REAC A B +addmsg /kinetics/CaMreac2 /kinetics/Ca REAC A B +addmsg /kinetics/CaMreac3 /kinetics/Ca REAC A B +addmsg /kinetics/CaMreac4 /kinetics/Ca REAC A B +addmsg /kinetics/Reac2 /kinetics/Ca REAC A B +addmsg /kinetics/Reac4 /kinetics/Ca REAC A B +addmsg /kinetics/Serca/MMenz_SERCA /kinetics/Ca REAC sA B +addmsg /kinetics/DEND_ER/leakPool/leakChan /kinetics/Ca REAC B A +addmsg /kinetics/ActIP3R/chan /kinetics/Ca REAC B A +addmsg /kinetics/Ca_regn /kinetics/Ca REAC A B +addmsg /kinetics/Ca_regn /kinetics/CaExtracell REAC B A +addmsg /kinetics/Ca /kinetics/Ca_regn SUBSTRATE n +addmsg /kinetics/CaExtracell /kinetics/Ca_regn PRODUCT n +addmsg /kinetics/Ca /graphs/conc1/CaCyt.Co PLOT Co *CaCyt.Co *23 +addmsg /kinetics/ActIP3R /graphs/conc1/ActIP3R.Co PLOT Co *ActIP3R.Co *8 +addmsg /kinetics/CaIP3_3_R /graphs/conc1/CaIP3_3_R.Co PLOT Co *CaIP3_3_R.Co *20 +addmsg /kinetics/DEND_ER/CaER /graphs/conc2/CaER.Co PLOT Co *CaER.Co *0 +enddump +// End of dump + +complete_loading diff --git a/tests/py_rdesigneur/chem/CICRwithConcChan.g b/tests/py_rdesigneur/chem/CICRwithConcChan.g new file mode 100644 index 00000000..136de825 --- /dev/null +++ b/tests/py_rdesigneur/chem/CICRwithConcChan.g @@ -0,0 +1,284 @@ +//genesis +// kkit Version 11 flat dumpfile + +// Saved on Fri Mar 29 19:34:16 2019 + +include kkit {argv 1} + +FASTDT = 0.001 +SIMDT = 0.001 +CONTROLDT = 0.1 +PLOTDT = 0.1 +MAXTIME = 100 +TRANSIENT_TIME = 2 +VARIABLE_DT_FLAG = 0 +DEFAULT_VOL = 3.1e-18 +VERSION = 11.0 +setfield /file/modpath value ~/scripts/modules +kparms + +//genesis + +initdump -version 3 -ignoreorphans 1 +simobjdump doqcsinfo filename accessname accesstype transcriber developer \ + citation species tissue cellcompartment methodology sources \ + model_implementation model_validation x y z +simobjdump table input output alloced step_mode stepsize x y z +simobjdump xtree path script namemode sizescale +simobjdump xcoredraw xmin xmax ymin ymax +simobjdump xtext editable +simobjdump xgraph xmin xmax ymin ymax overlay +simobjdump xplot pixflags script fg ysquish do_slope wy +simobjdump group xtree_fg_req xtree_textfg_req plotfield expanded movealone \ + link savename file version md5sum mod_save_flag x y z +simobjdump geometry size dim shape outside xtree_fg_req xtree_textfg_req x y \ + z +simobjdump kpool DiffConst CoInit Co n nInit mwt nMin vol slave_enable \ + geomname xtree_fg_req xtree_textfg_req x y z +simobjdump kreac kf kb notes xtree_fg_req xtree_textfg_req x y z +simobjdump kenz CoComplexInit CoComplex nComplexInit nComplex vol k1 k2 k3 \ + keepconc usecomplex notes xtree_fg_req xtree_textfg_req link x y z +simobjdump stim level1 width1 delay1 level2 width2 delay2 baselevel trig_time \ + trig_mode notes xtree_fg_req xtree_textfg_req is_running x y z +simobjdump xtab input output alloced step_mode stepsize notes editfunc \ + xtree_fg_req xtree_textfg_req baselevel last_x last_y is_running x y z +simobjdump kchan perm gmax Vm is_active use_nernst notes xtree_fg_req \ + xtree_textfg_req x y z +simobjdump transport input output alloced step_mode stepsize dt delay clock \ + kf xtree_fg_req xtree_textfg_req x y z +simobjdump proto x y z +simobjdump text str +simundump geometry /kinetics/geometry 0 3.1115e-18 3 sphere "" white black 0 \ + 0 0 +simundump geometry /kinetics/geometry[1] 0 3.9e-19 3 sphere "" white black 0 \ + 0 0 +simundump text /kinetics/notes 0 "" +call /kinetics/notes LOAD \ +"" +simundump text /kinetics/geometry/notes 0 "" +call /kinetics/geometry/notes LOAD \ +"" +simundump text /kinetics/geometry[1]/notes 0 "" +call /kinetics/geometry[1]/notes LOAD \ +"" +simundump group /kinetics/compt 0 blue green x 0 0 "" defaultfile \ + defaultfile.g 0 0 0 1 2 0 +simundump text /kinetics/compt/notes 0 "" +call /kinetics/compt/notes LOAD \ +"" +simundump kpool /kinetics/CaCyt 0 1e-13 0.079999 0.079999 149.35 149.35 0 0 \ + 1866.9 0 /kinetics/geometry 23 black 7 4 0 +simundump text /kinetics/CaCyt/notes 0 "" +call /kinetics/CaCyt/notes LOAD \ +"" +simundump kpool /kinetics/CaIP3_3_R 0 0.0 0 0 0 0 0 0 1866.9 0 \ + /kinetics/geometry 20 black 4 7 0 +simundump text /kinetics/CaIP3_3_R/notes 0 "" +call /kinetics/CaIP3_3_R/notes LOAD \ +"" +simundump kpool /kinetics/CaER 0 0.0 408.59 408.59 95611 95611 0 0 234 0 \ + /kinetics/geometry 0 black 2 5 0 +simundump text /kinetics/CaER/notes 0 "" +call /kinetics/CaER/notes LOAD \ +"" +simundump kpool /kinetics/Serca 0 0.0 1.9999 1.9999 3733.7 3733.7 0 0 1866.9 \ + 0 /kinetics/geometry 31 black 4 1 0 +simundump text /kinetics/Serca/notes 0 "" +call /kinetics/Serca/notes LOAD \ +"" +simundump kenz /kinetics/Serca/MMenz_SERCA 0 0 0 0 0 1866.9 0.14284 32 8 0 1 \ + "" black 42 "" 4 2 0 +simundump text /kinetics/Serca/MMenz_SERCA/notes 0 "" +call /kinetics/Serca/MMenz_SERCA/notes LOAD \ +"" +simundump kpool /kinetics/CaM 0 0.0 0 0 0 0 0 0 1866.9 0 /kinetics/geometry \ + 23 black 9 -1 0 +simundump text /kinetics/CaM/notes 0 "" +call /kinetics/CaM/notes LOAD \ +"" +simundump kpool /kinetics/CaMCa 0 0.0 0 0 0 0 0 0 1866.9 0 /kinetics/geometry \ + 23 black 9 0 0 +simundump text /kinetics/CaMCa/notes 0 "" +call /kinetics/CaMCa/notes LOAD \ +"" +simundump kpool /kinetics/CaMCa2 0 0.0 0 0 0 0 0 0 1866.9 0 \ + /kinetics/geometry 55 black 9 1 0 +simundump text /kinetics/CaMCa2/notes 0 "" +call /kinetics/CaMCa2/notes LOAD \ +"" +simundump kpool /kinetics/CaMCa3 0 0.0 0 0 0 0 0 0 1866.9 0 \ + /kinetics/geometry 27 black 9 2 0 +simundump text /kinetics/CaMCa3/notes 0 "" +call /kinetics/CaMCa3/notes LOAD \ +"" +simundump kpool /kinetics/CaMCa4 0 0.0 0 0 0 0 0 0 1866.9 0 \ + /kinetics/geometry 55 black 9 3 0 +simundump text /kinetics/CaMCa4/notes 0 "" +call /kinetics/CaMCa4/notes LOAD \ +"" +simundump kpool /kinetics/IP3_R 0 0.0 0.1 0.1 186.69 186.69 0 0 1866.9 0 \ + /kinetics/geometry 22 black 3 9 0 +simundump text /kinetics/IP3_R/notes 0 "" +call /kinetics/IP3_R/notes LOAD \ +"" +simundump kpool /kinetics/IP3_3_R 0 0.0 0 0 0 0 0 0 1866.9 0 \ + /kinetics/geometry 1 black 4 7 0 +simundump text /kinetics/IP3_3_R/notes 0 "" +call /kinetics/IP3_3_R/notes LOAD \ +"" +simundump kpool /kinetics/IP3 0 0.0 7.9999 7.9999 14935 14935 0 0 1866.9 4 \ + /kinetics/geometry 53 black 5 9 0 +simundump text /kinetics/IP3/notes 0 "" +call /kinetics/IP3/notes LOAD \ +"" +simundump kpool /kinetics/Ca2_IP3_3_R 0 0.0 0 0 0 0 0 0 1866.9 0 \ + /kinetics/geometry 25 black 7 9 0 +simundump text /kinetics/Ca2_IP3_3_R/notes 0 "" +call /kinetics/Ca2_IP3_3_R/notes LOAD \ +"" +simundump kpool /kinetics/Mirror_CaIP3_3_R 0 0.0 0 0 0 0 0 0 1866.9 0 \ + /kinetics/geometry 4 black -1 4 0 +simundump text /kinetics/Mirror_CaIP3_3_R/notes 0 "" +call /kinetics/Mirror_CaIP3_3_R/notes LOAD \ +"" +simundump kpool /kinetics/ActIP3R 0 0.0 0 0 0 0 0 0 1866.9 0 \ + /kinetics/geometry 8 black 2 1 0 +simundump text /kinetics/ActIP3R/notes 0 "" +call /kinetics/ActIP3R/notes LOAD \ +"" +simundump kchan /kinetics/ActIP3R/chan 0 8 0.1 0 1 0 "" brown 8 2 2 0 +simundump text /kinetics/ActIP3R/chan/notes 0 "" +call /kinetics/ActIP3R/chan/notes LOAD \ +"" +simundump kreac /kinetics/CaMreac1 0 0.0045449 8.4853 "" white black 5 0 0 +simundump text /kinetics/CaMreac1/notes 0 "" +call /kinetics/CaMreac1/notes LOAD \ +"" +simundump kreac /kinetics/CaMreac2 0 0.0045449 8.4853 "" white black 6 1 0 +simundump text /kinetics/CaMreac2/notes 0 "" +call /kinetics/CaMreac2/notes LOAD \ +"" +simundump kreac /kinetics/CaMreac3 0 0.0019284 10 "" white black 7 2 0 +simundump text /kinetics/CaMreac3/notes 0 "" +call /kinetics/CaMreac3/notes LOAD \ +"" +simundump kreac /kinetics/CaMreac4 0 0.00096419 10 "" white black 8 3 0 +simundump text /kinetics/CaMreac4/notes 0 "" +call /kinetics/CaMreac4/notes LOAD \ +"" +simundump kreac /kinetics/Reac 0 0.0064279 8 "" white black 4 8 0 +simundump text /kinetics/Reac/notes 0 "" +call /kinetics/Reac/notes LOAD \ +"" +simundump kreac /kinetics/Reac2 0 0.0080348 1.65 "" white black 6 6 0 +simundump text /kinetics/Reac2/notes 0 "" +call /kinetics/Reac2/notes LOAD \ +"" +simundump kreac /kinetics/Reac4 0 0.00096422 0.21 "" white black 7 7 0 +simundump text /kinetics/Reac4/notes 0 "" +call /kinetics/Reac4/notes LOAD \ +"" +simundump kreac /kinetics/Reac1 0 0.0001492 5 "" white black 0 0 0 +simundump text /kinetics/Reac1/notes 0 "" +call /kinetics/Reac1/notes LOAD \ +"" +simundump kpool /kinetics/leakPool 0 0 1 1 234 234 0 0 234 0 \ + /kinetics/geometry[1] 45 black 4 4 0 +simundump text /kinetics/leakPool/notes 0 "" +call /kinetics/leakPool/notes LOAD \ +"" +simundump kchan /kinetics/leakPool/leakChan 0 0.04 0.1 0 1 0 "" brown 45 4 5 \ + 0 +simundump text /kinetics/leakPool/leakChan/notes 0 "" +call /kinetics/leakPool/leakChan/notes LOAD \ +"" +simundump xgraph /graphs/conc1 0 0 100 0.001 0.999 0 +simundump xgraph /graphs/conc2 0 0 100 0 1 0 +simundump xplot /graphs/conc1/CaCyt.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " 23 0 0 1 +simundump xplot /graphs/conc1/ActIP3R.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " 8 0 0 1 +simundump xplot /graphs/conc1/CaIP3_3_R.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " 20 0 0 1 +simundump xplot /graphs/conc2/CaER.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " 0 0 0 1 +simundump xgraph /moregraphs/conc3 0 0 100 0 1 0 +simundump xgraph /moregraphs/conc4 0 0 100 0 1 0 +simundump xcoredraw /edit/draw 0 -1.5666 11.334 -1.8008 10.24 +simundump xtree /edit/draw/tree 0 \ + /kinetics/#[],/kinetics/#[]/#[],/kinetics/#[]/#[]/#[][TYPE!=proto],/kinetics/#[]/#[]/#[][TYPE!=linkinfo]/##[] \ + "edit_elm.D ; drag_from_edit.w " auto 0.6 +simundump xtext /file/notes 0 1 +addmsg /kinetics/CaMreac1 /kinetics/CaCyt REAC A B +addmsg /kinetics/CaMreac2 /kinetics/CaCyt REAC A B +addmsg /kinetics/CaMreac3 /kinetics/CaCyt REAC A B +addmsg /kinetics/CaMreac4 /kinetics/CaCyt REAC A B +addmsg /kinetics/Reac2 /kinetics/CaCyt REAC A B +addmsg /kinetics/Reac4 /kinetics/CaCyt REAC A B +addmsg /kinetics/Serca/MMenz_SERCA /kinetics/CaCyt REAC sA B +addmsg /kinetics/leakPool/leakChan /kinetics/CaCyt REAC B A +addmsg /kinetics/ActIP3R/chan /kinetics/CaCyt REAC B A +addmsg /kinetics/Reac2 /kinetics/CaIP3_3_R REAC B A +addmsg /kinetics/Reac4 /kinetics/CaIP3_3_R REAC A B +addmsg /kinetics/Serca/MMenz_SERCA /kinetics/CaER MM_PRD pA +addmsg /kinetics/leakPool/leakChan /kinetics/CaER REAC A B +addmsg /kinetics/ActIP3R/chan /kinetics/CaER REAC A B +addmsg /kinetics/CaCyt /kinetics/Serca/MMenz_SERCA SUBSTRATE n +addmsg /kinetics/Serca /kinetics/Serca/MMenz_SERCA ENZYME n +addmsg /kinetics/CaMreac1 /kinetics/CaM REAC A B +addmsg /kinetics/CaMreac1 /kinetics/CaMCa REAC B A +addmsg /kinetics/CaMreac2 /kinetics/CaMCa REAC A B +addmsg /kinetics/CaMreac2 /kinetics/CaMCa2 REAC B A +addmsg /kinetics/CaMreac3 /kinetics/CaMCa2 REAC A B +addmsg /kinetics/CaMreac3 /kinetics/CaMCa3 REAC B A +addmsg /kinetics/CaMreac4 /kinetics/CaMCa3 REAC A B +addmsg /kinetics/CaMreac4 /kinetics/CaMCa4 REAC B A +addmsg /kinetics/Reac /kinetics/IP3_R REAC A B +addmsg /kinetics/Reac /kinetics/IP3_3_R REAC B A +addmsg /kinetics/Reac2 /kinetics/IP3_3_R REAC A B +addmsg /kinetics/Reac /kinetics/IP3 REAC A B +addmsg /kinetics/Reac4 /kinetics/Ca2_IP3_3_R REAC B A +addmsg /kinetics/CaIP3_3_R /kinetics/Mirror_CaIP3_3_R SUMTOTAL n nInit +addmsg /kinetics/Reac1 /kinetics/Mirror_CaIP3_3_R REAC A B +addmsg /kinetics/Reac1 /kinetics/Mirror_CaIP3_3_R REAC A B +addmsg /kinetics/Reac1 /kinetics/Mirror_CaIP3_3_R REAC A B +addmsg /kinetics/Reac1 /kinetics/ActIP3R REAC B A +addmsg /kinetics/ActIP3R /kinetics/ActIP3R/chan NUMCHAN n +addmsg /kinetics/CaER /kinetics/ActIP3R/chan SUBSTRATE n vol +addmsg /kinetics/CaCyt /kinetics/ActIP3R/chan PRODUCT n vol +addmsg /kinetics/CaCyt /kinetics/CaMreac1 SUBSTRATE n +addmsg /kinetics/CaM /kinetics/CaMreac1 SUBSTRATE n +addmsg /kinetics/CaMCa /kinetics/CaMreac1 PRODUCT n +addmsg /kinetics/CaMCa /kinetics/CaMreac2 SUBSTRATE n +addmsg /kinetics/CaCyt /kinetics/CaMreac2 SUBSTRATE n +addmsg /kinetics/CaMCa2 /kinetics/CaMreac2 PRODUCT n +addmsg /kinetics/CaCyt /kinetics/CaMreac3 SUBSTRATE n +addmsg /kinetics/CaMCa2 /kinetics/CaMreac3 SUBSTRATE n +addmsg /kinetics/CaMCa3 /kinetics/CaMreac3 PRODUCT n +addmsg /kinetics/CaCyt /kinetics/CaMreac4 SUBSTRATE n +addmsg /kinetics/CaMCa3 /kinetics/CaMreac4 SUBSTRATE n +addmsg /kinetics/CaMCa4 /kinetics/CaMreac4 PRODUCT n +addmsg /kinetics/IP3_R /kinetics/Reac SUBSTRATE n +addmsg /kinetics/IP3 /kinetics/Reac SUBSTRATE n +addmsg /kinetics/IP3_3_R /kinetics/Reac PRODUCT n +addmsg /kinetics/CaCyt /kinetics/Reac2 SUBSTRATE n +addmsg /kinetics/IP3_3_R /kinetics/Reac2 SUBSTRATE n +addmsg /kinetics/CaIP3_3_R /kinetics/Reac2 PRODUCT n +addmsg /kinetics/CaCyt /kinetics/Reac4 SUBSTRATE n +addmsg /kinetics/CaIP3_3_R /kinetics/Reac4 SUBSTRATE n +addmsg /kinetics/Ca2_IP3_3_R /kinetics/Reac4 PRODUCT n +addmsg /kinetics/Mirror_CaIP3_3_R /kinetics/Reac1 SUBSTRATE n +addmsg /kinetics/Mirror_CaIP3_3_R /kinetics/Reac1 SUBSTRATE n +addmsg /kinetics/Mirror_CaIP3_3_R /kinetics/Reac1 SUBSTRATE n +addmsg /kinetics/ActIP3R /kinetics/Reac1 PRODUCT n +addmsg /kinetics/leakPool /kinetics/leakPool/leakChan NUMCHAN n +addmsg /kinetics/CaER /kinetics/leakPool/leakChan SUBSTRATE n vol +addmsg /kinetics/CaCyt /kinetics/leakPool/leakChan PRODUCT n vol +addmsg /kinetics/CaCyt /graphs/conc1/CaCyt.Co PLOT Co *CaCyt.Co *23 +addmsg /kinetics/ActIP3R /graphs/conc1/ActIP3R.Co PLOT Co *ActIP3R.Co *8 +addmsg /kinetics/CaIP3_3_R /graphs/conc1/CaIP3_3_R.Co PLOT Co *CaIP3_3_R.Co *20 +addmsg /kinetics/CaER /graphs/conc2/CaER.Co PLOT Co *CaER.Co *0 +enddump +// End of dump + +complete_loading diff --git a/tests/py_rdesigneur/chem/chanPhosph3compt.g b/tests/py_rdesigneur/chem/chanPhosph3compt.g new file mode 100644 index 00000000..10413da5 --- /dev/null +++ b/tests/py_rdesigneur/chem/chanPhosph3compt.g @@ -0,0 +1,189 @@ +//genesis +// kkit Version 11 flat dumpfile + +// Saved on Sat Jul 28 22:51:00 2018 + +include kkit {argv 1} + +FASTDT = 0.0001 +SIMDT = 0.01 +CONTROLDT = 5 +PLOTDT = 1 +MAXTIME = 100 +TRANSIENT_TIME = 2 +VARIABLE_DT_FLAG = 1 +DEFAULT_VOL = 1e-20 +VERSION = 11.0 +setfield /file/modpath value /home2/bhalla/scripts/modules +kparms + +//genesis + +initdump -version 3 -ignoreorphans 1 +simobjdump doqcsinfo filename accessname accesstype transcriber developer \ + citation species tissue cellcompartment methodology sources \ + model_implementation model_validation x y z +simobjdump table input output alloced step_mode stepsize x y z +simobjdump xtree path script namemode sizescale +simobjdump xcoredraw xmin xmax ymin ymax +simobjdump xtext editable +simobjdump xgraph xmin xmax ymin ymax overlay +simobjdump xplot pixflags script fg ysquish do_slope wy +simobjdump group xtree_fg_req xtree_textfg_req plotfield expanded movealone \ + link savename file version md5sum mod_save_flag x y z +simobjdump geometry size dim shape outside xtree_fg_req xtree_textfg_req x y \ + z +simobjdump kpool DiffConst CoInit Co n nInit mwt nMin vol slave_enable \ + geomname xtree_fg_req xtree_textfg_req x y z +simobjdump kreac kf kb notes xtree_fg_req xtree_textfg_req x y z +simobjdump kenz CoComplexInit CoComplex nComplexInit nComplex vol k1 k2 k3 \ + keepconc usecomplex notes xtree_fg_req xtree_textfg_req link x y z +simobjdump stim level1 width1 delay1 level2 width2 delay2 baselevel trig_time \ + trig_mode notes xtree_fg_req xtree_textfg_req is_running x y z +simobjdump xtab input output alloced step_mode stepsize notes editfunc \ + xtree_fg_req xtree_textfg_req baselevel last_x last_y is_running x y z +simobjdump kchan perm gmax Vm is_active use_nernst notes xtree_fg_req \ + xtree_textfg_req x y z +simobjdump transport input output alloced step_mode stepsize dt delay clock \ + kf xtree_fg_req xtree_textfg_req x y z +simobjdump proto x y z +simobjdump text str +simundump geometry /kinetics/geometry 0 1e-19 3 sphere "" white black 0 0 0 +simundump geometry /kinetics/geometry[1] 0 1e-18 3 sphere "" white black 0 0 \ + 0 +simundump text /kinetics/notes 0 "" +call /kinetics/notes LOAD \ +"" +simundump text /kinetics/geometry/notes 0 "" +call /kinetics/geometry/notes LOAD \ +"" +simundump text /kinetics/geometry[1]/notes 0 "" +call /kinetics/geometry[1]/notes LOAD \ +"" +simundump group /kinetics/PSD 0 yellow black x 0 0 "" PSD defaultfile.g 0 0 0 \ + 4 4 0 +simundump text /kinetics/PSD/notes 0 "" +call /kinetics/PSD/notes LOAD \ +"" +simundump kpool /kinetics/PSD/Ca_CaM_CaMKII 0 0 0 0 0 0 0 0 6 0 \ + /kinetics/geometry blue yellow 4 -5 0 +simundump text /kinetics/PSD/Ca_CaM_CaMKII/notes 0 "" +call /kinetics/PSD/Ca_CaM_CaMKII/notes LOAD \ +"" +simundump kenz /kinetics/PSD/Ca_CaM_CaMKII/kinase 0 0 0 0 0 6 0.16667 8 2 0 0 \ + "" red blue "" 4 -4 0 +simundump text /kinetics/PSD/Ca_CaM_CaMKII/kinase/notes 0 "" +call /kinetics/PSD/Ca_CaM_CaMKII/kinase/notes LOAD \ +"" +simundump kpool /kinetics/PSD/chan 0 0 100 100 600 600 0 0 6 0 \ + /kinetics/geometry 0 yellow 3 -1 0 +simundump text /kinetics/PSD/chan/notes 0 "" +call /kinetics/PSD/chan/notes LOAD \ +"" +simundump kreac /kinetics/PSD/dephosph 0 1 0 "" white yellow 4 1 0 +simundump text /kinetics/PSD/dephosph/notes 0 "" +call /kinetics/PSD/dephosph/notes LOAD \ +"" +simundump kpool /kinetics/PSD/chan_p 0 0 0 0 0 0 0 0 6 0 /kinetics/geometry 7 \ + yellow 5 -1 0 +simundump text /kinetics/PSD/chan_p/notes 0 "" +call /kinetics/PSD/chan_p/notes LOAD \ +"" +simundump group /kinetics/SPINE 0 0 black x 0 0 "" SPINE defaultfile.g 0 0 0 \ + -3 -2 0 +simundump text /kinetics/SPINE/notes 0 "" +call /kinetics/SPINE/notes LOAD \ +"" +simundump kpool /kinetics/SPINE/CaM 0 1e-11 10 10 600 600 0 0 60 0 \ + /kinetics/geometry 55 0 -2 2 0 +simundump text /kinetics/SPINE/CaM/notes 0 "" +call /kinetics/SPINE/CaM/notes LOAD \ +"" +simundump kpool /kinetics/SPINE/Ca 0 1e-10 0.08 0.08 4.8 4.8 0 0 60 0 \ + /kinetics/geometry blue 0 0 4 0 +simundump text /kinetics/SPINE/Ca/notes 0 "" +call /kinetics/SPINE/Ca/notes LOAD \ +"" +simundump kpool /kinetics/SPINE/Ca_CaM 0 1e-11 0 0 0 0 0 0 60 0 \ + /kinetics/geometry blue 0 1 -1 0 +simundump text /kinetics/SPINE/Ca_CaM/notes 0 "" +call /kinetics/SPINE/Ca_CaM/notes LOAD \ +"" +simundump kreac /kinetics/SPINE/Ca_bind_CaM 0 0.0027778 40 "" white 0 -1 0 0 +simundump text /kinetics/SPINE/Ca_bind_CaM/notes 0 \ + "This should actually be 4th order in Ca. Using 2nd order here\nfor simplicity and to lessen numerical stiffness." +call /kinetics/SPINE/Ca_bind_CaM/notes LOAD \ +"This should actually be 4th order in Ca. Using 2nd order here" \ +"for simplicity and to lessen numerical stiffness." +simundump kpool /kinetics/SPINE/CaMKII 0 0 8.3333 8.3333 500 500 0 0 60 0 \ + /kinetics/geometry 7 0 -1 -3 0 +simundump text /kinetics/SPINE/CaMKII/notes 0 "" +call /kinetics/SPINE/CaMKII/notes LOAD \ +"" +simundump kreac /kinetics/SPINE/CaM_bind_CaMKII 0 0.0016667 1 "" white 0 1 -4 \ + 0 +simundump text /kinetics/SPINE/CaM_bind_CaMKII/notes 0 "" +call /kinetics/SPINE/CaM_bind_CaMKII/notes LOAD \ +"" +simundump group /kinetics/DEND 0 35 black x 0 0 "" DEND defaultfile.g 0 0 0 \ + -3 -6 0 +simundump text /kinetics/DEND/notes 0 "" +call /kinetics/DEND/notes LOAD \ +"" +simundump kpool /kinetics/DEND/Ca 0 1e-10 0.08 0.08 48 48 0 0 600 0 \ + /kinetics/geometry[1] blue 35 0 -6 0 +simundump text /kinetics/DEND/Ca/notes 0 "" +call /kinetics/DEND/Ca/notes LOAD \ +"" +simundump xgraph /graphs/conc1 0 0 100 0 1 0 +simundump xgraph /graphs/conc2 0 0 100 0 1.4023 0 +simundump xplot /graphs/conc1/Ca.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " blue 0 0 1 +simundump xplot /graphs/conc2/chan_p.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " 7 0 0 1 +simundump xplot /graphs/conc2/Ca_CaM_CaMKII.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " blue 0 0 1 +simundump xgraph /moregraphs/conc3 0 0 100 0 1 0 +simundump xgraph /moregraphs/conc4 0 0 100 0 1 0 +simundump xcoredraw /edit/draw 0 -5 7 -8 6 +simundump xtree /edit/draw/tree 0 \ + /kinetics/#[],/kinetics/#[]/#[],/kinetics/#[]/#[]/#[][TYPE!=proto],/kinetics/#[]/#[]/#[][TYPE!=linkinfo]/##[] \ + "edit_elm.D ; drag_from_edit.w " auto 0.6 +simundump xtext /file/notes 0 1 +xtextload /file/notes \ +"Very simplified calcium-to-kinase model in 3 compts, " \ +"for a test multiscale" \ +"model." +addmsg /kinetics/SPINE/CaM_bind_CaMKII /kinetics/PSD/Ca_CaM_CaMKII REAC B A +addmsg /kinetics/PSD/Ca_CaM_CaMKII/kinase /kinetics/PSD/Ca_CaM_CaMKII REAC eA B +addmsg /kinetics/PSD/Ca_CaM_CaMKII /kinetics/PSD/Ca_CaM_CaMKII/kinase ENZYME n +addmsg /kinetics/PSD/chan /kinetics/PSD/Ca_CaM_CaMKII/kinase SUBSTRATE n +addmsg /kinetics/PSD/Ca_CaM_CaMKII/kinase /kinetics/PSD/chan REAC sA B +addmsg /kinetics/PSD/dephosph /kinetics/PSD/chan REAC B A +addmsg /kinetics/PSD/chan_p /kinetics/PSD/dephosph SUBSTRATE n +addmsg /kinetics/PSD/chan /kinetics/PSD/dephosph PRODUCT n +addmsg /kinetics/PSD/Ca_CaM_CaMKII/kinase /kinetics/PSD/chan_p MM_PRD pA +addmsg /kinetics/PSD/dephosph /kinetics/PSD/chan_p REAC A B +addmsg /kinetics/SPINE/Ca_bind_CaM /kinetics/SPINE/CaM REAC A B +addmsg /kinetics/SPINE/Ca_bind_CaM /kinetics/SPINE/Ca REAC A B +addmsg /kinetics/SPINE/Ca_bind_CaM /kinetics/SPINE/Ca REAC A B +addmsg /kinetics/SPINE/Ca_bind_CaM /kinetics/SPINE/Ca_CaM REAC B A +addmsg /kinetics/SPINE/CaM_bind_CaMKII /kinetics/SPINE/Ca_CaM REAC A B +addmsg /kinetics/SPINE/Ca /kinetics/SPINE/Ca_bind_CaM SUBSTRATE n +addmsg /kinetics/SPINE/Ca /kinetics/SPINE/Ca_bind_CaM SUBSTRATE n +addmsg /kinetics/SPINE/CaM /kinetics/SPINE/Ca_bind_CaM SUBSTRATE n +addmsg /kinetics/SPINE/Ca_CaM /kinetics/SPINE/Ca_bind_CaM PRODUCT n +addmsg /kinetics/SPINE/CaM_bind_CaMKII /kinetics/SPINE/CaMKII REAC A B +addmsg /kinetics/SPINE/Ca_CaM /kinetics/SPINE/CaM_bind_CaMKII SUBSTRATE n +addmsg /kinetics/SPINE/CaMKII /kinetics/SPINE/CaM_bind_CaMKII SUBSTRATE n +addmsg /kinetics/PSD/Ca_CaM_CaMKII /kinetics/SPINE/CaM_bind_CaMKII PRODUCT n +addmsg /kinetics/SPINE/Ca /graphs/conc1/Ca.Co PLOT Co *Ca.Co *blue +addmsg /kinetics/PSD/chan_p /graphs/conc2/chan_p.Co PLOT Co *chan_p.Co *7 +addmsg /kinetics/PSD/Ca_CaM_CaMKII /graphs/conc2/Ca_CaM_CaMKII.Co PLOT Co *Ca_CaM_CaMKII.Co *blue +enddump +// End of dump + +call /kinetics/SPINE/Ca_bind_CaM/notes LOAD \ +"This should actually be 4th order in Ca. Using 2nd order here" \ +"for simplicity and to lessen numerical stiffness." +complete_loading diff --git a/tests/py_rdesigneur/chem/chanPhosphByCaMKII.g b/tests/py_rdesigneur/chem/chanPhosphByCaMKII.g new file mode 100644 index 00000000..999f5239 --- /dev/null +++ b/tests/py_rdesigneur/chem/chanPhosphByCaMKII.g @@ -0,0 +1,162 @@ +//genesis +// kkit Version 11 flat dumpfile + +// Saved on Thu Sep 11 18:01:11 2014 + +include kkit {argv 1} + +FASTDT = 0.0001 +SIMDT = 0.01 +CONTROLDT = 5 +PLOTDT = 1 +MAXTIME = 100 +TRANSIENT_TIME = 2 +VARIABLE_DT_FLAG = 1 +DEFAULT_VOL = 1e-20 +VERSION = 11.0 +setfield /file/modpath value /home2/bhalla/scripts/modules +kparms + +//genesis + +initdump -version 3 -ignoreorphans 1 +simobjdump doqcsinfo filename accessname accesstype transcriber developer \ + citation species tissue cellcompartment methodology sources \ + model_implementation model_validation x y z +simobjdump table input output alloced step_mode stepsize x y z +simobjdump xtree path script namemode sizescale +simobjdump xcoredraw xmin xmax ymin ymax +simobjdump xtext editable +simobjdump xgraph xmin xmax ymin ymax overlay +simobjdump xplot pixflags script fg ysquish do_slope wy +simobjdump group xtree_fg_req xtree_textfg_req plotfield expanded movealone \ + link savename file version md5sum mod_save_flag x y z +simobjdump geometry size dim shape outside xtree_fg_req xtree_textfg_req x y \ + z +simobjdump kpool DiffConst CoInit Co n nInit mwt nMin vol slave_enable \ + geomname xtree_fg_req xtree_textfg_req x y z +simobjdump kreac kf kb notes xtree_fg_req xtree_textfg_req x y z +simobjdump kenz CoComplexInit CoComplex nComplexInit nComplex vol k1 k2 k3 \ + keepconc usecomplex notes xtree_fg_req xtree_textfg_req link x y z +simobjdump stim level1 width1 delay1 level2 width2 delay2 baselevel trig_time \ + trig_mode notes xtree_fg_req xtree_textfg_req is_running x y z +simobjdump xtab input output alloced step_mode stepsize notes editfunc \ + xtree_fg_req xtree_textfg_req baselevel last_x last_y is_running x y z +simobjdump kchan perm gmax Vm is_active use_nernst notes xtree_fg_req \ + xtree_textfg_req x y z +simobjdump transport input output alloced step_mode stepsize dt delay clock \ + kf xtree_fg_req xtree_textfg_req x y z +simobjdump proto x y z +simobjdump text str +simundump geometry /kinetics/geometry 0 1e-19 3 sphere "" white black 0 0 0 +simundump text /kinetics/notes 0 "" +call /kinetics/notes LOAD \ +"" +simundump text /kinetics/geometry/notes 0 "" +call /kinetics/geometry/notes LOAD \ +"" +simundump kpool /kinetics/CaM 0 1e-11 5 5 300 300 0 0 60 0 /kinetics/geometry \ + 55 28 -2 2 0 +simundump text /kinetics/CaM/notes 0 "" +call /kinetics/CaM/notes LOAD \ +"" +simundump kpool /kinetics/Ca_CaM 0 1e-11 0 0 0 0 0 0 60 0 /kinetics/geometry \ + blue 28 1 -1 0 +simundump text /kinetics/Ca_CaM/notes 0 "" +call /kinetics/Ca_CaM/notes LOAD \ +"" +simundump kpool /kinetics/Ca 0 1e-10 0.08 0.08 4.8 4.8 0 0 60 4 \ + /kinetics/geometry blue 28 0 4 0 +simundump text /kinetics/Ca/notes 0 "" +call /kinetics/Ca/notes LOAD \ +"" +simundump kreac /kinetics/CaM_bind_CaMKII 0 0.0016667 1 "" white 28 1 -4 0 +simundump text /kinetics/CaM_bind_CaMKII/notes 0 "" +call /kinetics/CaM_bind_CaMKII/notes LOAD \ +"" +simundump kpool /kinetics/CaMKII 0 0 8.3333 8.3333 500 500 0 0 60 0 \ + /kinetics/geometry 7 28 -1 -3 0 +simundump text /kinetics/CaMKII/notes 0 "" +call /kinetics/CaMKII/notes LOAD \ +"" +simundump kpool /kinetics/Ca_CaM_CaMKII 0 0 0 0 0 0 0 0 60 0 \ + /kinetics/geometry blue 0 4 -5 0 +simundump text /kinetics/Ca_CaM_CaMKII/notes 0 "" +call /kinetics/Ca_CaM_CaMKII/notes LOAD \ +"" +simundump kenz /kinetics/Ca_CaM_CaMKII/kinase 0 0 0 0 0 6 0.16667 8 2 0 0 "" \ + red blue "" 4 -4 0 +simundump text /kinetics/Ca_CaM_CaMKII/kinase/notes 0 "" +call /kinetics/Ca_CaM_CaMKII/kinase/notes LOAD \ +"" +simundump kpool /kinetics/chan 0 0 1 1 60 60 0 0 60 0 /kinetics/geometry 0 \ + black 3 -1 0 +simundump text /kinetics/chan/notes 0 "" +call /kinetics/chan/notes LOAD \ +"" +simundump kpool /kinetics/chan_p 0 0 0 0 0 0 0 0 60 0 /kinetics/geometry 7 \ + black 5 -1 0 +simundump text /kinetics/chan_p/notes 0 "" +call /kinetics/chan_p/notes LOAD \ +"" +simundump kreac /kinetics/Ca_bind_CaM 0 0.0027778 40 "" white 28 -1 0 0 +simundump text /kinetics/Ca_bind_CaM/notes 0 \ + "This should actually be 4th order in Ca. Using 2nd order here\nfor simplicity and to lessen numerical stiffness." +call /kinetics/Ca_bind_CaM/notes LOAD \ +"This should actually be 4th order in Ca. Using 2nd order here" \ +"for simplicity and to lessen numerical stiffness." +simundump kreac /kinetics/dephosph 0 1 0 "" white black 4 1 0 +simundump text /kinetics/dephosph/notes 0 "" +call /kinetics/dephosph/notes LOAD \ +"" +simundump xgraph /graphs/conc1 0 0 100 0 1 0 +simundump xgraph /graphs/conc2 0 0 100 0 1.4023 0 +simundump xplot /graphs/conc1/Ca.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " blue 0 0 1 +simundump xplot /graphs/conc2/chan_p.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " 7 0 0 1 +simundump xplot /graphs/conc2/Ca_CaM_CaMKII.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " blue 0 0 1 +simundump xgraph /moregraphs/conc3 0 0 100 0 1 0 +simundump xgraph /moregraphs/conc4 0 0 100 0 1 0 +simundump xcoredraw /edit/draw 0 -4 7 -7 6 +simundump xtree /edit/draw/tree 0 \ + /kinetics/#[],/kinetics/#[]/#[],/kinetics/#[]/#[]/#[][TYPE!=proto],/kinetics/#[]/#[]/#[][TYPE!=linkinfo]/##[] \ + "edit_elm.D ; drag_from_edit.w " auto 0.6 +simundump xtext /file/notes 0 1 +xtextload /file/notes \ +"Very simplified calcium-to-kinase model for a test multiscale" \ +"model." +addmsg /kinetics/Ca_bind_CaM /kinetics/CaM REAC A B +addmsg /kinetics/Ca_bind_CaM /kinetics/Ca_CaM REAC B A +addmsg /kinetics/CaM_bind_CaMKII /kinetics/Ca_CaM REAC A B +addmsg /kinetics/Ca_bind_CaM /kinetics/Ca REAC A B +addmsg /kinetics/Ca_bind_CaM /kinetics/Ca REAC A B +addmsg /kinetics/Ca_CaM /kinetics/CaM_bind_CaMKII SUBSTRATE n +addmsg /kinetics/CaMKII /kinetics/CaM_bind_CaMKII SUBSTRATE n +addmsg /kinetics/Ca_CaM_CaMKII /kinetics/CaM_bind_CaMKII PRODUCT n +addmsg /kinetics/CaM_bind_CaMKII /kinetics/CaMKII REAC A B +addmsg /kinetics/CaM_bind_CaMKII /kinetics/Ca_CaM_CaMKII REAC B A +addmsg /kinetics/Ca_CaM_CaMKII/kinase /kinetics/Ca_CaM_CaMKII REAC eA B +addmsg /kinetics/Ca_CaM_CaMKII /kinetics/Ca_CaM_CaMKII/kinase ENZYME n +addmsg /kinetics/chan /kinetics/Ca_CaM_CaMKII/kinase SUBSTRATE n +addmsg /kinetics/Ca_CaM_CaMKII/kinase /kinetics/chan REAC sA B +addmsg /kinetics/dephosph /kinetics/chan REAC B A +addmsg /kinetics/Ca_CaM_CaMKII/kinase /kinetics/chan_p MM_PRD pA +addmsg /kinetics/dephosph /kinetics/chan_p REAC A B +addmsg /kinetics/Ca /kinetics/Ca_bind_CaM SUBSTRATE n +addmsg /kinetics/Ca /kinetics/Ca_bind_CaM SUBSTRATE n +addmsg /kinetics/CaM /kinetics/Ca_bind_CaM SUBSTRATE n +addmsg /kinetics/Ca_CaM /kinetics/Ca_bind_CaM PRODUCT n +addmsg /kinetics/chan_p /kinetics/dephosph SUBSTRATE n +addmsg /kinetics/chan /kinetics/dephosph PRODUCT n +addmsg /kinetics/Ca /graphs/conc1/Ca.Co PLOT Co *Ca.Co *blue +addmsg /kinetics/chan_p /graphs/conc2/chan_p.Co PLOT Co *chan_p.Co *7 +addmsg /kinetics/Ca_CaM_CaMKII /graphs/conc2/Ca_CaM_CaMKII.Co PLOT Co *Ca_CaM_CaMKII.Co *blue +enddump +// End of dump + +call /kinetics/Ca_bind_CaM/notes LOAD \ +"This should actually be 4th order in Ca. Using 2nd order here" \ +"for simplicity and to lessen numerical stiffness." +complete_loading diff --git a/tests/py_rdesigneur/chem/psd52.g b/tests/py_rdesigneur/chem/psd52.g new file mode 100644 index 00000000..9b4197e2 --- /dev/null +++ b/tests/py_rdesigneur/chem/psd52.g @@ -0,0 +1,488 @@ +//genesis +// kkit Version 11 flat dumpfile + +// Saved on Sun Dec 7 15:51:46 2014 + +include kkit {argv 1} + +FASTDT = 1e-05 +SIMDT = 0.0001 +CONTROLDT = 1 +PLOTDT = 0.2 +MAXTIME = 200 +TRANSIENT_TIME = 2 +VARIABLE_DT_FLAG = 1 +DEFAULT_VOL = 1e-19 +VERSION = 11.0 +setfield /file/modpath value /home2/bhalla/scripts/modules +kparms + +//genesis + +initdump -version 3 -ignoreorphans 1 +simobjdump doqcsinfo filename accessname accesstype transcriber developer \ + citation species tissue cellcompartment methodology sources \ + model_implementation model_validation x y z +simobjdump table input output alloced step_mode stepsize x y z +simobjdump xtree path script namemode sizescale +simobjdump xcoredraw xmin xmax ymin ymax +simobjdump xtext editable +simobjdump xgraph xmin xmax ymin ymax overlay +simobjdump xplot pixflags script fg ysquish do_slope wy +simobjdump group xtree_fg_req xtree_textfg_req plotfield expanded movealone \ + link savename file version md5sum mod_save_flag x y z +simobjdump geometry size dim shape outside xtree_fg_req xtree_textfg_req x y \ + z +simobjdump kpool DiffConst CoInit Co n nInit mwt nMin vol slave_enable \ + geomname xtree_fg_req xtree_textfg_req x y z +simobjdump kreac kf kb notes xtree_fg_req xtree_textfg_req x y z +simobjdump kenz CoComplexInit CoComplex nComplexInit nComplex vol k1 k2 k3 \ + keepconc usecomplex notes xtree_fg_req xtree_textfg_req link x y z +simobjdump stim level1 width1 delay1 level2 width2 delay2 baselevel trig_time \ + trig_mode notes xtree_fg_req xtree_textfg_req is_running x y z +simobjdump xtab input output alloced step_mode stepsize notes editfunc \ + xtree_fg_req xtree_textfg_req baselevel last_x last_y is_running x y z +simobjdump kchan perm gmax Vm is_active use_nernst notes xtree_fg_req \ + xtree_textfg_req x y z +simobjdump transport input output alloced step_mode stepsize dt delay clock \ + kf xtree_fg_req xtree_textfg_req x y z +simobjdump proto x y z +simobjdump text str +simundump geometry /kinetics/geometry 0 1.6667e-21 3 sphere "" white black 5 \ + -4 0 +simundump geometry /kinetics/geometry[1] 0 1e-19 3 sphere "" white black 5 -2 \ + 0 +simundump geometry /kinetics/geometry[2] 0 1e-20 3 sphere "" white black 2 2 \ + 0 +simundump geometry /kinetics/geometry[3] 0 1e-20 3 sphere "" white black 4 8 \ + 0 +simundump geometry /kinetics/geometry[4] 0 1e-20 3 sphere "" white black 2 \ + -17 0 +simundump geometry /kinetics/geometry[5] 0 1e-20 3 sphere "" white black 5 \ + -13 0 +simundump geometry /kinetics/geometry[6] 0 1e-19 3 sphere "" white black 0 7 \ + 0 +simundump geometry /kinetics/geometry[7] 0 1e-20 3 sphere "" white black 0 -3 \ + 0 +simundump geometry /kinetics/geometry[8] 0 1e-20 3 sphere "" white black -1 \ + -18 0 +simundump geometry /kinetics/geometry[9] 0 1e-18 3 sphere "" white black 0 0 \ + 0 +simundump text /kinetics/notes 0 "" +call /kinetics/notes LOAD \ +"" +simundump text /kinetics/geometry/notes 0 "" +call /kinetics/geometry/notes LOAD \ +"" +simundump text /kinetics/geometry[1]/notes 0 "" +call /kinetics/geometry[1]/notes LOAD \ +"" +simundump text /kinetics/geometry[2]/notes 0 "" +call /kinetics/geometry[2]/notes LOAD \ +"" +simundump text /kinetics/geometry[3]/notes 0 "" +call /kinetics/geometry[3]/notes LOAD \ +"" +simundump text /kinetics/geometry[4]/notes 0 "" +call /kinetics/geometry[4]/notes LOAD \ +"" +simundump text /kinetics/geometry[5]/notes 0 "" +call /kinetics/geometry[5]/notes LOAD \ +"" +simundump text /kinetics/geometry[6]/notes 0 "" +call /kinetics/geometry[6]/notes LOAD \ +"" +simundump text /kinetics/geometry[7]/notes 0 "" +call /kinetics/geometry[7]/notes LOAD \ +"" +simundump text /kinetics/geometry[8]/notes 0 "" +call /kinetics/geometry[8]/notes LOAD \ +"" +simundump text /kinetics/geometry[9]/notes 0 "" +call /kinetics/geometry[9]/notes LOAD \ +"" +simundump kreac /kinetics/exocytosis 0 0.01 0 "" white black 4 -5 0 +simundump text /kinetics/exocytosis/notes 0 "" +call /kinetics/exocytosis/notes LOAD \ +"" +simundump kreac /kinetics/endocytosis 0 0 4 "" white black -7 -5 0 +simundump text /kinetics/endocytosis/notes 0 "" +call /kinetics/endocytosis/notes LOAD \ +"" +simundump group /kinetics/PSD 0 0 black x 0 1 "" PSD defaultfile.g 0 0 0 -10 \ + -3 0 +simundump text /kinetics/PSD/notes 0 "" +call /kinetics/PSD/notes LOAD \ +"" +simundump kpool /kinetics/PSD/Rp 0 0 0 0 0 0 0 0 6 0 /kinetics/geometry[1] \ + blue 0 -4 1 0 +simundump text /kinetics/PSD/Rp/notes 0 "" +call /kinetics/PSD/Rp/notes LOAD \ +"" +simundump kpool /kinetics/PSD/P 0 0 1 1 6 6 0 0 6 0 /kinetics/geometry[1] 61 \ + 0 -4 -2 0 +simundump text /kinetics/PSD/P/notes 0 "" +call /kinetics/PSD/P/notes LOAD \ +"" +simundump kenz /kinetics/PSD/P/P1 0 0 0 0 0 60 10.417 20 5 0 0 "" red 61 "" \ + -6 -1 0 +simundump text /kinetics/PSD/P/P1/notes 0 "" +call /kinetics/PSD/P/P1/notes LOAD \ +"" +simundump kenz /kinetics/PSD/P/P2 0 0 0 0 0 60 10.417 20 5 0 0 "" red 61 "" \ + -2 -1 0 +simundump text /kinetics/PSD/P/P2/notes 0 "" +call /kinetics/PSD/P/P2/notes LOAD \ +"" +simundump kpool /kinetics/PSD/KK 0 0 3 3 18 18 0 0 6 0 /kinetics/geometry[1] \ + 49 0 -4 4 0 +simundump text /kinetics/PSD/KK/notes 0 "" +call /kinetics/PSD/KK/notes LOAD \ +"" +simundump kenz /kinetics/PSD/KK/KK1 0 0 0 0 0 60 4.1667 40 10 0 0 "" red 49 \ + "" -6 3 0 +simundump text /kinetics/PSD/KK/KK1/notes 0 "" +call /kinetics/PSD/KK/KK1/notes LOAD \ +"" +simundump kenz /kinetics/PSD/KK/KK2 0 0 0 0 0 60 4.1667 40 10 0 0 "" red 49 \ + "" -2 3 0 +simundump text /kinetics/PSD/KK/KK2/notes 0 "" +call /kinetics/PSD/KK/KK2/notes LOAD \ +"" +simundump kpool /kinetics/PSD/Rpp 0 0 0 0 0 0 0 0 6 0 /kinetics/geometry[1] \ + 28 0 0 1 0 +simundump text /kinetics/PSD/Rpp/notes 0 "" +call /kinetics/PSD/Rpp/notes LOAD \ +"" +simundump kpool /kinetics/PSD/R 0 0 0 0 0 0 0 0 6 0 /kinetics/geometry[1] 4 0 \ + -8 1 0 +simundump text /kinetics/PSD/R/notes 0 "" +call /kinetics/PSD/R/notes LOAD \ +"" +simundump kpool /kinetics/PSD/tot_PSD_R 0 0 0 0 0 0 0 0 6 0 \ + /kinetics/geometry[4] blue 0 -4 7 0 +simundump text /kinetics/PSD/tot_PSD_R/notes 0 "" +call /kinetics/PSD/tot_PSD_R/notes LOAD \ +"" +simundump kpool /kinetics/PSD/Ca_PSD 0 0 0.1 0.1 0.6 0.6 0 0 6 0 \ + /kinetics/geometry[5] 53 0 -15 2 0 +simundump text /kinetics/PSD/Ca_PSD/notes 0 "" +call /kinetics/PSD/Ca_PSD/notes LOAD \ +"" +simundump kpool /kinetics/PSD/psd_inact_CaN 0 0 1 1 6 6 0 0 6 0 \ + /kinetics/geometry[7] blue 0 -12 5 0 +simundump text /kinetics/PSD/psd_inact_CaN/notes 0 "" +call /kinetics/PSD/psd_inact_CaN/notes LOAD \ +"" +simundump kreac /kinetics/PSD/psd_activate_CaN 0 0.27778 1 "" white 0 -11 1 0 +simundump text /kinetics/PSD/psd_activate_CaN/notes 0 "" +call /kinetics/PSD/psd_activate_CaN/notes LOAD \ +"" +simundump kpool /kinetics/PSD/Ca.P 0 0 0 0 0 0 0 0 6 0 /kinetics/geometry[7] \ + blue 0 -4 -4 0 +simundump text /kinetics/PSD/Ca.P/notes 0 "" +call /kinetics/PSD/Ca.P/notes LOAD \ +"" +simundump kenz /kinetics/PSD/Ca.P/Ca.P2 0 0 0 0 0 6 1.6667 40 10 0 0 "" red \ + blue "" -2 -3 0 +simundump text /kinetics/PSD/Ca.P/Ca.P2/notes 0 "" +call /kinetics/PSD/Ca.P/Ca.P2/notes LOAD \ +"" +simundump kenz /kinetics/PSD/Ca.P/Ca.P1 0 0 0 0 0 6 1.6667 40 10 0 0 "" red \ + blue "" -6 -3 0 +simundump text /kinetics/PSD/Ca.P/Ca.P1/notes 0 "" +call /kinetics/PSD/Ca.P/Ca.P1/notes LOAD \ +"" +simundump kpool /kinetics/PSD/Ca_input 0 0 0.1 0.1 0.6 0.6 0 0 6 4 \ + /kinetics/geometry[8] 60 black -12 9 0 +simundump text /kinetics/PSD/Ca_input/notes 0 "" +call /kinetics/PSD/Ca_input/notes LOAD \ +"" +simundump kreac /kinetics/PSD/Ca_reac 0 100 100 "" white black -17 6 0 +simundump text /kinetics/PSD/Ca_reac/notes 0 "" +call /kinetics/PSD/Ca_reac/notes LOAD \ +"" +simundump group /kinetics/Bulk 0 yellow black x 0 0 "" Bulk defaultfile.g 0 0 \ + 0 -6 -16 0 +simundump text /kinetics/Bulk/notes 0 "" +call /kinetics/Bulk/notes LOAD \ +"" +simundump kpool /kinetics/Bulk/iRpp 0 0 0 0 0 0 0 0 59.999 0 \ + /kinetics/geometry 29 yellow 2 -11 0 +simundump text /kinetics/Bulk/iRpp/notes 0 "" +call /kinetics/Bulk/iRpp/notes LOAD \ +"" +simundump kpool /kinetics/Bulk/iRp 0 0 0 0 0 0 0 0 59.999 0 \ + /kinetics/geometry blue yellow -2 -11 0 +simundump text /kinetics/Bulk/iRp/notes 0 "" +call /kinetics/Bulk/iRp/notes LOAD \ +"" +simundump kpool /kinetics/Bulk/iR 0 0 4.0001 4.0001 240 240 0 0 59.999 0 \ + /kinetics/geometry 0 yellow -6 -11 0 +simundump text /kinetics/Bulk/iR/notes 0 "Same as Fus3\n" +call /kinetics/Bulk/iR/notes LOAD \ +"Same as Fus3" \ +"" +simundump kpool /kinetics/Bulk/iKK 0 0 1 1 59.999 59.999 0 0 59.999 0 \ + /kinetics/geometry 50 yellow -2 -8 0 +simundump text /kinetics/Bulk/iKK/notes 0 "Same as Ste7\n" +call /kinetics/Bulk/iKK/notes LOAD \ +"Same as Ste7" \ +"" +simundump kenz /kinetics/Bulk/iKK/iKK1 0 0 0 0 0 59.999 0.83335 40 10 0 0 "" \ + red 50 "" -4 -9 0 +simundump text /kinetics/Bulk/iKK/iKK1/notes 0 "" +call /kinetics/Bulk/iKK/iKK1/notes LOAD \ +"" +simundump kenz /kinetics/Bulk/iKK/iKK2 0 0 0 0 0 59.999 0.83335 40 10 0 0 "" \ + red 50 "" 0 -9 0 +simundump text /kinetics/Bulk/iKK/iKK2/notes 0 "" +call /kinetics/Bulk/iKK/iKK2/notes LOAD \ +"" +simundump kpool /kinetics/Bulk/iP 0 0 0.50001 0.50001 30 30 0 0 59.999 0 \ + /kinetics/geometry 62 yellow -2 -14 0 +simundump text /kinetics/Bulk/iP/notes 0 "Same as Msg5\n" +call /kinetics/Bulk/iP/notes LOAD \ +"Same as Msg5" \ +"" +simundump kenz /kinetics/Bulk/iP/iP1 0 0 0 0 0 59.999 6.2501 60 15 0 0 "" red \ + 62 "" -4 -13 0 +simundump text /kinetics/Bulk/iP/iP1/notes 0 "" +call /kinetics/Bulk/iP/iP1/notes LOAD \ +"" +simundump kenz /kinetics/Bulk/iP/iP2 0 0 0 0 0 59.999 6.2501 60 15 0 0 "" red \ + 62 "" 0 -13 0 +simundump text /kinetics/Bulk/iP/iP2/notes 0 "" +call /kinetics/Bulk/iP/iP2/notes LOAD \ +"" +simundump kpool /kinetics/Bulk/PKA 0 0 0 0 0 0 0 0 60 0 /kinetics/geometry[3] \ + 43 yellow -3 -5 0 +simundump text /kinetics/Bulk/PKA/notes 0 "" +call /kinetics/Bulk/PKA/notes LOAD \ +"" +simundump kenz /kinetics/Bulk/PKA/PKA1 0 0 0 0 0 60 0.41667 40 10 0 0 "" red \ + 43 "" -4 -7 0 +simundump text /kinetics/Bulk/PKA/PKA1/notes 0 "" +call /kinetics/Bulk/PKA/PKA1/notes LOAD \ +"" +simundump kenz /kinetics/Bulk/PKA/PKA2 0 0 0 0 0 60 0.41667 40 10 0 0 "" red \ + 43 "" 0 -7 0 +simundump text /kinetics/Bulk/PKA/PKA2/notes 0 "" +call /kinetics/Bulk/PKA/PKA2/notes LOAD \ +"" +simundump kenz /kinetics/Bulk/PKA/PKA_exo 0 0 0 0 0 60 0.016667 8 2 0 0 "" \ + red 43 "" 1 -5 0 +simundump text /kinetics/Bulk/PKA/PKA_exo/notes 0 "" +call /kinetics/Bulk/PKA/PKA_exo/notes LOAD \ +"" +simundump kreac /kinetics/Bulk/activate_PKA 0 0.0016667 5 "" white yellow -11 \ + -10 0 +simundump text /kinetics/Bulk/activate_PKA/notes 0 "" +call /kinetics/Bulk/activate_PKA/notes LOAD \ +"" +simundump kpool /kinetics/Bulk/inact_PKA 0 0 1.6 1.6 96 96 0 0 60 0 \ + /kinetics/geometry[2] 51 yellow -12 -6 0 +simundump text /kinetics/Bulk/inact_PKA/notes 0 "" +call /kinetics/Bulk/inact_PKA/notes LOAD \ +"" +simundump kpool /kinetics/Bulk/inact_CaN 0 0 0.2 0.2 12 12 0 0 60 0 \ + /kinetics/geometry[6] blue yellow -13 -18 0 +simundump text /kinetics/Bulk/inact_CaN/notes 0 "" +call /kinetics/Bulk/inact_CaN/notes LOAD \ +"" +simundump kreac /kinetics/Bulk/activate_CaN 0 0.0055556 1 "" white yellow -10 \ + -16 0 +simundump text /kinetics/Bulk/activate_CaN/notes 0 "" +call /kinetics/Bulk/activate_CaN/notes LOAD \ +"" +simundump kpool /kinetics/Bulk/Ca_Spine 0 0 0.1 0.1 6 6 0 0 60 0 \ + /kinetics/geometry[2] 50 yellow -15 -13 0 +simundump text /kinetics/Bulk/Ca_Spine/notes 0 "" +call /kinetics/Bulk/Ca_Spine/notes LOAD \ +"" +simundump kreac /kinetics/Bulk/Ca_to_dend 0 10 1 "" white black -16 -22 0 +simundump text /kinetics/Bulk/Ca_to_dend/notes 0 "" +call /kinetics/Bulk/Ca_to_dend/notes LOAD \ +"" +simundump kreac /kinetics/Ca_to_bulk 0 10 100 "" white black -15 -3 0 +simundump text /kinetics/Ca_to_bulk/notes 0 "" +call /kinetics/Ca_to_bulk/notes LOAD \ +"" +simundump kpool /kinetics/Ca_dend 0 0 0 0 0 0 0 0 600 0 /kinetics/geometry[9] \ + 1 black -19 -25 0 +simundump text /kinetics/Ca_dend/notes 0 "" +call /kinetics/Ca_dend/notes LOAD \ +"" +simundump kpool /kinetics/Ca_dend_input 0 0 0 0 0 0 0 0 600 0 \ + /kinetics/geometry[9] 60 black -12 -28 0 +simundump text /kinetics/Ca_dend_input/notes 0 "" +call /kinetics/Ca_dend_input/notes LOAD \ +"" +simundump kreac /kinetics/dend_Ca_reac 0 100 100 "" white black -16 -27 0 +simundump text /kinetics/dend_Ca_reac/notes 0 "" +call /kinetics/dend_Ca_reac/notes LOAD \ +"" +simundump xgraph /graphs/conc1 0 0 800 9.6002e-07 0.10547 0 +simundump xgraph /graphs/conc2 0 0 800 0 18.128 0 +simundump xplot /graphs/conc1/Ca_PSD.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " 53 0 0 1 +simundump xplot /graphs/conc1/Ca_Bulk.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " 41 0 0 1 +simundump xplot /graphs/conc1/PKA.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " 43 0 0 1 +simundump xplot /graphs/conc1/Ca.P.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " blue 0 0 1 +simundump xplot /graphs/conc1/Ca_dend.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " 1 0 0 1 +simundump xplot /graphs/conc2/tot_PSD_R.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " blue 0 0 1 +simundump xplot /graphs/conc2/Rpp.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " 28 0 0 1 +simundump xgraph /moregraphs/conc3 0 0 800 0 33.241 0 +simundump xgraph /moregraphs/conc4 0 0 800 0 2 0 +simundump xcoredraw /edit/draw 0 -21 7 -30 11 +simundump xtree /edit/draw/tree 0 \ + /kinetics/#[],/kinetics/#[]/#[],/kinetics/#[]/#[]/#[][TYPE!=proto],/kinetics/#[]/#[]/#[][TYPE!=linkinfo]/##[] \ + "edit_elm.D ; drag_from_edit.w " auto 0.6 +simundump xtext /file/notes 0 1 +xtextload /file/notes \ +"26 Nov 2014. psd51.g: based on psd50.g which was" \ +"based on psd41_back_dend.g." \ +"07 Dec 2014. psd52.g: based on psd51. Slowed down Ca_to_dend by " \ +"10x while retaining Keq." +addmsg /kinetics/Bulk/iRpp /kinetics/exocytosis SUBSTRATE n +addmsg /kinetics/PSD/Rpp /kinetics/exocytosis PRODUCT n +addmsg /kinetics/Bulk/iR /kinetics/endocytosis SUBSTRATE n +addmsg /kinetics/PSD/R /kinetics/endocytosis PRODUCT n +addmsg /kinetics/PSD/KK/KK1 /kinetics/PSD/Rp MM_PRD pA +addmsg /kinetics/PSD/KK/KK2 /kinetics/PSD/Rp REAC sA B +addmsg /kinetics/PSD/P/P2 /kinetics/PSD/Rp MM_PRD pA +addmsg /kinetics/PSD/P/P1 /kinetics/PSD/Rp REAC sA B +addmsg /kinetics/PSD/Ca.P/Ca.P2 /kinetics/PSD/Rp MM_PRD pA +addmsg /kinetics/PSD/Ca.P/Ca.P1 /kinetics/PSD/Rp REAC sA B +addmsg /kinetics/PSD/P/P1 /kinetics/PSD/P REAC eA B +addmsg /kinetics/PSD/P/P2 /kinetics/PSD/P REAC eA B +addmsg /kinetics/PSD/P /kinetics/PSD/P/P1 ENZYME n +addmsg /kinetics/PSD/Rp /kinetics/PSD/P/P1 SUBSTRATE n +addmsg /kinetics/PSD/P /kinetics/PSD/P/P2 ENZYME n +addmsg /kinetics/PSD/Rpp /kinetics/PSD/P/P2 SUBSTRATE n +addmsg /kinetics/PSD/KK/KK1 /kinetics/PSD/KK REAC eA B +addmsg /kinetics/PSD/KK/KK2 /kinetics/PSD/KK REAC eA B +addmsg /kinetics/PSD/KK /kinetics/PSD/KK/KK1 ENZYME n +addmsg /kinetics/PSD/R /kinetics/PSD/KK/KK1 SUBSTRATE n +addmsg /kinetics/PSD/KK /kinetics/PSD/KK/KK2 ENZYME n +addmsg /kinetics/PSD/Rp /kinetics/PSD/KK/KK2 SUBSTRATE n +addmsg /kinetics/PSD/KK/KK2 /kinetics/PSD/Rpp MM_PRD pA +addmsg /kinetics/PSD/P/P2 /kinetics/PSD/Rpp REAC sA B +addmsg /kinetics/exocytosis /kinetics/PSD/Rpp REAC B A +addmsg /kinetics/Bulk/PKA/PKA_exo /kinetics/PSD/Rpp MM_PRD pA +addmsg /kinetics/PSD/Ca.P/Ca.P2 /kinetics/PSD/Rpp REAC sA B +addmsg /kinetics/PSD/KK/KK1 /kinetics/PSD/R REAC sA B +addmsg /kinetics/PSD/P/P1 /kinetics/PSD/R MM_PRD pA +addmsg /kinetics/PSD/Ca.P/Ca.P1 /kinetics/PSD/R MM_PRD pA +addmsg /kinetics/endocytosis /kinetics/PSD/R REAC B A +addmsg /kinetics/PSD/R /kinetics/PSD/tot_PSD_R SUMTOTAL n nInit +addmsg /kinetics/PSD/Rp /kinetics/PSD/tot_PSD_R SUMTOTAL n nInit +addmsg /kinetics/PSD/Rpp /kinetics/PSD/tot_PSD_R SUMTOTAL n nInit +addmsg /kinetics/PSD/psd_activate_CaN /kinetics/PSD/Ca_PSD REAC A B +addmsg /kinetics/PSD/psd_activate_CaN /kinetics/PSD/Ca_PSD REAC A B +addmsg /kinetics/Ca_to_bulk /kinetics/PSD/Ca_PSD REAC B A +addmsg /kinetics/PSD/Ca_reac /kinetics/PSD/Ca_PSD REAC B A +addmsg /kinetics/PSD/psd_activate_CaN /kinetics/PSD/psd_inact_CaN REAC A B +addmsg /kinetics/PSD/psd_inact_CaN /kinetics/PSD/psd_activate_CaN SUBSTRATE n +addmsg /kinetics/PSD/Ca_PSD /kinetics/PSD/psd_activate_CaN SUBSTRATE n +addmsg /kinetics/PSD/Ca_PSD /kinetics/PSD/psd_activate_CaN SUBSTRATE n +addmsg /kinetics/PSD/Ca.P /kinetics/PSD/psd_activate_CaN PRODUCT n +addmsg /kinetics/PSD/psd_activate_CaN /kinetics/PSD/Ca.P REAC B A +addmsg /kinetics/PSD/Ca.P/Ca.P2 /kinetics/PSD/Ca.P REAC eA B +addmsg /kinetics/PSD/Ca.P/Ca.P1 /kinetics/PSD/Ca.P REAC eA B +addmsg /kinetics/PSD/Ca.P /kinetics/PSD/Ca.P/Ca.P2 ENZYME n +addmsg /kinetics/PSD/Rpp /kinetics/PSD/Ca.P/Ca.P2 SUBSTRATE n +addmsg /kinetics/PSD/Ca.P /kinetics/PSD/Ca.P/Ca.P1 ENZYME n +addmsg /kinetics/PSD/Rp /kinetics/PSD/Ca.P/Ca.P1 SUBSTRATE n +addmsg /kinetics/PSD/Ca_reac /kinetics/PSD/Ca_input REAC A B +addmsg /kinetics/PSD/Ca_input /kinetics/PSD/Ca_reac SUBSTRATE n +addmsg /kinetics/PSD/Ca_PSD /kinetics/PSD/Ca_reac PRODUCT n +addmsg /kinetics/Bulk/iKK/iKK2 /kinetics/Bulk/iRpp MM_PRD pA +addmsg /kinetics/Bulk/iP/iP2 /kinetics/Bulk/iRpp REAC sA B +addmsg /kinetics/exocytosis /kinetics/Bulk/iRpp REAC A B +addmsg /kinetics/Bulk/PKA/PKA2 /kinetics/Bulk/iRpp MM_PRD pA +addmsg /kinetics/Bulk/PKA/PKA_exo /kinetics/Bulk/iRpp REAC sA B +addmsg /kinetics/Bulk/iKK/iKK1 /kinetics/Bulk/iRp MM_PRD pA +addmsg /kinetics/Bulk/iKK/iKK2 /kinetics/Bulk/iRp REAC sA B +addmsg /kinetics/Bulk/iP/iP2 /kinetics/Bulk/iRp MM_PRD pA +addmsg /kinetics/Bulk/iP/iP1 /kinetics/Bulk/iRp REAC sA B +addmsg /kinetics/Bulk/PKA/PKA1 /kinetics/Bulk/iRp MM_PRD pA +addmsg /kinetics/Bulk/PKA/PKA2 /kinetics/Bulk/iRp REAC sA B +addmsg /kinetics/Bulk/iKK/iKK1 /kinetics/Bulk/iR REAC sA B +addmsg /kinetics/Bulk/iP/iP1 /kinetics/Bulk/iR MM_PRD pA +addmsg /kinetics/Bulk/PKA/PKA1 /kinetics/Bulk/iR REAC sA B +addmsg /kinetics/endocytosis /kinetics/Bulk/iR REAC A B +addmsg /kinetics/Bulk/iKK/iKK1 /kinetics/Bulk/iKK REAC eA B +addmsg /kinetics/Bulk/iKK/iKK2 /kinetics/Bulk/iKK REAC eA B +addmsg /kinetics/Bulk/iKK /kinetics/Bulk/iKK/iKK1 ENZYME n +addmsg /kinetics/Bulk/iR /kinetics/Bulk/iKK/iKK1 SUBSTRATE n +addmsg /kinetics/Bulk/iKK /kinetics/Bulk/iKK/iKK2 ENZYME n +addmsg /kinetics/Bulk/iRp /kinetics/Bulk/iKK/iKK2 SUBSTRATE n +addmsg /kinetics/Bulk/iP/iP1 /kinetics/Bulk/iP REAC eA B +addmsg /kinetics/Bulk/iP/iP2 /kinetics/Bulk/iP REAC eA B +addmsg /kinetics/Bulk/activate_CaN /kinetics/Bulk/iP REAC B A +addmsg /kinetics/Bulk/iP /kinetics/Bulk/iP/iP1 ENZYME n +addmsg /kinetics/Bulk/iRp /kinetics/Bulk/iP/iP1 SUBSTRATE n +addmsg /kinetics/Bulk/iP /kinetics/Bulk/iP/iP2 ENZYME n +addmsg /kinetics/Bulk/iRpp /kinetics/Bulk/iP/iP2 SUBSTRATE n +addmsg /kinetics/Bulk/activate_PKA /kinetics/Bulk/PKA REAC B A +addmsg /kinetics/Bulk/PKA/PKA1 /kinetics/Bulk/PKA REAC eA B +addmsg /kinetics/Bulk/PKA/PKA2 /kinetics/Bulk/PKA REAC eA B +addmsg /kinetics/Bulk/PKA/PKA_exo /kinetics/Bulk/PKA REAC eA B +addmsg /kinetics/Bulk/PKA /kinetics/Bulk/PKA/PKA1 ENZYME n +addmsg /kinetics/Bulk/iR /kinetics/Bulk/PKA/PKA1 SUBSTRATE n +addmsg /kinetics/Bulk/PKA /kinetics/Bulk/PKA/PKA2 ENZYME n +addmsg /kinetics/Bulk/iRp /kinetics/Bulk/PKA/PKA2 SUBSTRATE n +addmsg /kinetics/Bulk/PKA /kinetics/Bulk/PKA/PKA_exo ENZYME n +addmsg /kinetics/Bulk/iRpp /kinetics/Bulk/PKA/PKA_exo SUBSTRATE n +addmsg /kinetics/Bulk/inact_PKA /kinetics/Bulk/activate_PKA SUBSTRATE n +addmsg /kinetics/Bulk/Ca_Spine /kinetics/Bulk/activate_PKA SUBSTRATE n +addmsg /kinetics/Bulk/PKA /kinetics/Bulk/activate_PKA PRODUCT n +addmsg /kinetics/Bulk/Ca_Spine /kinetics/Bulk/activate_PKA SUBSTRATE n +addmsg /kinetics/Bulk/activate_PKA /kinetics/Bulk/inact_PKA REAC A B +addmsg /kinetics/Bulk/activate_CaN /kinetics/Bulk/inact_CaN REAC A B +addmsg /kinetics/Bulk/inact_CaN /kinetics/Bulk/activate_CaN SUBSTRATE n +addmsg /kinetics/Bulk/iP /kinetics/Bulk/activate_CaN PRODUCT n +addmsg /kinetics/Bulk/Ca_Spine /kinetics/Bulk/activate_CaN SUBSTRATE n +addmsg /kinetics/Bulk/Ca_Spine /kinetics/Bulk/activate_CaN SUBSTRATE n +addmsg /kinetics/Bulk/activate_PKA /kinetics/Bulk/Ca_Spine REAC A B +addmsg /kinetics/Bulk/activate_PKA /kinetics/Bulk/Ca_Spine REAC A B +addmsg /kinetics/Bulk/activate_CaN /kinetics/Bulk/Ca_Spine REAC A B +addmsg /kinetics/Bulk/activate_CaN /kinetics/Bulk/Ca_Spine REAC A B +addmsg /kinetics/Ca_to_bulk /kinetics/Bulk/Ca_Spine REAC A B +addmsg /kinetics/Bulk/Ca_to_dend /kinetics/Bulk/Ca_Spine REAC A B +addmsg /kinetics/Bulk/Ca_Spine /kinetics/Bulk/Ca_to_dend SUBSTRATE n +addmsg /kinetics/Ca_dend /kinetics/Bulk/Ca_to_dend PRODUCT n +addmsg /kinetics/Bulk/Ca_Spine /kinetics/Ca_to_bulk SUBSTRATE n +addmsg /kinetics/PSD/Ca_PSD /kinetics/Ca_to_bulk PRODUCT n +addmsg /kinetics/dend_Ca_reac /kinetics/Ca_dend REAC B A +addmsg /kinetics/Bulk/Ca_to_dend /kinetics/Ca_dend REAC B A +addmsg /kinetics/dend_Ca_reac /kinetics/Ca_dend_input REAC A B +addmsg /kinetics/Ca_dend_input /kinetics/dend_Ca_reac SUBSTRATE n +addmsg /kinetics/Ca_dend /kinetics/dend_Ca_reac PRODUCT n +addmsg /kinetics/PSD/Ca_PSD /graphs/conc1/Ca_PSD.Co PLOT Co *Ca_PSD.Co *53 +addmsg /kinetics/Bulk/Ca_Spine /graphs/conc1/Ca_Bulk.Co PLOT Co *Ca_Bulk.Co *41 +addmsg /kinetics/Bulk/PKA /graphs/conc1/PKA.Co PLOT Co *PKA.Co *43 +addmsg /kinetics/PSD/Ca.P /graphs/conc1/Ca.P.Co PLOT Co *Ca.P.Co *blue +addmsg /kinetics/Ca_dend /graphs/conc1/Ca_dend.Co PLOT Co *Ca_dend.Co *1 +addmsg /kinetics/PSD/tot_PSD_R /graphs/conc2/tot_PSD_R.Co PLOT Co *tot_PSD_R.Co *blue +addmsg /kinetics/PSD/Rpp /graphs/conc2/Rpp.Co PLOT Co *Rpp.Co *28 +enddump +// End of dump + +call /kinetics/Bulk/iR/notes LOAD \ +"Same as Fus3" \ +"" +call /kinetics/Bulk/iKK/notes LOAD \ +"Same as Ste7" \ +"" +call /kinetics/Bulk/iP/notes LOAD \ +"Same as Msg5" \ +"" +complete_loading diff --git a/tests/py_rdesigneur/chem/psd53_old.g b/tests/py_rdesigneur/chem/psd53_old.g new file mode 100644 index 00000000..75469332 --- /dev/null +++ b/tests/py_rdesigneur/chem/psd53_old.g @@ -0,0 +1,474 @@ +//genesis +// kkit Version 11 flat dumpfile + +// Saved on Thu Jun 4 22:45:34 2015 + +include kkit {argv 1} + +FASTDT = 1e-05 +SIMDT = 0.0001 +CONTROLDT = 1 +PLOTDT = 0.2 +MAXTIME = 200 +TRANSIENT_TIME = 2 +VARIABLE_DT_FLAG = 1 +DEFAULT_VOL = 1e-19 +VERSION = 11.0 +setfield /file/modpath value /home2/bhalla/scripts/modules +kparms + +//genesis + +initdump -version 3 -ignoreorphans 1 +simobjdump doqcsinfo filename accessname accesstype transcriber developer \ + citation species tissue cellcompartment methodology sources \ + model_implementation model_validation x y z +simobjdump table input output alloced step_mode stepsize x y z +simobjdump xtree path script namemode sizescale +simobjdump xcoredraw xmin xmax ymin ymax +simobjdump xtext editable +simobjdump xgraph xmin xmax ymin ymax overlay +simobjdump xplot pixflags script fg ysquish do_slope wy +simobjdump group xtree_fg_req xtree_textfg_req plotfield expanded movealone \ + link savename file version md5sum mod_save_flag x y z +simobjdump geometry size dim shape outside xtree_fg_req xtree_textfg_req x y \ + z +simobjdump kpool DiffConst CoInit Co n nInit mwt nMin vol slave_enable \ + geomname xtree_fg_req xtree_textfg_req x y z +simobjdump kreac kf kb notes xtree_fg_req xtree_textfg_req x y z +simobjdump kenz CoComplexInit CoComplex nComplexInit nComplex vol k1 k2 k3 \ + keepconc usecomplex notes xtree_fg_req xtree_textfg_req link x y z +simobjdump stim level1 width1 delay1 level2 width2 delay2 baselevel trig_time \ + trig_mode notes xtree_fg_req xtree_textfg_req is_running x y z +simobjdump xtab input output alloced step_mode stepsize notes editfunc \ + xtree_fg_req xtree_textfg_req baselevel last_x last_y is_running x y z +simobjdump kchan perm gmax Vm is_active use_nernst notes xtree_fg_req \ + xtree_textfg_req x y z +simobjdump transport input output alloced step_mode stepsize dt delay clock \ + kf xtree_fg_req xtree_textfg_req x y z +simobjdump proto x y z +simobjdump text str +simundump geometry /kinetics/geometry 0 1.6667e-21 3 sphere "" white black 5 \ + -4 0 +simundump geometry /kinetics/geometry[1] 0 1e-19 3 sphere "" white black 5 -2 \ + 0 +simundump geometry /kinetics/geometry[2] 0 1e-20 3 sphere "" white black 2 2 \ + 0 +simundump geometry /kinetics/geometry[3] 0 1e-20 3 sphere "" white black 4 8 \ + 0 +simundump geometry /kinetics/geometry[4] 0 1e-20 3 sphere "" white black 2 \ + -17 0 +simundump geometry /kinetics/geometry[5] 0 1e-20 3 sphere "" white black 5 \ + -13 0 +simundump geometry /kinetics/geometry[6] 0 1e-19 3 sphere "" white black 0 7 \ + 0 +simundump geometry /kinetics/geometry[7] 0 1e-20 3 sphere "" white black 0 -3 \ + 0 +simundump geometry /kinetics/geometry[8] 0 1e-20 3 sphere "" white black -1 \ + -18 0 +simundump geometry /kinetics/geometry[9] 0 1e-18 3 sphere "" white black 0 0 \ + 0 +simundump text /kinetics/notes 0 "" +call /kinetics/notes LOAD \ +"" +simundump text /kinetics/geometry/notes 0 "" +call /kinetics/geometry/notes LOAD \ +"" +simundump text /kinetics/geometry[1]/notes 0 "" +call /kinetics/geometry[1]/notes LOAD \ +"" +simundump text /kinetics/geometry[2]/notes 0 "" +call /kinetics/geometry[2]/notes LOAD \ +"" +simundump text /kinetics/geometry[3]/notes 0 "" +call /kinetics/geometry[3]/notes LOAD \ +"" +simundump text /kinetics/geometry[4]/notes 0 "" +call /kinetics/geometry[4]/notes LOAD \ +"" +simundump text /kinetics/geometry[5]/notes 0 "" +call /kinetics/geometry[5]/notes LOAD \ +"" +simundump text /kinetics/geometry[6]/notes 0 "" +call /kinetics/geometry[6]/notes LOAD \ +"" +simundump text /kinetics/geometry[7]/notes 0 "" +call /kinetics/geometry[7]/notes LOAD \ +"" +simundump text /kinetics/geometry[8]/notes 0 "" +call /kinetics/geometry[8]/notes LOAD \ +"" +simundump text /kinetics/geometry[9]/notes 0 "" +call /kinetics/geometry[9]/notes LOAD \ +"" +simundump kreac /kinetics/exocytosis 0 0.01 0 "" white black 4 -5 0 +simundump text /kinetics/exocytosis/notes 0 "" +call /kinetics/exocytosis/notes LOAD \ +"" +simundump kreac /kinetics/endocytosis 0 0 4 "" white black -7 -5 0 +simundump text /kinetics/endocytosis/notes 0 "" +call /kinetics/endocytosis/notes LOAD \ +"" +simundump group /kinetics/PSD 0 0 black x 0 1 "" PSD defaultfile.g 0 0 0 -10 \ + -3 0 +simundump text /kinetics/PSD/notes 0 "" +call /kinetics/PSD/notes LOAD \ +"" +simundump kpool /kinetics/PSD/Rp 0 0 0 0 0 0 0 0 6 0 /kinetics/geometry[1] \ + blue 0 -4 1 0 +simundump text /kinetics/PSD/Rp/notes 0 "" +call /kinetics/PSD/Rp/notes LOAD \ +"" +simundump kpool /kinetics/PSD/P 0 0 1 1 6 6 0 0 6 0 /kinetics/geometry[1] 61 \ + 0 -4 -2 0 +simundump text /kinetics/PSD/P/notes 0 "" +call /kinetics/PSD/P/notes LOAD \ +"" +simundump kenz /kinetics/PSD/P/P1 0 0 0 0 0 60 10.417 20 5 0 0 "" red 61 "" \ + -6 -1 0 +simundump text /kinetics/PSD/P/P1/notes 0 "" +call /kinetics/PSD/P/P1/notes LOAD \ +"" +simundump kenz /kinetics/PSD/P/P2 0 0 0 0 0 60 10.417 20 5 0 0 "" red 61 "" \ + -2 -1 0 +simundump text /kinetics/PSD/P/P2/notes 0 "" +call /kinetics/PSD/P/P2/notes LOAD \ +"" +simundump kpool /kinetics/PSD/KK 0 0 3 3 18 18 0 0 6 0 /kinetics/geometry[1] \ + 49 0 -4 4 0 +simundump text /kinetics/PSD/KK/notes 0 "" +call /kinetics/PSD/KK/notes LOAD \ +"" +simundump kenz /kinetics/PSD/KK/KK1 0 0 0 0 0 60 4.1667 40 10 0 0 "" red 49 \ + "" -6 3 0 +simundump text /kinetics/PSD/KK/KK1/notes 0 "" +call /kinetics/PSD/KK/KK1/notes LOAD \ +"" +simundump kenz /kinetics/PSD/KK/KK2 0 0 0 0 0 60 4.1667 40 10 0 0 "" red 49 \ + "" -2 3 0 +simundump text /kinetics/PSD/KK/KK2/notes 0 "" +call /kinetics/PSD/KK/KK2/notes LOAD \ +"" +simundump kpool /kinetics/PSD/Rpp 0 0 0 0 0 0 0 0 6 0 /kinetics/geometry[1] \ + 28 0 0 1 0 +simundump text /kinetics/PSD/Rpp/notes 0 "" +call /kinetics/PSD/Rpp/notes LOAD \ +"" +simundump kpool /kinetics/PSD/R 0 0 0 0 0 0 0 0 6 0 /kinetics/geometry[1] 4 0 \ + -8 1 0 +simundump text /kinetics/PSD/R/notes 0 "" +call /kinetics/PSD/R/notes LOAD \ +"" +simundump kpool /kinetics/PSD/tot_PSD_R 0 0 0 0 0 0 0 0 6 0 \ + /kinetics/geometry[4] blue 0 -4 7 0 +simundump text /kinetics/PSD/tot_PSD_R/notes 0 "" +call /kinetics/PSD/tot_PSD_R/notes LOAD \ +"" +simundump kpool /kinetics/PSD/Ca_PSD 0 1e-11 0.1 0.1 0.6 0.6 0 0 6 0 \ + /kinetics/geometry[5] 53 0 -15 2 0 +simundump text /kinetics/PSD/Ca_PSD/notes 0 "" +call /kinetics/PSD/Ca_PSD/notes LOAD \ +"" +simundump kpool /kinetics/PSD/psd_inact_CaN 0 0 1 1 6 6 0 0 6 0 \ + /kinetics/geometry[7] blue 0 -12 5 0 +simundump text /kinetics/PSD/psd_inact_CaN/notes 0 "" +call /kinetics/PSD/psd_inact_CaN/notes LOAD \ +"" +simundump kreac /kinetics/PSD/psd_activate_CaN 0 0.27778 1 "" white 0 -11 1 0 +simundump text /kinetics/PSD/psd_activate_CaN/notes 0 "" +call /kinetics/PSD/psd_activate_CaN/notes LOAD \ +"" +simundump kpool /kinetics/PSD/Ca.P 0 0 0 0 0 0 0 0 6 0 /kinetics/geometry[7] \ + blue 0 -4 -4 0 +simundump text /kinetics/PSD/Ca.P/notes 0 "" +call /kinetics/PSD/Ca.P/notes LOAD \ +"" +simundump kenz /kinetics/PSD/Ca.P/Ca.P2 0 0 0 0 0 6 1.6667 40 10 0 0 "" red \ + blue "" -2 -3 0 +simundump text /kinetics/PSD/Ca.P/Ca.P2/notes 0 "" +call /kinetics/PSD/Ca.P/Ca.P2/notes LOAD \ +"" +simundump kenz /kinetics/PSD/Ca.P/Ca.P1 0 0 0 0 0 6 1.6667 40 10 0 0 "" red \ + blue "" -6 -3 0 +simundump text /kinetics/PSD/Ca.P/Ca.P1/notes 0 "" +call /kinetics/PSD/Ca.P/Ca.P1/notes LOAD \ +"" +simundump kpool /kinetics/PSD/Ca_input 0 0 0.1 0.1 0.6 0.6 0 0 6 4 \ + /kinetics/geometry[8] 60 black -12 9 0 +simundump text /kinetics/PSD/Ca_input/notes 0 "" +call /kinetics/PSD/Ca_input/notes LOAD \ +"" +simundump kreac /kinetics/PSD/Ca_reac 0 100 100 "" white black -17 6 0 +simundump text /kinetics/PSD/Ca_reac/notes 0 "" +call /kinetics/PSD/Ca_reac/notes LOAD \ +"" +simundump group /kinetics/Bulk 0 yellow black x 0 0 "" Bulk defaultfile.g 0 0 \ + 0 -6 -16 0 +simundump text /kinetics/Bulk/notes 0 "" +call /kinetics/Bulk/notes LOAD \ +"" +simundump kpool /kinetics/Bulk/iRpp 0 0 0 0 0 0 0 0 59.999 0 \ + /kinetics/geometry 29 yellow 2 -11 0 +simundump text /kinetics/Bulk/iRpp/notes 0 "" +call /kinetics/Bulk/iRpp/notes LOAD \ +"" +simundump kpool /kinetics/Bulk/iRp 0 0 0 0 0 0 0 0 59.999 0 \ + /kinetics/geometry blue yellow -2 -11 0 +simundump text /kinetics/Bulk/iRp/notes 0 "" +call /kinetics/Bulk/iRp/notes LOAD \ +"" +simundump kpool /kinetics/Bulk/iR 0 0 4.0001 4.0001 240 240 0 0 59.999 0 \ + /kinetics/geometry 0 yellow -6 -11 0 +simundump text /kinetics/Bulk/iR/notes 0 "Same as Fus3\n" +call /kinetics/Bulk/iR/notes LOAD \ +"Same as Fus3" \ +"" +simundump kpool /kinetics/Bulk/iKK 0 0 1 1 59.999 59.999 0 0 59.999 0 \ + /kinetics/geometry 50 yellow -2 -8 0 +simundump text /kinetics/Bulk/iKK/notes 0 "Same as Ste7\n" +call /kinetics/Bulk/iKK/notes LOAD \ +"Same as Ste7" \ +"" +simundump kenz /kinetics/Bulk/iKK/iKK1 0 0 0 0 0 59.999 0.83335 40 10 0 0 "" \ + red 50 "" -4 -9 0 +simundump text /kinetics/Bulk/iKK/iKK1/notes 0 "" +call /kinetics/Bulk/iKK/iKK1/notes LOAD \ +"" +simundump kenz /kinetics/Bulk/iKK/iKK2 0 0 0 0 0 59.999 0.83335 40 10 0 0 "" \ + red 50 "" 0 -9 0 +simundump text /kinetics/Bulk/iKK/iKK2/notes 0 "" +call /kinetics/Bulk/iKK/iKK2/notes LOAD \ +"" +simundump kpool /kinetics/Bulk/iP 0 0 0.50001 0.50001 30 30 0 0 59.999 0 \ + /kinetics/geometry 62 yellow -2 -14 0 +simundump text /kinetics/Bulk/iP/notes 0 "Same as Msg5\n" +call /kinetics/Bulk/iP/notes LOAD \ +"Same as Msg5" \ +"" +simundump kenz /kinetics/Bulk/iP/iP1 0 0 0 0 0 59.999 6.2501 60 15 0 0 "" red \ + 62 "" -4 -13 0 +simundump text /kinetics/Bulk/iP/iP1/notes 0 "" +call /kinetics/Bulk/iP/iP1/notes LOAD \ +"" +simundump kenz /kinetics/Bulk/iP/iP2 0 0 0 0 0 59.999 6.2501 60 15 0 0 "" red \ + 62 "" 0 -13 0 +simundump text /kinetics/Bulk/iP/iP2/notes 0 "" +call /kinetics/Bulk/iP/iP2/notes LOAD \ +"" +simundump kpool /kinetics/Bulk/PKA 0 0 0 0 0 0 0 0 60 0 /kinetics/geometry[3] \ + 43 yellow -3 -5 0 +simundump text /kinetics/Bulk/PKA/notes 0 "" +call /kinetics/Bulk/PKA/notes LOAD \ +"" +simundump kenz /kinetics/Bulk/PKA/PKA1 0 0 0 0 0 60 0.41667 40 10 0 0 "" red \ + 43 "" -4 -7 0 +simundump text /kinetics/Bulk/PKA/PKA1/notes 0 "" +call /kinetics/Bulk/PKA/PKA1/notes LOAD \ +"" +simundump kenz /kinetics/Bulk/PKA/PKA2 0 0 0 0 0 60 0.41667 40 10 0 0 "" red \ + 43 "" 0 -7 0 +simundump text /kinetics/Bulk/PKA/PKA2/notes 0 "" +call /kinetics/Bulk/PKA/PKA2/notes LOAD \ +"" +simundump kenz /kinetics/Bulk/PKA/PKA_exo 0 0 0 0 0 60 0.016667 8 2 0 0 "" \ + red 43 "" 1 -5 0 +simundump text /kinetics/Bulk/PKA/PKA_exo/notes 0 "" +call /kinetics/Bulk/PKA/PKA_exo/notes LOAD \ +"" +simundump kreac /kinetics/Bulk/activate_PKA 0 0.0016667 5 "" white yellow -11 \ + -10 0 +simundump text /kinetics/Bulk/activate_PKA/notes 0 "" +call /kinetics/Bulk/activate_PKA/notes LOAD \ +"" +simundump kpool /kinetics/Bulk/inact_PKA 0 0 1.6 1.6 96 96 0 0 60 0 \ + /kinetics/geometry[2] 51 yellow -12 -6 0 +simundump text /kinetics/Bulk/inact_PKA/notes 0 "" +call /kinetics/Bulk/inact_PKA/notes LOAD \ +"" +simundump kpool /kinetics/Bulk/inact_CaN 0 0 0.2 0.2 12 12 0 0 60 0 \ + /kinetics/geometry[6] blue yellow -13 -18 0 +simundump text /kinetics/Bulk/inact_CaN/notes 0 "" +call /kinetics/Bulk/inact_CaN/notes LOAD \ +"" +simundump kreac /kinetics/Bulk/activate_CaN 0 0.0055556 1 "" white yellow -10 \ + -16 0 +simundump text /kinetics/Bulk/activate_CaN/notes 0 "" +call /kinetics/Bulk/activate_CaN/notes LOAD \ +"" +simundump kpool /kinetics/Bulk/Ca_Spine 0 1e-11 0.1 0.1 6 6 0 0 60 0 \ + /kinetics/geometry[2] 50 yellow -15 -13 0 +simundump text /kinetics/Bulk/Ca_Spine/notes 0 "" +call /kinetics/Bulk/Ca_Spine/notes LOAD \ +"" +simundump kpool /kinetics/Ca_dend 0 1e-11 0 0 0 0 0 0 600 0 \ + /kinetics/geometry[9] 1 black -19 -25 0 +simundump text /kinetics/Ca_dend/notes 0 "" +call /kinetics/Ca_dend/notes LOAD \ +"" +simundump kpool /kinetics/Ca_dend_input 0 0 0 0 0 0 0 0 600 0 \ + /kinetics/geometry[9] 60 black -12 -28 0 +simundump text /kinetics/Ca_dend_input/notes 0 "" +call /kinetics/Ca_dend_input/notes LOAD \ +"" +simundump kreac /kinetics/dend_Ca_reac 0 100 100 "" white black -16 -27 0 +simundump text /kinetics/dend_Ca_reac/notes 0 "" +call /kinetics/dend_Ca_reac/notes LOAD \ +"" +simundump xgraph /graphs/conc1 0 0 800 9.6002e-07 0.10547 0 +simundump xgraph /graphs/conc2 0 0 800 0 18.128 0 +simundump xplot /graphs/conc1/Ca_PSD.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " 53 0 0 1 +simundump xplot /graphs/conc1/Ca_Bulk.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " 41 0 0 1 +simundump xplot /graphs/conc1/PKA.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " 43 0 0 1 +simundump xplot /graphs/conc1/Ca.P.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " blue 0 0 1 +simundump xplot /graphs/conc1/Ca_dend.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " 1 0 0 1 +simundump xplot /graphs/conc2/tot_PSD_R.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " blue 0 0 1 +simundump xplot /graphs/conc2/Rpp.Co 3 524288 \ + "delete_plot.w ; edit_plot.D " 28 0 0 1 +simundump xgraph /moregraphs/conc3 0 0 800 0 33.241 0 +simundump xgraph /moregraphs/conc4 0 0 800 0 2 0 +simundump xcoredraw /edit/draw 0 -21 7 -30 11 +simundump xtree /edit/draw/tree 0 \ + /kinetics/#[],/kinetics/#[]/#[],/kinetics/#[]/#[]/#[][TYPE!=proto],/kinetics/#[]/#[]/#[][TYPE!=linkinfo]/##[] \ + "edit_elm.D ; drag_from_edit.w " auto 0.6 +simundump xtext /file/notes 0 1 +xtextload /file/notes \ +"26 Nov 2014. psd51.g: based on psd50.g which was" \ +"based on psd41_back_dend.g." \ +"07 Dec 2014. psd52.g: based on psd51. Slowed down Ca_to_dend by " \ +"10x while retaining Keq." \ +"04 June 2015. psd53.g: Removed the reacts between dend, head and" \ +"psd. Will use diffusion instead." +addmsg /kinetics/Bulk/iRpp /kinetics/exocytosis SUBSTRATE n +addmsg /kinetics/PSD/Rpp /kinetics/exocytosis PRODUCT n +addmsg /kinetics/Bulk/iR /kinetics/endocytosis SUBSTRATE n +addmsg /kinetics/PSD/R /kinetics/endocytosis PRODUCT n +addmsg /kinetics/PSD/KK/KK1 /kinetics/PSD/Rp MM_PRD pA +addmsg /kinetics/PSD/KK/KK2 /kinetics/PSD/Rp REAC sA B +addmsg /kinetics/PSD/P/P2 /kinetics/PSD/Rp MM_PRD pA +addmsg /kinetics/PSD/P/P1 /kinetics/PSD/Rp REAC sA B +addmsg /kinetics/PSD/Ca.P/Ca.P2 /kinetics/PSD/Rp MM_PRD pA +addmsg /kinetics/PSD/Ca.P/Ca.P1 /kinetics/PSD/Rp REAC sA B +addmsg /kinetics/PSD/P/P1 /kinetics/PSD/P REAC eA B +addmsg /kinetics/PSD/P/P2 /kinetics/PSD/P REAC eA B +addmsg /kinetics/PSD/P /kinetics/PSD/P/P1 ENZYME n +addmsg /kinetics/PSD/Rp /kinetics/PSD/P/P1 SUBSTRATE n +addmsg /kinetics/PSD/P /kinetics/PSD/P/P2 ENZYME n +addmsg /kinetics/PSD/Rpp /kinetics/PSD/P/P2 SUBSTRATE n +addmsg /kinetics/PSD/KK/KK1 /kinetics/PSD/KK REAC eA B +addmsg /kinetics/PSD/KK/KK2 /kinetics/PSD/KK REAC eA B +addmsg /kinetics/PSD/KK /kinetics/PSD/KK/KK1 ENZYME n +addmsg /kinetics/PSD/R /kinetics/PSD/KK/KK1 SUBSTRATE n +addmsg /kinetics/PSD/KK /kinetics/PSD/KK/KK2 ENZYME n +addmsg /kinetics/PSD/Rp /kinetics/PSD/KK/KK2 SUBSTRATE n +addmsg /kinetics/PSD/KK/KK2 /kinetics/PSD/Rpp MM_PRD pA +addmsg /kinetics/PSD/P/P2 /kinetics/PSD/Rpp REAC sA B +addmsg /kinetics/exocytosis /kinetics/PSD/Rpp REAC B A +addmsg /kinetics/Bulk/PKA/PKA_exo /kinetics/PSD/Rpp MM_PRD pA +addmsg /kinetics/PSD/Ca.P/Ca.P2 /kinetics/PSD/Rpp REAC sA B +addmsg /kinetics/PSD/KK/KK1 /kinetics/PSD/R REAC sA B +addmsg /kinetics/PSD/P/P1 /kinetics/PSD/R MM_PRD pA +addmsg /kinetics/PSD/Ca.P/Ca.P1 /kinetics/PSD/R MM_PRD pA +addmsg /kinetics/endocytosis /kinetics/PSD/R REAC B A +addmsg /kinetics/PSD/R /kinetics/PSD/tot_PSD_R SUMTOTAL n nInit +addmsg /kinetics/PSD/Rp /kinetics/PSD/tot_PSD_R SUMTOTAL n nInit +addmsg /kinetics/PSD/Rpp /kinetics/PSD/tot_PSD_R SUMTOTAL n nInit +addmsg /kinetics/PSD/psd_activate_CaN /kinetics/PSD/Ca_PSD REAC A B +addmsg /kinetics/PSD/psd_activate_CaN /kinetics/PSD/Ca_PSD REAC A B +addmsg /kinetics/PSD/Ca_reac /kinetics/PSD/Ca_PSD REAC B A +addmsg /kinetics/PSD/psd_activate_CaN /kinetics/PSD/psd_inact_CaN REAC A B +addmsg /kinetics/PSD/psd_inact_CaN /kinetics/PSD/psd_activate_CaN SUBSTRATE n +addmsg /kinetics/PSD/Ca_PSD /kinetics/PSD/psd_activate_CaN SUBSTRATE n +addmsg /kinetics/PSD/Ca_PSD /kinetics/PSD/psd_activate_CaN SUBSTRATE n +addmsg /kinetics/PSD/Ca.P /kinetics/PSD/psd_activate_CaN PRODUCT n +addmsg /kinetics/PSD/psd_activate_CaN /kinetics/PSD/Ca.P REAC B A +addmsg /kinetics/PSD/Ca.P/Ca.P2 /kinetics/PSD/Ca.P REAC eA B +addmsg /kinetics/PSD/Ca.P/Ca.P1 /kinetics/PSD/Ca.P REAC eA B +addmsg /kinetics/PSD/Ca.P /kinetics/PSD/Ca.P/Ca.P2 ENZYME n +addmsg /kinetics/PSD/Rpp /kinetics/PSD/Ca.P/Ca.P2 SUBSTRATE n +addmsg /kinetics/PSD/Ca.P /kinetics/PSD/Ca.P/Ca.P1 ENZYME n +addmsg /kinetics/PSD/Rp /kinetics/PSD/Ca.P/Ca.P1 SUBSTRATE n +addmsg /kinetics/PSD/Ca_reac /kinetics/PSD/Ca_input REAC A B +addmsg /kinetics/PSD/Ca_input /kinetics/PSD/Ca_reac SUBSTRATE n +addmsg /kinetics/PSD/Ca_PSD /kinetics/PSD/Ca_reac PRODUCT n +addmsg /kinetics/Bulk/iKK/iKK2 /kinetics/Bulk/iRpp MM_PRD pA +addmsg /kinetics/Bulk/iP/iP2 /kinetics/Bulk/iRpp REAC sA B +addmsg /kinetics/exocytosis /kinetics/Bulk/iRpp REAC A B +addmsg /kinetics/Bulk/PKA/PKA2 /kinetics/Bulk/iRpp MM_PRD pA +addmsg /kinetics/Bulk/PKA/PKA_exo /kinetics/Bulk/iRpp REAC sA B +addmsg /kinetics/Bulk/iKK/iKK1 /kinetics/Bulk/iRp MM_PRD pA +addmsg /kinetics/Bulk/iKK/iKK2 /kinetics/Bulk/iRp REAC sA B +addmsg /kinetics/Bulk/iP/iP2 /kinetics/Bulk/iRp MM_PRD pA +addmsg /kinetics/Bulk/iP/iP1 /kinetics/Bulk/iRp REAC sA B +addmsg /kinetics/Bulk/PKA/PKA1 /kinetics/Bulk/iRp MM_PRD pA +addmsg /kinetics/Bulk/PKA/PKA2 /kinetics/Bulk/iRp REAC sA B +addmsg /kinetics/Bulk/iKK/iKK1 /kinetics/Bulk/iR REAC sA B +addmsg /kinetics/Bulk/iP/iP1 /kinetics/Bulk/iR MM_PRD pA +addmsg /kinetics/Bulk/PKA/PKA1 /kinetics/Bulk/iR REAC sA B +addmsg /kinetics/endocytosis /kinetics/Bulk/iR REAC A B +addmsg /kinetics/Bulk/iKK/iKK1 /kinetics/Bulk/iKK REAC eA B +addmsg /kinetics/Bulk/iKK/iKK2 /kinetics/Bulk/iKK REAC eA B +addmsg /kinetics/Bulk/iKK /kinetics/Bulk/iKK/iKK1 ENZYME n +addmsg /kinetics/Bulk/iR /kinetics/Bulk/iKK/iKK1 SUBSTRATE n +addmsg /kinetics/Bulk/iKK /kinetics/Bulk/iKK/iKK2 ENZYME n +addmsg /kinetics/Bulk/iRp /kinetics/Bulk/iKK/iKK2 SUBSTRATE n +addmsg /kinetics/Bulk/iP/iP1 /kinetics/Bulk/iP REAC eA B +addmsg /kinetics/Bulk/iP/iP2 /kinetics/Bulk/iP REAC eA B +addmsg /kinetics/Bulk/activate_CaN /kinetics/Bulk/iP REAC B A +addmsg /kinetics/Bulk/iP /kinetics/Bulk/iP/iP1 ENZYME n +addmsg /kinetics/Bulk/iRp /kinetics/Bulk/iP/iP1 SUBSTRATE n +addmsg /kinetics/Bulk/iP /kinetics/Bulk/iP/iP2 ENZYME n +addmsg /kinetics/Bulk/iRpp /kinetics/Bulk/iP/iP2 SUBSTRATE n +addmsg /kinetics/Bulk/activate_PKA /kinetics/Bulk/PKA REAC B A +addmsg /kinetics/Bulk/PKA/PKA1 /kinetics/Bulk/PKA REAC eA B +addmsg /kinetics/Bulk/PKA/PKA2 /kinetics/Bulk/PKA REAC eA B +addmsg /kinetics/Bulk/PKA/PKA_exo /kinetics/Bulk/PKA REAC eA B +addmsg /kinetics/Bulk/PKA /kinetics/Bulk/PKA/PKA1 ENZYME n +addmsg /kinetics/Bulk/iR /kinetics/Bulk/PKA/PKA1 SUBSTRATE n +addmsg /kinetics/Bulk/PKA /kinetics/Bulk/PKA/PKA2 ENZYME n +addmsg /kinetics/Bulk/iRp /kinetics/Bulk/PKA/PKA2 SUBSTRATE n +addmsg /kinetics/Bulk/PKA /kinetics/Bulk/PKA/PKA_exo ENZYME n +addmsg /kinetics/Bulk/iRpp /kinetics/Bulk/PKA/PKA_exo SUBSTRATE n +addmsg /kinetics/Bulk/inact_PKA /kinetics/Bulk/activate_PKA SUBSTRATE n +addmsg /kinetics/Bulk/Ca_Spine /kinetics/Bulk/activate_PKA SUBSTRATE n +addmsg /kinetics/Bulk/PKA /kinetics/Bulk/activate_PKA PRODUCT n +addmsg /kinetics/Bulk/Ca_Spine /kinetics/Bulk/activate_PKA SUBSTRATE n +addmsg /kinetics/Bulk/activate_PKA /kinetics/Bulk/inact_PKA REAC A B +addmsg /kinetics/Bulk/activate_CaN /kinetics/Bulk/inact_CaN REAC A B +addmsg /kinetics/Bulk/inact_CaN /kinetics/Bulk/activate_CaN SUBSTRATE n +addmsg /kinetics/Bulk/iP /kinetics/Bulk/activate_CaN PRODUCT n +addmsg /kinetics/Bulk/Ca_Spine /kinetics/Bulk/activate_CaN SUBSTRATE n +addmsg /kinetics/Bulk/Ca_Spine /kinetics/Bulk/activate_CaN SUBSTRATE n +addmsg /kinetics/Bulk/activate_PKA /kinetics/Bulk/Ca_Spine REAC A B +addmsg /kinetics/Bulk/activate_PKA /kinetics/Bulk/Ca_Spine REAC A B +addmsg /kinetics/Bulk/activate_CaN /kinetics/Bulk/Ca_Spine REAC A B +addmsg /kinetics/Bulk/activate_CaN /kinetics/Bulk/Ca_Spine REAC A B +addmsg /kinetics/dend_Ca_reac /kinetics/Ca_dend REAC B A +addmsg /kinetics/dend_Ca_reac /kinetics/Ca_dend_input REAC A B +addmsg /kinetics/Ca_dend_input /kinetics/dend_Ca_reac SUBSTRATE n +addmsg /kinetics/Ca_dend /kinetics/dend_Ca_reac PRODUCT n +addmsg /kinetics/PSD/Ca_PSD /graphs/conc1/Ca_PSD.Co PLOT Co *Ca_PSD.Co *53 +addmsg /kinetics/Bulk/Ca_Spine /graphs/conc1/Ca_Bulk.Co PLOT Co *Ca_Bulk.Co *41 +addmsg /kinetics/Bulk/PKA /graphs/conc1/PKA.Co PLOT Co *PKA.Co *43 +addmsg /kinetics/PSD/Ca.P /graphs/conc1/Ca.P.Co PLOT Co *Ca.P.Co *blue +addmsg /kinetics/Ca_dend /graphs/conc1/Ca_dend.Co PLOT Co *Ca_dend.Co *1 +addmsg /kinetics/PSD/tot_PSD_R /graphs/conc2/tot_PSD_R.Co PLOT Co *tot_PSD_R.Co *blue +addmsg /kinetics/PSD/Rpp /graphs/conc2/Rpp.Co PLOT Co *Rpp.Co *28 +enddump +// End of dump + +call /kinetics/Bulk/iR/notes LOAD \ +"Same as Fus3" \ +"" +call /kinetics/Bulk/iKK/notes LOAD \ +"Same as Ste7" \ +"" +call /kinetics/Bulk/iP/notes LOAD \ +"Same as Msg5" \ +"" +complete_loading diff --git a/tests/py_rdesigneur/test_1_minimalModel.py b/tests/py_rdesigneur/test_1_minimalModel.py new file mode 100644 index 00000000..10b3ed15 --- /dev/null +++ b/tests/py_rdesigneur/test_1_minimalModel.py @@ -0,0 +1,50 @@ +# Rdesigneur tutorial converted to a test. +import moose +print("[INFO ] MOOSE version=%s, loc=%s" % (moose.version(), moose.__file__)) +import rdesigneur as rd + +def test_simple(): + """First test. + >>> test_simple() # doctest: +NORMALIZE_WHITESPACE + Rdesigneur: Elec model has 1 compartments and 0 spines on 0 compartments. + + [/model[0]/elec[0]/soma[0]] + Cm =7.853981633975e-09 + Em =-0.0544 + Im =1.3194689277024895e-08 + Ra =7639437.268410473 + Rm =424413.1773342278 + Vm =-0.06 + className =ZombieCompartment + diameter =0.0005 + dt =0.0 + fieldIndex =0 + idValue =455 + index =0 + initVm =-0.065 + inject =0.0 + length =0.0005 + name =soma + numData =1 + numField =1 + path =/model[0]/elec[0]/soma[0] + tick =-2 + x =0.0005 + x0 =0.0 + y =0.0 + y0 =0.0 + z =0.0 + z0 =0.0 + + INCOMING: + /model[0]/elec[0]/soma ('parentMsg',) <--- /model[0]/elec ('childOut',) + OUTGOING: + """ + rdes = rd.rdesigneur() + rdes.buildModel() + moose.showfields(rdes.soma) + moose.showmsg(rdes.soma) + +if __name__ == '__main__': + import doctest + doctest.testmod() diff --git a/tests/py_rdesigneur/test_20_currentPulse.py b/tests/py_rdesigneur/test_20_currentPulse.py new file mode 100644 index 00000000..4ab405b0 --- /dev/null +++ b/tests/py_rdesigneur/test_20_currentPulse.py @@ -0,0 +1,48 @@ +import matplotlib as mpl +mpl.use('Agg') +import numpy as np +import matplotlib.pyplot as plt +import moose +print("[INFO ] MOOSE version=%s, loc=%s" % (moose.version(), moose.__file__)) +import rdesigneur as rd + +expected = (-0.051693861353435865, 0.004062563722923687 + , np.array([7, 8, 11, 17, 34, 1852, 49, 31, 34, 958]) + , np.array([-0.065, -0.06309117, -0.06118235, -0.05927352, -0.05736469, + -0.05545587, -0.05354704, -0.05163822, -0.04972939, -0.04782056, + -0.04591174])) + +def test_msgs(): + if moose.exists('/model'): + moose.delete('/model') + rdes = rd.rdesigneur( + stimList = [['soma', '1', '.', 'inject', '(t>0.1 && t<0.2) * 2e-8' ]], + plotList = [['soma', '1', '.', 'Vm', 'Soma membrane potential']] + ) + rdes.buildModel() + msgs = moose.listmsg(rdes.soma) + assert len(msgs) == 3, msgs + +def test_current_pulse(): + """Test current pulse. + """ + rdes = rd.rdesigneur( + stimList = [['soma', '1', '.', 'inject', '(t>0.1 && t<0.2) * 2e-8' ]], + plotList = [['soma', '1', '.', 'Vm', 'Soma membrane potential']] + ) + rdes.buildModel() + moose.reinit() + moose.start(0.3) + rdes.display(block=False) + y = moose.wildcardFind('/##[TYPE=Table]')[0].vector + ym, ys = y.mean(), y.std() + X = np.histogram(y) + assert np.allclose(ym, expected[0]) + assert np.allclose(ys, expected[1]) + assert np.allclose(X[0], expected[2]) + assert np.allclose(X[1], expected[3]) + + +if __name__ == '__main__': + test_current_pulse() + test_msgs() diff --git a/tests/py_rdesigneur/test_21_vclamp.py b/tests/py_rdesigneur/test_21_vclamp.py new file mode 100644 index 00000000..5ce99637 --- /dev/null +++ b/tests/py_rdesigneur/test_21_vclamp.py @@ -0,0 +1,29 @@ +import moose +import numpy as np +import rdesigneur as rd + +def test_21_vclamp(): + """Test vclamp. + """ + rdes = rd.rdesigneur( + stimList = [['soma', '1', '.', 'vclamp', '-0.065 + (t>0.1 && t<0.2) * 0.02' ]], + plotList = [ + ['soma', '1', '.', 'Vm', 'Soma membrane potential'], + ['soma', '1', 'vclamp', 'current', 'Soma holding current'], + ] + ) + rdes.buildModel() + moose.reinit() + moose.start( 0.3 ) + # rdes.display(block=False) + data = [] + for t in moose.wildcardFind('/##[TYPE=Table]'): + data.append(t.vector) + mean = np.mean(data, axis=1) + std = np.std(data, axis=1) + assert np.allclose([-5.83422152e-02, -9.28563233e-09], mean), mean + assert np.allclose([9.41512562e-03, 2.79081939e-08], std), std + return data + +if __name__ == '__main__': + test_21_vclamp() diff --git a/tests/py_rdesigneur/test_30_squid_currentPulse.py b/tests/py_rdesigneur/test_30_squid_currentPulse.py new file mode 100644 index 00000000..901a6c7d --- /dev/null +++ b/tests/py_rdesigneur/test_30_squid_currentPulse.py @@ -0,0 +1,32 @@ +import matplotlib as mpl +mpl.use('Agg') +import numpy as np +import moose +import rdesigneur as rd + +def test_current_pulse_squid(): + """Test current pulse. + >>> test_current_pulse_squid() + Rdesigneur: Elec model has 1 compartments and 0 spines on 0 compartments. + [array([-0.065 , -0.06525877, -0.06549723, ..., -0.06676325, + -0.06676329, -0.06676332])] + """ + rdes = rd.rdesigneur( + chanProto = [['make_HH_Na()', 'Na'], ['make_HH_K()', 'K']], + chanDistrib = [ + ['Na', 'soma', 'Gbar', '1200' ], + ['K', 'soma', 'Gbar', '360' ]], + stimList = [['soma', '1', '.', 'inject', '(t>0.1 && t<0.2) * 1e-8' ]], + plotList = [['soma', '1', '.', 'Vm', 'Membrane potential']]) + rdes.buildModel() + moose.reinit() + moose.start(0.3) + rdes.display(block=False) + data = moose.wildcardFind('/##[TYPE=Table]')[0].vector + m, u = data.mean(), data.std() + np.allclose([-0.06507780556166297, 0.012544993918549656], [m, u]) + print("[INFO ] Done") + return True + +if __name__ == '__main__': + test_current_pulse_squid() diff --git a/tests/py_rdesigneur/test_32_squid_axon_propgn.py b/tests/py_rdesigneur/test_32_squid_axon_propgn.py new file mode 100644 index 00000000..a62995b1 --- /dev/null +++ b/tests/py_rdesigneur/test_32_squid_axon_propgn.py @@ -0,0 +1,74 @@ +# Rdesigneur example 4.1 +# Making an axon with a propagating action potential. +# Turned into a doctest + +import matplotlib +matplotlib.use('Agg') +import numpy as np +import moose +import rdesigneur as rd + +numAxonSegments = 200 +comptLen = 10e-6 +comptDia = 1e-6 +RM = 1.0 +RA = 10.0 +CM = 0.01 + +expected = np.array([-0.065 , -0.06983536, -0.07267512, -0.07384024, -0.07422599, + -0.07426641, -0.07057581, -0.06788169, -0.06541139, -0.06203896, + -0.04844496, 0.02185485, -0.02780464, -0.07129777, -0.07606423, + -0.07568317, -0.07514661, -0.07449245, -0.07373675, -0.07290267, + -0.07201665, -0.07110338, -0.07018217, -0.06926533, -0.06835791, + -0.06745804, -0.0665565 , -0.06563355, -0.06464782, -0.06349831, + -0.06186082, -0.05798547, 0.00504934, -0.00513958, -0.04914883, + -0.07588121, -0.07586509, -0.07538907, -0.07478491, -0.07407192, + -0.0732706 ]) + +def makeAxonProto(): + axon = moose.Neuron( '/library/axon' ) + prev = rd.buildCompt( axon, 'soma', RM = RM, RA = RA, CM = CM, dia = 10e-6, x=0, dx=comptLen) + theta = 0 + x = comptLen + y = 0.0 + + for i in range( numAxonSegments ): + dx = comptLen * np.cos( theta ) + dy = comptLen * np.sin( theta ) + r = np.sqrt( x * x + y * y ) + theta += comptLen / r + compt = rd.buildCompt( axon, 'axon' + str(i), RM = RM, RA = RA, CM = CM, x = x, y = y, dx = dx, dy = dy, dia = comptDia ) + moose.connect( prev, 'axial', compt, 'raxial' ) + prev = compt + x += dx + y += dy + + return axon + +def test_axon_propagation(): + """ Test squid axon propagation. + """ + moose.Neutral( '/library' ) + makeAxonProto() + + rdes = rd.rdesigneur( + chanProto = [['make_HH_Na()', 'Na'], ['make_HH_K()', 'K']], + cellProto = [['elec','axon']], + chanDistrib = [ + ['Na', '#', 'Gbar', '1200' ], + ['K', '#', 'Gbar', '360' ]], + stimList = [['soma', '1', '.', 'inject', '(t>0.005 && t<0.2) * 2e-11' ]], + plotList = [['soma', '1', '.', 'Vm', 'Membrane potential']], + moogList = [['#', '1', '.', 'Vm', 'Vm (mV)']] + ) + + rdes.buildModel() + moose.reinit() + moose.start(0.04) + data = moose.wildcardFind('/##[TYPE=Table]')[0].vector[::10] + assert np.allclose(data, expected), "Error is %s" % (data-expected) + print('Add done') + return data + +if __name__ == '__main__': + test_axon_propagation() diff --git a/tests/py_rdesigneur/test_41_ballAndStick.py b/tests/py_rdesigneur/test_41_ballAndStick.py new file mode 100644 index 00000000..2a0f594e --- /dev/null +++ b/tests/py_rdesigneur/test_41_ballAndStick.py @@ -0,0 +1,52 @@ +# This example demonstrates loading a ball-and-stick model of a neuron +# with 10 compartments in the dendrite, that support propagating +# action potentials. +# Copyright (C) Upinder S. Bhalla NCBS 2018 +# Released under the terms of the GNU Public License V3. +# +# Turned to a test by Dilawar Singh + +import matplotlib +matplotlib.use('Agg') +import moose +import numpy as np +import rdesigneur as rd + +expected = np.array([-0.065, -0.068, -0.07 , -0.071, -0.072, -0.072, -0.072, -0.072, + -0.072, -0.072, -0.072, -0.048, 0.03 , -0.019, -0.054, -0.07 , + -0.07 , -0.067, -0.065, -0.062, -0.06 , -0.056, -0.048, -0.005, + -0.024, -0.055, -0.069, -0.069, -0.067, -0.064, -0.062, -0.059, + -0.055, -0.046, -0.005, -0.028, -0.057, -0.069, -0.068, -0.066, + -0.064, -0.061, -0.058, -0.054, -0.044, -0.004, -0.031, -0.059, + -0.069, -0.068, -0.066, -0.075, -0.076, -0.075, -0.075, -0.075, + -0.075, -0.074, -0.074, -0.073, -0.073]) + +def test_ball_and_stick(): + """Test 41 Ball and Stick model. + """ + rdes = rd.rdesigneur( + cellProto = [['ballAndStick', 'soma', 20e-6, 20e-6, 4e-6, 500e-6, 10]], + chanProto = [['make_HH_Na()', 'Na'], ['make_HH_K()', 'K']], + chanDistrib = [ + ['Na', 'soma', 'Gbar', '1200' ], + ['K', 'soma', 'Gbar', '360' ], + ['Na', 'dend#', 'Gbar', '400' ], + ['K', 'dend#', 'Gbar', '120' ] + ], + stimList = [['soma', '1', '.', 'inject', '(t>0.01 && t<0.05) * 1e-9' ]], + plotList = [['soma', '1', '.', 'Vm', 'Membrane potential']], + moogList = [['#', '1', '.', 'Vm', 'Vm (mV)']] + ) + rdes.buildModel() + soma = moose.element( '/model/elec/soma' ) + moose.reinit() + moose.start(0.06) + t = [x.vector for x in moose.wildcardFind('/##[TYPE=Table]')] + m, u = np.mean(t), np.std(t) + assert np.allclose([m, u], [-0.05820780543933818, 0.02098328548146809]), \ + (m, u) + print('done') + return True + +if __name__ == '__main__': + test_ball_and_stick() diff --git a/tests/py_rdesigneur/test_51_periodic_syn_input.py b/tests/py_rdesigneur/test_51_periodic_syn_input.py new file mode 100644 index 00000000..2406392b --- /dev/null +++ b/tests/py_rdesigneur/test_51_periodic_syn_input.py @@ -0,0 +1,32 @@ +# This example demonstrates periodic synaptic input to a cell. +# Copyright (C) Upinder S. Bhalla NCBS 2018 +# Released under the terms of the GNU Public License V3. No warranty. +# Doctest by Dilawar Singh + +import moose +import rdesigneur as rd +import numpy as np + + +def test_periodic_syninput(): + rdes = rd.rdesigneur( + cellProto = [['somaProto', 'soma', 20e-6, 200e-6]], + chanProto = [['make_glu()', 'glu']], + chanDistrib = [['glu', 'soma', 'Gbar', '1' ]], + + # Deliver stimulus to glu synapse on soma, periodically at 50 Hz. + stimList = [['soma', '0.5', 'glu', 'periodicsyn', '50' ]], + plotList = [['soma', '1', '.', 'Vm', 'Soma membrane potential']] + ) + rdes.buildModel() + moose.reinit() + moose.start( 0.3 ) + t = moose.wildcardFind('/##[TYPE=Table]')[0].vector + expected = np.array([-0.04995514162861773, 0.004795008283676097]) + got = np.array([t.mean(), t.std()]) + assert np.allclose(expected, got, rtol=1e-3), (expected, got) + print('ok') + return t + +if __name__ == '__main__': + test_periodic_syninput() diff --git a/tests/py_rdesigneur/test_6_chem_osc.py b/tests/py_rdesigneur/test_6_chem_osc.py new file mode 100644 index 00000000..b786613c --- /dev/null +++ b/tests/py_rdesigneur/test_6_chem_osc.py @@ -0,0 +1,28 @@ +import moose +import numpy as np +import rdesigneur as rd + +def test_chem_osc(): + """Test chemical oscillation. + """ + rdes = rd.rdesigneur( + turnOffElec = True, + diffusionLength = 1e-3, # Default diffusion length is 2 microns + chemProto = [['makeChemOscillator()', 'osc']], + chemDistrib = [['osc', 'soma', 'install', '1' ]], + plotList = [['soma', '1', 'dend/a', 'conc', 'a Conc'], + ['soma', '1', 'dend/b', 'conc', 'b Conc']] + ) + rdes.buildModel() + b = moose.element( '/model/chem/dend/b' ) + b.concInit *= 5 + moose.reinit() + moose.start(200) + res = [t.vector for t in moose.wildcardFind('/##[TYPE=Table2]')] + m = np.mean(res, axis=1) + s = np.std(res, axis=1) + expected = ([0.13622532, 0.13261175], [0.08518292, 0.06766806]) + assert np.allclose(expected, [m,s]), (m,s) + +if __name__ == '__main__': + test_chem_osc() diff --git a/tests/py_rdesigneur/test_72_CICR.py b/tests/py_rdesigneur/test_72_CICR.py new file mode 100644 index 00000000..b41b4661 --- /dev/null +++ b/tests/py_rdesigneur/test_72_CICR.py @@ -0,0 +1,94 @@ +# This example demonstrates insertion of endo-compartments into the +# dendrite. Here endo_compartments are used for the endoplasmic reticulum +# (ER) in a model of Calcium Induced Calcium Release through the +# IP3 receptor. It generates a series of propagating waves of calcium. +# Note that units of permeability in the ConcChan are 1/(millimolar.sec) +# +# Copyright (C) Upinder S. Bhalla NCBS 2018 +# Released under the terms of the GNU Public License V3. +# Converted to a test by Dilawar Singh, 2020 + +import matplotlib as mpl +mpl.use('Agg') + +import os +import moose +print("[INFO ] Using moose from %s (%s)" % (moose.__file__, moose.version())) + +import numpy as np +import rdesigneur as rd + +np.set_printoptions(precision=3) + +sdir_ = os.path.dirname(os.path.realpath(__file__)) + +E = (np.array([1.09014453e-07, 7.28082797e-13, 2.75389935e-08, 4.09373273e-01, + 5.13839676e-04, 5.04392239e-04, 5.18535951e-04, 5.20332653e-04, + 5.20319412e-04, 5.20315927e-04, 5.20315785e-04, 5.20315780e-04, + 5.20315780e-04, 5.20315780e-04, 5.13839676e-04, 5.04392239e-04, + 5.18535951e-04, 5.20332653e-04, 5.20319412e-04, 5.20315927e-04, + 5.20315785e-04, 5.20315780e-04, 5.20315780e-04, 5.20315780e-04, + 4.03334121e-01, 4.04616316e-01, 4.03839819e-01, 4.03873596e-01, + 4.03877574e-01, 4.03877276e-01, 4.03877250e-01, 4.03877249e-01, + 4.03877249e-01, 4.03877249e-01, 1.08136177e-06, 1.03726538e-06, + 1.04624969e-06, 1.04989891e-06, 1.05005782e-06, 1.05006129e-06, + 1.05006147e-06, 1.05006148e-06, 1.05006148e-06, 1.05006148e-06]), + np.array([2.64763531e-06, 3.53901405e-12, 1.06297817e-07, 2.59647692e-05, + 1.50771752e-03, 1.44372345e-03, 1.46452771e-03, 1.46445738e-03, + 1.46426743e-03, 1.46425938e-03, 1.46425914e-03, 1.46425913e-03, + 1.46425913e-03, 1.46425913e-03, 1.50771752e-03, 1.44372345e-03, + 1.46452771e-03, 1.46445738e-03, 1.46426743e-03, 1.46425938e-03, + 1.46425914e-03, 1.46425913e-03, 1.46425913e-03, 1.46425913e-03, + 1.26799318e-02, 1.15981501e-02, 1.19280784e-02, 1.20059244e-02, + 1.20092971e-02, 1.20092807e-02, 1.20092772e-02, 1.20092772e-02, + 1.20092772e-02, 1.20092772e-02, 2.11602709e-06, 2.06303080e-06, + 2.08117025e-06, 2.08584557e-06, 2.08603181e-06, 2.08603541e-06, + 2.08603560e-06, 2.08603562e-06, 2.08603562e-06, 2.08603562e-06]) + ) + + +def test_CICR(): + """Test CICR + """ + rdes = rd.rdesigneur( + turnOffElec=True, + chemDt=0.005, + chemPlotDt=0.02, + numWaveFrames=200, + diffusionLength=1e-6, + useGssa=False, + addSomaChemCompt=False, + addEndoChemCompt=True, + # cellProto syntax: ['somaProto', 'name', dia, length] + cellProto=[['somaProto', 'soma', 2e-6, 10e-6]], + chemProto=[[os.path.join(sdir_, 'chem', 'CICRwithConcChan.g'), + 'chem']], + chemDistrib=[['chem', 'soma', 'install', '1']], + plotList=[ + ['soma', '1', 'dend/CaCyt', 'conc', 'Dendritic Ca'], + ['soma', '1', 'dend/CaCyt', 'conc', 'Dendritic Ca', 'wave'], + ['soma', '1', 'dend_endo/CaER', 'conc', 'ER Ca'], + ['soma', '1', 'dend/ActIP3R', 'conc', 'active IP3R'], + ], + ) + rdes.buildModel() + IP3 = moose.element('/model/chem/dend/IP3') + IP3.vec.concInit = 0.004 + IP3.vec[0].concInit = 0.02 + moose.reinit() + + moose.start(20) + data = [t.vector for t in moose.wildcardFind('/##[TYPE=Table2]')] + m, s = np.mean(data, axis=1), np.std(data, axis=1) + # print(np.array_repr(m)) + # print(np.array_repr(s)) + # In multithreaded mode, the numers are not exactly the same as in + # expected. + assert np.allclose(m, E[0], rtol=1e-2, atol=1e-4), (m - E[0]) + # standard deviation could be very low in some cases. + print(np.sum(abs(s-E[1])) ) + assert np.sum(abs(s-E[1])) < 1e-2, "Got %s" % np.sum(abs(s-E[1])) + print('done') + +if __name__ == '__main__': + test_CICR() diff --git a/tests/py_rdesigneur/test_74_travelling_osc.py b/tests/py_rdesigneur/test_74_travelling_osc.py new file mode 100644 index 00000000..68ce453e --- /dev/null +++ b/tests/py_rdesigneur/test_74_travelling_osc.py @@ -0,0 +1,75 @@ +# This example illustrates molecular transport of an oscillatory reaction +# system, along a closed-end cylinder. The concentrations along the entire +# length of the cylinder start out uniform. It shows an interesting +# combination of propagating oscillations and buildup of reagents. +# Author: Upinder Bhalla +# Converted to pydoc test by Dilawar Singh + +import matplotlib +matplotlib.use('Agg') +import moose +import numpy as np +import pylab +import rdesigneur as rd + +expected = (np.array([0.1, 0.15516149, 0.1403528 , 0.12798643, 0.14763476, + 0.13274035, 0.13840812, 0.14143158, 0.13480444, 0.14342124, + 0.13690342, 0.14346931, 0.13888074, 0.14376058, 0.14016138, + 0.14403992, 0.1415519 , 0.14333911, 0.143152 , 0.14287822, + 0.14605064, 0.14336306, 0.15619844, 0.14403064, 0.15615248, + 0.14539543, 0.1517716 , 0.14729328, 0.14838669, 0.14997354, + 0.14767709, 0.16223196, 0.14865582, 0.16134809, 0.14992121, + 0.15467856, 0.15189257, 0.15189602, 0.19084929, 0.15356592, + 0.15523634]), np.array([1.46079786e-17, 4.78646136e-02, 3.27393913e-02, 2.49512647e-02, + 3.63456677e-02, 3.83510871e-02, 3.26338079e-02, 6.95644575e-02, + 3.46265152e-02, 9.46756756e-02, 4.61280054e-02, 1.05823511e-01, + 5.86208446e-02, 1.05951587e-01, 7.15086316e-02, 9.68416361e-02, + 8.33557080e-02, 8.79500371e-02, 1.01320736e-01, 8.94334644e-02, + 1.37529592e-01, 9.51733672e-02, 2.21766095e-01, 1.01452560e-01, + 2.12351153e-01, 1.09061426e-01, 1.47326940e-01, 1.19309887e-01, + 1.19308264e-01, 1.48644433e-01, 1.21409122e-01, 2.55315182e-01, + 1.26555965e-01, 2.30541272e-01, 1.32675123e-01, 1.52134329e-01, + 1.45874039e-01, 1.37777639e-01, 6.86047595e-01, 1.43783302e-01, + 1.82237898e-01])) + + +def test_travelling_osc(): + """Test travelling wave. + """ + rdes = rd.rdesigneur( + turnOffElec = True, + diffusionLength = 2e-6, + chemProto = [['makeChemOscillator()', 'osc']], + chemDistrib = [['osc', 'soma', 'install', '1' ]], + plotList = [ + ['soma', '1', 'dend/a', 'conc', 'Concentration of a'], + ['soma', '1', 'dend/b', 'conc', 'Concentration of b'], + ['soma', '1', 'dend/a', 'conc', 'Concentration of a', 'wave'], + ], + moogList = [['soma', '1', 'dend/a', 'conc', 'a Conc', 0, 360 ]] + ) + a = moose.element( '/library/osc/kinetics/a' ) + b = moose.element( '/library/osc/kinetics/b' ) + s = moose.element( '/library/osc/kinetics/s' ) + a.diffConst = 0 + b.diffConst = 0 + a.motorConst = 1e-6 + rdes.buildModel() + moose.reinit() + # rdes.displayMoogli( 1, 400, rotation = 0, azim = -np.pi/2, elev = 0.0 ) + moose.start(400) + data = [] + for t in moose.wildcardFind('/##[TYPE=Table2]'): + data.append(t.vector[::10]) + m = np.mean(data, axis=0) + u = np.std(data, axis=0) + # The expected values are computed with GSL solver. These values will vary + # a little with BOOST solver. Give some leeway for these tests. + assert np.allclose(expected[0], m, rtol=1e-2), "Error is %s " % (expected[0]-m) + A, B = expected[1], u + assert np.allclose(B, A, rtol=1e-1), "Error is %s, base=%s" % ((A-B), B) + print('done') + + +if __name__ == '__main__': + test_travelling_osc() diff --git a/tests/alpha/ex7.6_func_controls_reac_rate.py b/tests/py_rdesigneur/test_76_func_func_control_reac_rates.py similarity index 50% rename from tests/alpha/ex7.6_func_controls_reac_rate.py rename to tests/py_rdesigneur/test_76_func_func_control_reac_rates.py index b8c8fb4c..8d369b17 100644 --- a/tests/alpha/ex7.6_func_controls_reac_rate.py +++ b/tests/py_rdesigneur/test_76_func_func_control_reac_rates.py @@ -17,12 +17,12 @@ # Released under the terms of the GNU Public License V3. ######################################################################## +import matplotlib +matplotlib.use('Agg') import numpy as np import moose -import pylab import rdesigneur as rd - def makeFuncRate(): model = moose.Neutral( '/library' ) model = moose.Neutral( '/library/chem' ) @@ -45,10 +45,9 @@ def makeFuncRate(): C.concInit = 0 reac.Kb = 1 - -makeFuncRate() - -rdes = rd.rdesigneur( +def test_reac_rates(): + makeFuncRate() + rdes = rd.rdesigneur( turnOffElec = True, #This subdivides the 50-micron cylinder into 2 micron voxels diffusionLength = 2e-6, @@ -57,11 +56,50 @@ def makeFuncRate(): chemDistrib = [['chem', 'soma', 'install', '1' ]], plotList = [['soma', '1', 'dend/A', 'conc', 'A conc', 'wave'], ['soma', '1', 'dend/C', 'conc', 'C conc', 'wave']], -) -rdes.buildModel() + ) + rdes.buildModel() + + C = moose.element( '/model/chem/dend/C' ) + C.vec.concInit = [ 1+np.sin(x/5.0) for x in range( len(C.vec) ) ] + moose.reinit() + moose.start(10) + + E = (np.array([0.76793869, 0.69093771, 0.61740932, 0.55290337, 0.50043755, + 0.46090277, 0.43395074, 0.41882627, 0.41492281, 0.42206285, + 0.4405646 , 0.47111808, 0.51443061, 0.57058404, 0.63814939, + 0.71337226, 0.79003606, 0.86055299, 0.91814872, 0.95908718, + 0.9836508 , 0.99540289, 0.99934529, 0.99998887, 0.99999589, + 1. , 1.19866933, 1.38941834, 1.56464247, 1.71735609, + 1.84147098, 1.93203909, 1.98544973, 1.9995736 , 1.97384763, + 1.90929743, 1.8084964 , 1.67546318, 1.51550137, 1.33498815, + 1.14112001, 0.94162586, 0.7444589 , 0.55747956, 0.38814211, + 0.2431975 , 0.12842423, 0.04839793, 0.006309 , 0.00383539]), + np.array([1.35368806e-01, 1.74391515e-01, 2.08263083e-01, 2.34835055e-01, + 2.53957994e-01, 2.66695461e-01, 2.74465660e-01, 2.78476408e-01, + 2.79468906e-01, 2.77640055e-01, 2.72631277e-01, 2.63551810e-01, + 2.49094224e-01, 2.27869755e-01, 1.99072915e-01, 1.63375068e-01, + 1.23566311e-01, 8.42635843e-02, 5.04491469e-02, 2.55522217e-02, + 1.02890632e-02, 2.90344842e-03, 4.13990858e-04, 7.03942852e-06, + 2.60159221e-06, 0.00000000e+00, 0.00000000e+00, 2.22044605e-16, + 0.00000000e+00, 0.00000000e+00, 2.22044605e-16, 2.22044605e-16, + 2.22044605e-16, 2.22044605e-16, 4.44089210e-16, 0.00000000e+00, + 2.22044605e-16, 2.22044605e-16, 0.00000000e+00, 2.22044605e-16, + 2.22044605e-16, 0.00000000e+00, 1.11022302e-16, 0.00000000e+00, + 0.00000000e+00, 2.77555756e-17, 0.00000000e+00, 0.00000000e+00, + 0.00000000e+00, 0.00000000e+00])) + + + + A = [] + for t in moose.wildcardFind('/##[TYPE=Table2]'): + A.append(t.vector) + m = np.mean(A, axis=1) + u = np.std(A, axis=1) + + # multithreaded version given different results. + assert np.allclose(m, E[0], rtol=1e-3), (m-E[0]) + assert np.allclose(u, E[1], rtol=1e-3), (u-E[1]) + print('all done') -C = moose.element( '/model/chem/dend/C' ) -C.vec.concInit = [ 1+np.sin(x/5.0) for x in range( len(C.vec) ) ] -moose.reinit() -moose.start(10) -rdes.display() +if __name__ == '__main__': + test_reac_rates() diff --git a/tests/py_rdesigneur/test_rdes_with_func_proto.py b/tests/py_rdesigneur/test_rdes_with_func_proto.py new file mode 100644 index 00000000..5267e2f4 --- /dev/null +++ b/tests/py_rdesigneur/test_rdes_with_func_proto.py @@ -0,0 +1,58 @@ +import matplotlib +matplotlib.use('Agg') +import os +import moose +import rdesigneur as rd +import numpy as np + +sm_diam = 20e-6 +sm_len = 20e-6 +dend_diam = 4e-6 +dend_len = 500e-6 +numDend = 10 +sm_area = np.pi*sm_len*sm_diam +elecPlotDt = 50e-6 +elecDt = 10e-6 +RM = 1 +CM = 0.01 +RA = 1.5 +Vrest = -0.065 + +sdir_ = os.path.dirname(os.path.realpath(__file__)) + +def test_proto(): + # Boilerplate + rdes = rd.rdesigneur( + elecPlotDt = elecPlotDt, + elecDt = elecDt, + cellProto = [['somaProto', 'soma', sm_diam, sm_len]], + chanProto = [[ os.path.join(sdir_, 'Na_Chan_Migliore2018_.Na_Chan()'), 'Na']], + chanDistrib = [ + ['Na', 'soma', 'Gbar', '360'] + ], + passiveDistrib = [ + ['#', 'RM', str(RM), 'CM', str(CM), 'initVm', str(Vrest), 'Em', str(Vrest)], + ], + stimList = [['soma', '1', '.', 'vclamp', '-0.065 + (t>0.1 && t<0.2) * 0.02' ]], + plotList = [ + ['soma', '1', '.', 'Vm', 'Soma membrane potential'], + ['soma', '1', 'vclamp', 'current', 'Soma holding current'], + ] + ) + rdes.buildModel() + + if moose.exists('/model/elec/soma/vclamp'): + moose.element( '/model/elec/soma/vclamp' ).gain = CM*sm_area/elecDt + moose.element( '/model/elec/soma/vclamp' ).tau = 5*elecDt + moose.element( '/model/elec/soma/vclamp' ).ti = elecDt*2 + moose.element( '/model/elec/soma/vclamp' ).td = 0 + + moose.reinit() + moose.start( 0.3 ) + rdes.display() + +def main(): + test_proto() + +if __name__ == '__main__': + main() diff --git a/tests/pytest.ini b/tests/pytest.ini new file mode 100644 index 00000000..1d0d4374 --- /dev/null +++ b/tests/pytest.ini @@ -0,0 +1,10 @@ +[pytest] +addopts = -ra -q --maxfail=2 +norecusedirs = .git _build tmp* +filterwarnings = + error + ignore::DeprecationWarning + ignore::PendingDeprecationWarning + ignore::UserWarning + ignore::Warning + ignore::FutureWarning diff --git a/tests/python/Rallpacks/README.Rallpack3 b/tests/python/Rallpacks/README.Rallpack3 deleted file mode 100644 index f3a973ce..00000000 --- a/tests/python/Rallpacks/README.Rallpack3 +++ /dev/null @@ -1,163 +0,0 @@ -Specification of Rallpack 3 : axon with squid channels - -============================================================================= - -1. Objective. -Tests the ability of a simulator to evaluate the Hodgkin-Huxley channel models. - -============================================================================= - -2. Simulation -This model consists of the cable from Rallpack1 with the addition of -squid sodium and potassium channels from Hodgkin and Huxley. - -This simulation models a uniform unbranched cable with -1000 identical compartments, with a length constant of 1, a diameter -of 1 micron, and a total length of 1 mm. -The membrane properties are : -RA = 1.0 ohms meter = 100 ohms cm -RM = 4.0 ohms meter^2 = 40000 ohms cm^2 -CM = 0.01 Farads/meter^2 = 1.0 uf/cm^2 -Eleak = ERest = -0.065 V = -65 mV - -The channel properties are as described by Hodkin and Huxley, as follows : -(We have reversed their sign convention, and take the resting potential to -be -65 mV) - -ENa = 0.050 V = 50 mV -EK = -0.077 V = -77 mV -GNa = 1200 Siemens/m^2 = 120 mmho/cm^2 -GK = 360 Siemens/m^2 = 36 mmho/cm^2 -(For each compartment : -Gbar_Na= 3.77e-9 Siemens = 3.77e-6 mmho -Gbar_K = 1.131e-9 Siemens = 1.131e-6 mmho ) - -gNa= Gbar_Na * m^3 * h -gK = Gbar_K * n^4 - -dm/dt = alpha_m*(1-m) - beta_m*m -dh/dt = alpha_h*(1-h) - beta_h*h - -dn/dt = alpha_n*(1-n) - beta_n*n - -alpha_m = A (v-V0) / (exp((v-V0)/B) - 1) -A = -0.1e6 1/(Volts*sec) = -0.1 1/(mV*msec) -B = -0.01 Volts = -10 mV -V0= -0.040 Volts = -40 mV - -beta_m = A exp((v-V0)/B) -A = 4.0e3 1/sec = 4.0 1/msec -B = -0.018 Volts = -18 mV -V0= -0.065 Volts = -65 mV - -alpha_h = A exp((v-V0)/B) -A = 70.0 1/sec = 0.07 1/msec -B = -0.020 Volts = -20 mV -V0= -0.065 Volts = -65 mV - -beta_h = A / (exp((v-V0)/B) + 1) -A = 1.0e3 1/sec = 1.0 1/msec -B = -0.010 Volts = -10 mV -V0= -0.035 Volts = -35 mV - - -alpha_n = A (v-V0) / (exp((v-V0)/B) - 1) -A = -10.0e3 1/(Volts*sec) = -0.01 1/(mV*msec) -B = -0.01 Volts = -10 mV -V0= -0.055 Volts = -55 mV - -beta_n = A exp((v-V0)/B) -A = 125.0 1/sec = 0.125 1/msec -B = -0.080 Volts = -80 mV -V0= -0.065 Volts = -65 mV - - -A current of 0.1 nA is injected in the first compartment. Membrane voltages -are recorded for the first and last compartments. -This model is run for a simulated time of 0.25 seconds. - -============================================================================= - -3. Correct solution. -There is no analytic solution available for the complete cable model. We will -use the original solutions of Hodgkin and Huxley -(J Physiol 117,pp 500-544, 1952) as the basis for the benchmark. -Since we are simulating for longer times and in -a cable, we have used as our reference waveforms generated by Genesis and -by Cable (Hines), using the parameters discussed above and an exponential -evaluation for the channel kinetics, and timesteps of 1 usec. The two -simulators give very similar results, differing by < 1% by the srms test -described below. -The reference waveforms (provided in this directory) are -ref_axon.0.neuron (waveform at injection site, generated by NEURON) -ref_axon.x.neuron (waveform at far end of axon, generated by NEURON) -ref_axon.0.genesis (waveform at injection site, generated by GENESIS) -ref_axon.x.genesis (waveform at far end of axon, generated by GENESIS) -These reference waveforms start at time 0 and have 5001 data points, -ending at time 0.25 sec. If a simulator saves the output values at the end of -every time step as opposed to the beginning, it may be necessary to shift -the output curves by one time step. - -Since spike waveforms will give very large rms differences with relatively -small differences in spike period, we adopt a different method for comparing -results. The rms differences for the following spike parameters are -calculated by the analysis program srms.c : - ISI - PTP - Spike shape (scaled). -These are all normalized and summed to give the benchmark output. - -Note : The srms program performs a very simplistic comparison which is -sensitive to a number of uncontrolled factors such as sampling interval -and jitter in the waveforms. It does, however, produce the appropriate -values when comparing identical waveforms whose time or voltage axes are -scaled with respect to each other. The 'srms' values it generates are not -easily related to intuitive ideas of waveform difference, being rather larger -than one would expect. It is valuable to visually compare the spike traces -in addition to using the srms values. - -============================================================================= - -4. Performance measures. (See ../README for definitions) -General information - Rallpack name, Simulator name and version - Peak speed and model size at which the speed is attained - Asymptotic accuracy (error %) - Semi-accurate timestep (Timestep for 2x asymptotic error) - Hardware information : model and MIPS rating. - Simulation setup time for 1000 compartment model - Integration method - Compartment equivalents : Description, value - -Detailed report : - 1 Accuracy vs. Timestep - 2 Accuracy vs. Simulation speed - A set of simulations of the same model size should be run at - a range of timesteps, and the accuracy and simulation speed - should be calculated for each case. - The timesteps should cover the 'useful' range for the model, - within which the accuracy goes from close to its asymptotic - (best) value to a few % error. Typical timesteps are - 5,10,20,50,100,200,500 and 1000 usec. The recommended model size - is 1000 compartments. The model size should be quoted. - These results can be tabulated and/or graphed. - If the raw speed is independent of timestep (i.e. the - simulation speed is directly proportional to timestep, which is - usually true) the two graphs can be merged, and the respective - x axis scales should be displayed. - The x axis may be displayed on a log scale. - - 3 Raw speed vs. Model size - 4 Model memory per compartment vs. Model size - A set of simulations with a range of model sizes should - be carried out, calculating the raw speed and model memory - for each case. All simulations should use the same timestep, - which should be quoted. The suggested timestep is 50 usec. - Recommended model sizes are 1, 10, 100, 1000 and 10000 - compartments. - These results can be tabulated and/or graphed. - If graphed, they may be displayed on the same graph with - the two y axis scales displayed. - The x axis may be displayed on a log scale. - -============================================================================= diff --git a/tests/python/Rallpacks/compartment.py b/tests/python/Rallpacks/compartment.py deleted file mode 100644 index 04d7bd31..00000000 --- a/tests/python/Rallpacks/compartment.py +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -"""Compartment.py: - - A compartment in moose. - -Last modified: Tue May 13, 2014 06:03PM - -""" - -__author__ = "Dilawar Singh" -__copyright__ = "Copyright 2013, NCBS Bangalore" -__credits__ = ["NCBS Bangalore", "Bhalla Lab"] -__license__ = "GPL" -__version__ = "1.0.0" -__maintainer__ = "Dilawar Singh" -__email__ = "dilawars@ncbs.res.in" -__status__ = "Development" - - -import unittest -import math - -import moose -import moose.utils as utils - -class MooseCompartment(): - """A simple class for making MooseCompartment in moose""" - - def __init__(self, path, length, diameter, args): - """ Initialize moose-compartment """ - self.mc_ = None - self.path = path - # Following values are taken from Upi's chapter on Rallpacks - self.RM = args.get('RM', 4.0) - self.RA = args.get('RA', 1.0) - self.CM = args.get('CM', 0.01) - self.Em = args.get('Em', -0.065) - self.diameter = diameter - self.compLength = length - self.computeParams( ) - - try: - self.mc_ = moose.Compartment(self.path) - self.mc_.length = self.compLength - self.mc_.diameter = self.diameter - self.mc_.Ra = self.Ra - self.mc_.Rm = self.Rm - self.mc_.Cm = self.Cm - self.mc_.Em = self.Em - self.mc_.initVm = self.Em - - except Exception as e: - utils.dump("ERROR" - , [ "Can't create compartment with path %s " % path - , "Failed with error %s " % e - ] - ) - raise - #utils.dump('DEBUG', [ 'Compartment: {}'.format( self ) ] ) - - - def __repr__( self ): - msg = '{}: '.format( self.mc_.path ) - msg += '\n\t|- Length: {:1.4e}, Diameter: {:1.4e}'.format( - self.mc_.length, self.mc_.diameter - ) -# msg += '\n\t|- Cross-section: {:1.4e}, SurfaceArea: {:1.4e}'.format( -# self.crossSection, self.surfaceArea -# ) - msg += '\n\t|- Ra: {:1.3e}, Rm: {:1.3e}, Cm: {:1.3e}, Em: {:1.3e}'.format( - self.mc_.Ra, self.mc_.Rm, self.mc_.Cm, self.mc_.Em - ) - return msg - - def __str__( self ): - return self.__repr__( ) - - def computeParams( self ): - '''Compute essentials paramters for compartment. ''' - - self.surfaceArea = math.pi * self.compLength * self.diameter - self.crossSection = ( math.pi * self.diameter * self.diameter ) / 4.0 - self.Ra = ( self.RA * self.compLength ) / self.crossSection - self.Rm = ( self.RM / self.surfaceArea ) - self.Cm = ( self.CM * self.surfaceArea ) - - -class TestCompartment( unittest.TestCase): - ''' Test class ''' - - def setUp( self ): - self.dut = MooseCompartment() - self.dut.createCompartment( path = '/dut1' ) - - def test_creation( self ): - m = MooseCompartment( ) - m.createCompartment( path = '/compartment1' ) - self.assertTrue( m.mc_ - , 'Always create compartments when parent is /.' - ) - - m = MooseCompartment( ) - m.createCompartment( path='/model/compartment1' ) - self.assertFalse ( m.mc_ - , 'Should not create compartment when parent does not exists.' - ) - - def test_properties( self ): - m = MooseCompartment() - m.createCompartment('/comp1') - self.assertTrue( m.mc_.Em <= 0.0 - , "Em is initialized to some positive value." - " Current value is %s " % m.mc_.Em - ) - self.assertTrue( m.mc_.Rm >= 0.0 - , "Rm should be initialized to non-zero positive float" - " Current value is: {}".format( m.mc_.Rm ) - ) - - def test_repr ( self ): - print( self.dut ) - -if __name__ == "__main__": - unittest.main() diff --git a/tests/python/Rallpacks/data/run_data.dat b/tests/python/Rallpacks/data/run_data.dat deleted file mode 100644 index 2e280491..00000000 --- a/tests/python/Rallpacks/data/run_data.dat +++ /dev/null @@ -1,14 +0,0 @@ -; Compartments SimTimeInMoose -10 1.1 -100 2.95 -200 4.85 -300 7.14 -400 9.27 -500 11.96 -600 14.29 -700 17.65 -1000 28 -2000 66 -3000 124 -4000 200 -5000 276 diff --git a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/active_cable_template.nrn b/tests/python/Rallpacks/moose_vs_neuron/rallpack3/active_cable_template.nrn deleted file mode 100644 index fc7d2374..00000000 --- a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/active_cable_template.nrn +++ /dev/null @@ -1,68 +0,0 @@ -/* This is a template file which is used by a python script to generate - * rallpack3 for various cable size. -*/ - -dia = ||diameter|| -len = ||comp_length|| -incompts = ||ncomp|| -entire_len = incompts * len -runtime = ||run_time|| - -create cable -access cable -nseg = incompts - -/* -** Initialization routines -*/ - -cable {nseg=incompts L=entire_len diam=dia insert hh} - - -proc geometry() { - L = entire_len - diam = 1 - Ra = ||RA|| -} - -proc membrane() { - insert hh - - ena = 50 - ek = -77 - el = -65 - gnabar = .12 - gkbar = .036 - gl_hh = 1 / 40000 - - cm = 1 -} - -/* -** Simulation and output of data -*/ - -proc run() { local io - geometry() - membrane() - v = ||Em|| - t=0 - - m = m_hh - h = h_hh - n = n_hh - - dt = ||dt|| - io = 0 - wopen("||data||") - fstim(1) fstim(0, 0, 0, 251, .100) - fprint("%g %g %g\n", t, v(||0||), v(||x||)) - while (t < runtime) { - fadvance() - fprint("%g %g %g\n", t, v(||0||), v(||x||)) - } - wopen() -} - -finitialize() -run() diff --git a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/cable.out b/tests/python/Rallpacks/moose_vs_neuron/rallpack3/cable.out deleted file mode 100644 index 61222308..00000000 --- a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/cable.out +++ /dev/null @@ -1,5001 +0,0 @@ -0 -65 -65 -0.05 -60.749 -65.1427 -0.1 -58.6969 -65.2832 -0.15 -57.2087 -65.4217 -0.2 -55.9965 -65.5586 -0.25 -54.9483 -65.6943 -0.3 -54.0054 -65.8287 -0.35 -53.1306 -65.9621 -0.4 -52.2972 -66.0946 -0.45 -51.4844 -66.2261 -0.5 -50.6743 -66.3565 -0.55 -49.85 -66.486 -0.6 -48.9953 -66.6143 -0.65 -48.0927 -66.7416 -0.7 -47.1226 -66.8676 -0.75 -46.0621 -66.9925 -0.8 -44.8833 -67.1161 -0.85 -43.5507 -67.2383 -0.9 -42.0184 -67.3591 -0.95 -40.2255 -67.4784 -1 -38.09 -67.5962 -1.05 -35.5008 -67.7124 -1.1 -32.3066 -67.827 -1.15 -28.3053 -67.9398 -1.2 -23.24 -68.051 -1.25 -16.8209 -68.1604 -1.3 -8.81618 -68.2681 -1.35 0.732819 -68.3738 -1.4 11.2067 -68.4777 -1.45 21.3296 -68.5797 -1.5 29.6973 -68.6797 -1.55 35.5552 -68.7778 -1.6 38.9985 -68.8739 -1.65 40.5724 -68.968 -1.7 40.8535 -69.06 -1.75 40.2745 -69.15 -1.8 39.1169 -69.238 -1.85 37.5558 -69.3237 -1.9 35.7013 -69.4073 -1.95 33.6268 -69.4887 -2 31.3846 -69.5679 -2.05 29.0146 -69.6446 -2.1 26.5492 -69.719 -2.15 24.015 -69.7907 -2.2 21.4348 -69.8598 -2.25 18.8278 -69.926 -2.3 16.21 -69.989 -2.35 13.5951 -70.0486 -2.4 10.9942 -70.1044 -2.45 8.41632 -70.1558 -2.5 5.86862 -70.2024 -2.55 3.35662 -70.2433 -2.6 0.884406 -70.2778 -2.65 -1.54512 -70.3046 -2.7 -3.93011 -70.3225 -2.75 -6.26954 -70.3299 -2.8 -8.56312 -70.3247 -2.85 -10.8112 -70.3046 -2.9 -13.0145 -70.2666 -2.95 -15.1744 -70.2072 -3 -17.2927 -70.1221 -3.05 -19.3716 -70.006 -3.1 -21.4139 -69.8527 -3.15 -23.4231 -69.6544 -3.2 -25.4034 -69.4018 -3.25 -27.3598 -69.0838 -3.3 -29.2985 -68.6867 -3.35 -31.2266 -68.1941 -3.4 -33.1525 -67.5859 -3.45 -35.0856 -66.838 -3.5 -37.0365 -65.921 -3.55 -39.0162 -64.799 -3.6 -41.0361 -63.4285 -3.65 -43.1065 -61.7555 -3.7 -45.2355 -59.7134 -3.75 -47.4269 -57.2183 -3.8 -49.6773 -54.1625 -3.85 -51.973 -50.4031 -3.9 -54.2868 -45.7442 -3.95 -56.5767 -39.9054 -4 -58.7869 -32.478 -4.05 -60.8546 -22.8947 -4.1 -62.7198 -10.5629 -4.15 -64.3381 4.43985 -4.2 -65.6887 20.0357 -4.25 -66.7762 32.4664 -4.3 -67.6252 39.7254 -4.35 -68.271 42.8352 -4.4 -68.7521 43.6372 -4.45 -69.1037 43.331 -4.5 -69.3557 42.4672 -4.55 -69.532 41.2649 -4.6 -69.6508 39.8123 -4.65 -69.7261 38.1517 -4.7 -69.768 36.3106 -4.75 -69.7842 34.3122 -4.8 -69.7806 32.1783 -4.85 -69.7613 29.9297 -4.9 -69.7296 27.5867 -4.95 -69.6881 25.1683 -5 -69.6385 22.692 -5.05 -69.5824 20.1739 -5.1 -69.521 17.6281 -5.15 -69.455 15.067 -5.2 -69.3853 12.5012 -5.25 -69.3124 9.93971 -5.3 -69.2367 7.38987 -5.35 -69.1587 4.85755 -5.4 -69.0787 2.34732 -5.45 -68.9968 -0.13745 -5.5 -68.9133 -2.59445 -5.55 -68.8285 -5.02232 -5.6 -68.7423 -7.42048 -5.65 -68.6549 -9.78925 -5.7 -68.5665 -12.1295 -5.75 -68.4772 -14.443 -5.8 -68.3869 -16.7323 -5.85 -68.2957 -19.0006 -5.9 -68.2038 -21.2526 -5.95 -68.1111 -23.4944 -6 -68.0177 -25.7336 -6.05 -67.9237 -27.9804 -6.1 -67.829 -30.2475 -6.15 -67.7337 -32.5518 -6.2 -67.6379 -34.9135 -6.25 -67.5414 -37.3574 -6.3 -67.4445 -39.9132 -6.35 -67.347 -42.6137 -6.4 -67.2491 -45.4928 -6.45 -67.1506 -48.5792 -6.5 -67.0517 -51.886 -6.55 -66.9524 -55.3943 -6.6 -66.8526 -59.032 -6.65 -66.7525 -62.6591 -6.7 -66.6519 -66.0741 -6.75 -66.5509 -69.0633 -6.8 -66.4496 -71.4755 -6.85 -66.3479 -73.2759 -6.9 -66.2458 -74.5358 -6.95 -66.1434 -75.3782 -7 -66.0407 -75.9264 -7.05 -65.9377 -76.2787 -7.1 -65.8344 -76.5044 -7.15 -65.7308 -76.6495 -7.2 -65.6269 -76.7434 -7.25 -65.5227 -76.8044 -7.3 -65.4183 -76.8444 -7.35 -65.3137 -76.8706 -7.4 -65.2088 -76.8878 -7.45 -65.1037 -76.899 -7.5 -64.9984 -76.9062 -7.55 -64.8929 -76.9107 -7.6 -64.7872 -76.9132 -7.65 -64.6813 -76.9144 -7.7 -64.5753 -76.9147 -7.75 -64.4691 -76.9143 -7.8 -64.3628 -76.9134 -7.85 -64.2563 -76.9122 -7.9 -64.1497 -76.9107 -7.95 -64.043 -76.909 -8 -63.9362 -76.9071 -8.05 -63.8293 -76.905 -8.1 -63.7224 -76.9029 -8.15 -63.6153 -76.9006 -8.2 -63.5082 -76.8983 -8.25 -63.401 -76.8959 -8.3 -63.2938 -76.8934 -8.35 -63.1866 -76.8908 -8.4 -63.0793 -76.8881 -8.45 -62.972 -76.8854 -8.5 -62.8647 -76.8826 -8.55 -62.7574 -76.8798 -8.6 -62.6501 -76.8769 -8.65 -62.5428 -76.8739 -8.7 -62.4355 -76.8709 -8.75 -62.3283 -76.8678 -8.8 -62.2211 -76.8646 -8.85 -62.114 -76.8614 -8.9 -62.0069 -76.8581 -8.95 -61.8999 -76.8547 -9 -61.7929 -76.8513 -9.05 -61.686 -76.8477 -9.1 -61.5792 -76.8442 -9.15 -61.4724 -76.8405 -9.2 -61.3658 -76.8368 -9.25 -61.2592 -76.833 -9.3 -61.1528 -76.8291 -9.35 -61.0464 -76.8251 -9.4 -60.9402 -76.8211 -9.45 -60.834 -76.817 -9.5 -60.728 -76.8128 -9.55 -60.6221 -76.8085 -9.6 -60.5163 -76.8041 -9.65 -60.4107 -76.7997 -9.7 -60.3051 -76.7951 -9.75 -60.1997 -76.7905 -9.8 -60.0945 -76.7858 -9.85 -59.9893 -76.781 -9.9 -59.8843 -76.7761 -9.95 -59.7794 -76.7711 -10 -59.6747 -76.766 -10.05 -59.57 -76.7609 -10.1 -59.4656 -76.7556 -10.15 -59.3612 -76.7502 -10.2 -59.257 -76.7447 -10.25 -59.1529 -76.7392 -10.3 -59.0489 -76.7335 -10.35 -58.9451 -76.7277 -10.4 -58.8413 -76.7218 -10.45 -58.7377 -76.7158 -10.5 -58.6342 -76.7097 -10.55 -58.5308 -76.7034 -10.6 -58.4275 -76.6971 -10.65 -58.3244 -76.6906 -10.7 -58.2213 -76.684 -10.75 -58.1183 -76.6773 -10.8 -58.0153 -76.6705 -10.85 -57.9125 -76.6636 -10.9 -57.8097 -76.6565 -10.95 -57.707 -76.6493 -11 -57.6043 -76.642 -11.05 -57.5017 -76.6345 -11.1 -57.3991 -76.6269 -11.15 -57.2966 -76.6192 -11.2 -57.194 -76.6113 -11.25 -57.0915 -76.6033 -11.3 -56.9889 -76.5952 -11.35 -56.8864 -76.5869 -11.4 -56.7838 -76.5785 -11.45 -56.6811 -76.5699 -11.5 -56.5784 -76.5611 -11.55 -56.4756 -76.5523 -11.6 -56.3727 -76.5432 -11.65 -56.2697 -76.534 -11.7 -56.1666 -76.5247 -11.75 -56.0634 -76.5152 -11.8 -55.9599 -76.5055 -11.85 -55.8563 -76.4957 -11.9 -55.7525 -76.4857 -11.95 -55.6485 -76.4756 -12 -55.5442 -76.4652 -12.05 -55.4397 -76.4547 -12.1 -55.3348 -76.4441 -12.15 -55.2296 -76.4332 -12.2 -55.1241 -76.4222 -12.25 -55.0182 -76.411 -12.3 -54.9118 -76.3997 -12.35 -54.805 -76.3881 -12.4 -54.6978 -76.3764 -12.45 -54.59 -76.3645 -12.5 -54.4817 -76.3524 -12.55 -54.3727 -76.3401 -12.6 -54.2631 -76.3276 -12.65 -54.1528 -76.315 -12.7 -54.0418 -76.3021 -12.75 -53.93 -76.2891 -12.8 -53.8173 -76.2758 -12.85 -53.7037 -76.2624 -12.9 -53.5892 -76.2487 -12.95 -53.4737 -76.2349 -13 -53.357 -76.2209 -13.05 -53.2391 -76.2066 -13.1 -53.12 -76.1922 -13.15 -52.9995 -76.1776 -13.2 -52.8776 -76.1627 -13.25 -52.7542 -76.1477 -13.3 -52.6291 -76.1324 -13.35 -52.5023 -76.117 -13.4 -52.3735 -76.1013 -13.45 -52.2428 -76.0854 -13.5 -52.1098 -76.0693 -13.55 -51.9746 -76.053 -13.6 -51.8368 -76.0365 -13.65 -51.6964 -76.0198 -13.7 -51.5531 -76.0028 -13.75 -51.4067 -75.9857 -13.8 -51.2569 -75.9683 -13.85 -51.1035 -75.9507 -13.9 -50.9462 -75.9329 -13.95 -50.7846 -75.9149 -14 -50.6185 -75.8966 -14.05 -50.4475 -75.8782 -14.1 -50.271 -75.8595 -14.15 -50.0886 -75.8406 -14.2 -49.8998 -75.8215 -14.25 -49.704 -75.8022 -14.3 -49.5005 -75.7826 -14.35 -49.2886 -75.7628 -14.4 -49.0673 -75.7428 -14.45 -48.8359 -75.7226 -14.5 -48.5931 -75.7022 -14.55 -48.3377 -75.6815 -14.6 -48.0683 -75.6606 -14.65 -47.7834 -75.6395 -14.7 -47.481 -75.6181 -14.75 -47.159 -75.5966 -14.8 -46.8149 -75.5748 -14.85 -46.4458 -75.5528 -14.9 -46.0482 -75.5306 -14.95 -45.6181 -75.5081 -15 -45.1509 -75.4854 -15.05 -44.6407 -75.4625 -15.1 -44.0809 -75.4394 -15.15 -43.4631 -75.416 -15.2 -42.7777 -75.3924 -15.25 -42.0125 -75.3686 -15.3 -41.1528 -75.3445 -15.35 -40.1804 -75.3202 -15.4 -39.0732 -75.2957 -15.45 -37.8035 -75.271 -15.5 -36.3372 -75.246 -15.55 -34.6324 -75.2207 -15.6 -32.6379 -75.1952 -15.65 -30.2928 -75.1695 -15.7 -27.5268 -75.1435 -15.75 -24.2643 -75.1173 -15.8 -20.4337 -75.0909 -15.85 -15.9865 -75.0641 -15.9 -10.9282 -75.0371 -15.95 -5.35894 -75.0098 -16 0.491254 -74.9823 -16.05 6.26204 -74.9544 -16.1 11.5239 -74.9263 -16.15 15.8883 -74.8978 -16.2 19.1085 -74.869 -16.25 21.1178 -74.8399 -16.3 21.9977 -74.8104 -16.35 21.9152 -74.7806 -16.4 21.0645 -74.7503 -16.45 19.6293 -74.7195 -16.5 17.7668 -74.6882 -16.55 15.6028 -74.6564 -16.6 13.2352 -74.6239 -16.65 10.7381 -74.5908 -16.7 8.16701 -74.5567 -16.75 5.56316 -74.5217 -16.8 2.95678 -74.4855 -16.85 0.369848 -74.4479 -16.9 -2.18188 -74.4086 -16.95 -4.68743 -74.3673 -17 -7.13935 -74.3235 -17.05 -9.53294 -74.2768 -17.1 -11.8655 -74.2263 -17.15 -14.1359 -74.1713 -17.2 -16.3442 -74.1108 -17.25 -18.4915 -74.0435 -17.3 -20.5795 -73.9679 -17.35 -22.6108 -73.8822 -17.4 -24.5886 -73.784 -17.45 -26.5167 -73.6708 -17.5 -28.3996 -73.539 -17.55 -30.2425 -73.3847 -17.6 -32.0511 -73.2029 -17.65 -33.8319 -72.9877 -17.7 -35.5917 -72.7319 -17.75 -37.3379 -72.4267 -17.8 -39.0778 -72.0616 -17.85 -40.8188 -71.6238 -17.9 -42.5674 -71.0979 -17.95 -44.3293 -70.4652 -18 -46.1079 -69.7029 -18.05 -47.9042 -68.7837 -18.1 -49.7153 -67.6743 -18.15 -51.5334 -66.3339 -18.2 -53.3453 -64.7131 -18.25 -55.1323 -62.7506 -18.3 -56.8703 -60.3704 -18.35 -58.5323 -57.4761 -18.4 -60.0907 -53.9424 -18.45 -61.5211 -49.6005 -18.5 -62.8054 -44.2118 -18.55 -63.9342 -37.424 -18.6 -64.9068 -28.7102 -18.65 -65.7306 -17.36 -18.7 -66.4182 -2.83719 -18.75 -66.9853 13.8954 -18.8 -67.4483 29.1116 -18.85 -67.8231 39.0497 -18.9 -68.1237 43.6873 -18.95 -68.3626 45.1808 -19 -68.5501 45.2312 -19.05 -68.6949 44.6364 -19.1 -68.8041 43.694 -19.15 -68.8836 42.507 -19.2 -68.938 41.1147 -19.25 -68.9715 39.5382 -19.3 -68.9872 37.794 -19.35 -68.9878 35.8989 -19.4 -68.9756 33.87 -19.45 -68.9525 31.7248 -19.5 -68.92 29.4811 -19.55 -68.8794 27.1559 -19.6 -68.8319 24.7655 -19.65 -68.7783 22.3251 -19.7 -68.7195 19.8484 -19.75 -68.6562 17.3478 -19.8 -68.5889 14.8341 -19.85 -68.5181 12.3168 -19.9 -68.4443 9.80361 -19.95 -68.3678 7.30119 -20 -68.2888 4.81479 -20.05 -68.2078 2.34852 -20.1 -68.1249 -0.0945294 -20.15 -68.0402 -2.51224 -20.2 -67.9541 -4.90335 -20.25 -67.8665 -7.26728 -20.3 -67.7778 -9.60431 -20.35 -67.6879 -11.9153 -20.4 -67.5969 -14.2016 -20.45 -67.505 -16.4658 -20.5 -67.4122 -18.7109 -20.55 -67.3187 -20.9412 -20.6 -67.2243 -23.1621 -20.65 -67.1293 -25.3813 -20.7 -67.0337 -27.6081 -20.75 -66.9374 -29.8548 -20.8 -66.8405 -32.1369 -20.85 -66.7432 -34.4741 -20.9 -66.6453 -36.8906 -20.95 -66.5469 -39.4148 -21 -66.4481 -42.0795 -21.05 -66.3489 -44.9192 -21.1 -66.2493 -47.9649 -21.15 -66.1493 -51.2348 -21.2 -66.0489 -54.7181 -21.25 -65.9482 -58.3547 -21.3 -65.8471 -62.0161 -21.35 -65.7457 -65.5071 -21.4 -65.6441 -68.6055 -21.45 -65.5421 -71.1395 -21.5 -65.4399 -73.0506 -21.55 -65.3375 -74.3961 -21.6 -65.2348 -75.297 -21.65 -65.1319 -75.882 -21.7 -65.0287 -76.256 -21.75 -64.9254 -76.4941 -21.8 -64.8219 -76.6459 -21.85 -64.7182 -76.7433 -21.9 -64.6143 -76.8062 -21.95 -64.5103 -76.8469 -22 -64.4061 -76.8735 -22.05 -64.3018 -76.8908 -22.1 -64.1974 -76.902 -22.15 -64.0929 -76.9091 -22.2 -63.9882 -76.9134 -22.25 -63.8835 -76.9158 -22.3 -63.7787 -76.917 -22.35 -63.6738 -76.9172 -22.4 -63.5689 -76.9168 -22.45 -63.4639 -76.9159 -22.5 -63.3588 -76.9147 -22.55 -63.2537 -76.9131 -22.6 -63.1486 -76.9114 -22.65 -63.0435 -76.9096 -22.7 -62.9384 -76.9076 -22.75 -62.8332 -76.9054 -22.8 -62.7281 -76.9032 -22.85 -62.623 -76.9009 -22.9 -62.5179 -76.8985 -22.95 -62.4128 -76.8961 -23 -62.3078 -76.8936 -23.05 -62.2028 -76.891 -23.1 -62.0979 -76.8883 -23.15 -61.993 -76.8856 -23.2 -61.8882 -76.8828 -23.25 -61.7834 -76.8799 -23.3 -61.6787 -76.877 -23.35 -61.5741 -76.8741 -23.4 -61.4696 -76.871 -23.45 -61.3652 -76.8679 -23.5 -61.2609 -76.8647 -23.55 -61.1567 -76.8615 -23.6 -61.0525 -76.8582 -23.65 -60.9485 -76.8548 -23.7 -60.8446 -76.8514 -23.75 -60.7409 -76.8479 -23.8 -60.6372 -76.8443 -23.85 -60.5337 -76.8406 -23.9 -60.4302 -76.8369 -23.95 -60.327 -76.8331 -24 -60.2238 -76.8292 -24.05 -60.1208 -76.8252 -24.1 -60.0179 -76.8212 -24.15 -59.9151 -76.817 -24.2 -59.8125 -76.8128 -24.25 -59.71 -76.8086 -24.3 -59.6077 -76.8042 -24.35 -59.5054 -76.7997 -24.4 -59.4034 -76.7952 -24.45 -59.3014 -76.7905 -24.5 -59.1996 -76.7858 -24.55 -59.0979 -76.781 -24.6 -58.9963 -76.7761 -24.65 -58.8949 -76.7711 -24.7 -58.7936 -76.766 -24.75 -58.6924 -76.7608 -24.8 -58.5914 -76.7555 -24.85 -58.4904 -76.7501 -24.9 -58.3896 -76.7446 -24.95 -58.2889 -76.739 -25 -58.1883 -76.7333 -25.05 -58.0877 -76.7275 -25.1 -57.9873 -76.7215 -25.15 -57.887 -76.7155 -25.2 -57.7867 -76.7093 -25.25 -57.6865 -76.7031 -25.3 -57.5864 -76.6967 -25.35 -57.4863 -76.6902 -25.4 -57.3863 -76.6835 -25.45 -57.2864 -76.6768 -25.5 -57.1864 -76.6699 -25.55 -57.0865 -76.6629 -25.6 -56.9866 -76.6558 -25.65 -56.8867 -76.6485 -25.7 -56.7868 -76.6411 -25.75 -56.6869 -76.6336 -25.8 -56.5869 -76.6259 -25.85 -56.4869 -76.6181 -25.9 -56.3868 -76.6102 -25.95 -56.2867 -76.6021 -26 -56.1865 -76.5939 -26.05 -56.0861 -76.5855 -26.1 -55.9857 -76.577 -26.15 -55.8851 -76.5683 -26.2 -55.7843 -76.5595 -26.25 -55.6834 -76.5505 -26.3 -55.5823 -76.5414 -26.35 -55.481 -76.5321 -26.4 -55.3795 -76.5226 -26.45 -55.2776 -76.513 -26.5 -55.1755 -76.5032 -26.55 -55.0731 -76.4933 -26.6 -54.9704 -76.4832 -26.65 -54.8673 -76.4729 -26.7 -54.7638 -76.4624 -26.75 -54.6599 -76.4518 -26.8 -54.5555 -76.441 -26.85 -54.4507 -76.43 -26.9 -54.3453 -76.4188 -26.95 -54.2393 -76.4075 -27 -54.1328 -76.396 -27.05 -54.0256 -76.3843 -27.1 -53.9177 -76.3724 -27.15 -53.8091 -76.3603 -27.2 -53.6997 -76.348 -27.25 -53.5895 -76.3356 -27.3 -53.4784 -76.3229 -27.35 -53.3663 -76.31 -27.4 -53.2531 -76.297 -27.45 -53.1389 -76.2838 -27.5 -53.0236 -76.2703 -27.55 -52.9069 -76.2567 -27.6 -52.789 -76.2428 -27.65 -52.6696 -76.2288 -27.7 -52.5488 -76.2146 -27.75 -52.4263 -76.2001 -27.8 -52.302 -76.1854 -27.85 -52.1759 -76.1706 -27.9 -52.0479 -76.1555 -27.95 -51.9177 -76.1402 -28 -51.7852 -76.1247 -28.05 -51.6503 -76.109 -28.1 -51.5128 -76.0931 -28.15 -51.3725 -76.077 -28.2 -51.2291 -76.0606 -28.25 -51.0824 -76.0441 -28.3 -50.9323 -76.0273 -28.35 -50.7783 -76.0103 -28.4 -50.6203 -75.9931 -28.45 -50.4578 -75.9757 -28.5 -50.2904 -75.958 -28.55 -50.1178 -75.9401 -28.6 -49.9396 -75.9221 -28.65 -49.7551 -75.9037 -28.7 -49.5638 -75.8852 -28.75 -49.3651 -75.8665 -28.8 -49.1583 -75.8475 -28.85 -48.9425 -75.8283 -28.9 -48.7169 -75.8088 -28.95 -48.4804 -75.7892 -29 -48.2319 -75.7693 -29.05 -47.9699 -75.7492 -29.1 -47.6931 -75.7289 -29.15 -47.3996 -75.7083 -29.2 -47.0874 -75.6876 -29.25 -46.7543 -75.6665 -29.3 -46.3974 -75.6453 -29.35 -46.0135 -75.6238 -29.4 -45.5991 -75.6022 -29.45 -45.1496 -75.5802 -29.5 -44.6598 -75.5581 -29.55 -44.1236 -75.5357 -29.6 -43.5334 -75.5131 -29.65 -42.8803 -75.4902 -29.7 -42.1533 -75.4671 -29.75 -41.3392 -75.4438 -29.8 -40.4217 -75.4203 -29.85 -39.3808 -75.3965 -29.9 -38.1921 -75.3724 -29.95 -36.8251 -75.3482 -30 -35.2426 -75.3237 -30.05 -33.3994 -75.2989 -30.1 -31.2411 -75.2739 -30.15 -28.704 -75.2486 -30.2 -25.7182 -75.2231 -30.25 -22.2129 -75.1974 -30.3 -18.1309 -75.1713 -30.35 -13.4519 -75.145 -30.4 -8.2267 -75.1184 -30.45 -2.61501 -75.0916 -30.5 3.09605 -75.0644 -30.55 8.51949 -75.037 -30.6 13.252 -75.0093 -30.65 16.9794 -74.9812 -30.7 19.5457 -74.9528 -30.75 20.9566 -74.924 -30.8 21.3332 -74.8948 -30.85 20.852 -74.8653 -30.9 19.6986 -74.8353 -30.95 18.0414 -74.8048 -31 16.0206 -74.7738 -31.05 13.7481 -74.7422 -31.1 11.3097 -74.7099 -31.15 8.77072 -74.6768 -31.2 6.17973 -74.6428 -31.25 3.57268 -74.6077 -31.3 0.975803 -74.5714 -31.35 -1.59202 -74.5335 -31.4 -4.11744 -74.4938 -31.45 -6.59136 -74.4519 -31.5 -9.00778 -74.4073 -31.55 -11.3632 -74.3594 -31.6 -13.6558 -74.3075 -31.65 -15.8852 -74.2508 -31.7 -18.0521 -74.188 -31.75 -20.1582 -74.1179 -31.8 -22.2057 -74.0388 -31.85 -24.1977 -73.9488 -31.9 -26.1379 -73.8454 -31.95 -28.0306 -73.7257 -32 -29.8809 -73.5862 -32.05 -31.6943 -73.4225 -32.1 -33.4773 -73.2294 -32.15 -35.2364 -73.0006 -32.2 -36.979 -72.7285 -32.25 -38.7125 -72.4038 -32.3 -40.444 -72.0154 -32.35 -42.1804 -71.5498 -32.4 -43.9274 -70.9908 -32.45 -45.6891 -70.3186 -32.5 -47.4672 -69.5094 -32.55 -49.2597 -68.5343 -32.6 -51.0605 -67.3583 -32.65 -52.8582 -65.9388 -32.7 -54.6359 -64.2236 -32.75 -56.3717 -62.1482 -32.8 -58.0398 -59.6323 -32.85 -59.6133 -56.5733 -32.9 -61.0675 -52.8368 -32.95 -62.3829 -48.2397 -33 -63.5478 -42.5196 -33.05 -64.5591 -35.2856 -33.1 -65.4218 -25.9594 -33.15 -66.1467 -13.8175 -33.2 -66.7482 1.45037 -33.25 -67.2422 18.1877 -33.3 -67.6443 32.2199 -33.35 -67.9688 40.6059 -33.4 -68.2284 44.2053 -33.45 -68.4338 45.2018 -33.5 -68.594 45.0332 -33.55 -68.7165 44.3256 -33.6 -68.8074 43.3062 -33.65 -68.8718 42.0547 -33.7 -68.9139 40.6038 -33.75 -68.937 38.973 -33.8 -68.9441 37.1792 -33.85 -68.9375 35.2394 -33.9 -68.9193 33.1711 -33.95 -68.891 30.9919 -34 -68.8541 28.7197 -34.05 -68.8098 26.3711 -34.1 -68.7591 23.9624 -34.15 -68.7028 21.5082 -34.2 -68.6417 19.0219 -34.25 -68.5763 16.5154 -34.3 -68.5072 13.999 -34.35 -68.4348 11.4817 -34.4 -68.3596 8.97084 -34.45 -68.2818 6.47265 -34.5 -68.2018 3.99196 -34.55 -68.1197 1.53258 -34.6 -68.0359 -0.902795 -34.65 -67.9504 -3.31226 -34.7 -67.8635 -5.69488 -34.75 -67.7753 -8.05031 -34.8 -67.6859 -10.379 -34.85 -67.5954 -12.682 -34.9 -67.5039 -14.9612 -34.95 -67.4115 -17.2189 -35 -67.3183 -19.459 -35.05 -67.2243 -21.6861 -35.1 -67.1295 -23.9061 -35.15 -67.0341 -26.127 -35.2 -66.9381 -28.3595 -35.25 -66.8415 -30.6168 -35.3 -66.7443 -32.9158 -35.35 -66.6466 -35.2774 -35.4 -66.5484 -37.7275 -35.45 -66.4498 -40.2963 -35.5 -66.3507 -43.0172 -35.55 -66.2512 -45.9245 -35.6 -66.1514 -49.0461 -35.65 -66.0511 -52.3924 -35.7 -65.9506 -55.9383 -35.75 -65.8496 -59.6022 -35.8 -65.7484 -63.2309 -35.85 -65.6469 -66.613 -35.9 -65.5451 -69.5345 -35.95 -65.443 -71.8572 -36 -65.3406 -73.5654 -36.05 -65.238 -74.745 -36.1 -65.1352 -75.525 -36.15 -65.0322 -76.0281 -36.2 -64.929 -76.349 -36.25 -64.8256 -76.5533 -36.3 -64.722 -76.6838 -36.35 -64.6182 -76.7677 -36.4 -64.5143 -76.8219 -36.45 -64.4102 -76.8572 -36.5 -64.306 -76.8802 -36.55 -64.2017 -76.8951 -36.6 -64.0973 -76.9047 -36.65 -63.9927 -76.9107 -36.7 -63.8881 -76.9143 -36.75 -63.7834 -76.9163 -36.8 -63.6786 -76.9171 -36.85 -63.5738 -76.9171 -36.9 -63.4689 -76.9165 -36.95 -63.3639 -76.9155 -37 -63.259 -76.9141 -37.05 -63.1539 -76.9125 -37.1 -63.0489 -76.9108 -37.15 -62.9439 -76.9089 -37.2 -62.8388 -76.9068 -37.25 -62.7338 -76.9046 -37.3 -62.6288 -76.9024 -37.35 -62.5238 -76.9001 -37.4 -62.4188 -76.8977 -37.45 -62.3139 -76.8952 -37.5 -62.209 -76.8926 -37.55 -62.1042 -76.89 -37.6 -61.9994 -76.8873 -37.65 -61.8947 -76.8846 -37.7 -61.79 -76.8818 -37.75 -61.6854 -76.8789 -37.8 -61.5809 -76.876 -37.85 -61.4765 -76.873 -37.9 -61.3722 -76.8699 -37.95 -61.268 -76.8668 -38 -61.1638 -76.8636 -38.05 -61.0598 -76.8603 -38.1 -60.9559 -76.857 -38.15 -60.8521 -76.8536 -38.2 -60.7484 -76.8501 -38.25 -60.6449 -76.8466 -38.3 -60.5414 -76.8429 -38.35 -60.4381 -76.8393 -38.4 -60.3349 -76.8355 -38.45 -60.2319 -76.8317 -38.5 -60.1289 -76.8277 -38.55 -60.0261 -76.8237 -38.6 -59.9235 -76.8197 -38.65 -59.821 -76.8155 -38.7 -59.7186 -76.8113 -38.75 -59.6163 -76.807 -38.8 -59.5142 -76.8026 -38.85 -59.4122 -76.7981 -38.9 -59.3104 -76.7935 -38.95 -59.2087 -76.7888 -39 -59.1071 -76.7841 -39.05 -59.0056 -76.7792 -39.1 -58.9043 -76.7743 -39.15 -58.8031 -76.7692 -39.2 -58.7021 -76.7641 -39.25 -58.6011 -76.7588 -39.3 -58.5003 -76.7535 -39.35 -58.3996 -76.7481 -39.4 -58.299 -76.7425 -39.45 -58.1985 -76.7369 -39.5 -58.0981 -76.7311 -39.55 -57.9977 -76.7252 -39.6 -57.8975 -76.7193 -39.65 -57.7974 -76.7132 -39.7 -57.6973 -76.707 -39.75 -57.5973 -76.7006 -39.8 -57.4974 -76.6942 -39.85 -57.3975 -76.6876 -39.9 -57.2977 -76.681 -39.95 -57.1979 -76.6742 -40 -57.0981 -76.6672 -40.05 -56.9983 -76.6602 -40.1 -56.8986 -76.653 -40.15 -56.7988 -76.6457 -40.2 -56.6991 -76.6382 -40.25 -56.5993 -76.6306 -40.3 -56.4994 -76.6229 -40.35 -56.3995 -76.615 -40.4 -56.2995 -76.607 -40.45 -56.1995 -76.5989 -40.5 -56.0993 -76.5906 -40.55 -55.9991 -76.5822 -40.6 -55.8987 -76.5736 -40.65 -55.7981 -76.5648 -40.7 -55.6974 -76.5559 -40.75 -55.5965 -76.5469 -40.8 -55.4954 -76.5377 -40.85 -55.3941 -76.5283 -40.9 -55.2925 -76.5188 -40.95 -55.1906 -76.5091 -41 -55.0884 -76.4992 -41.05 -54.9859 -76.4892 -41.1 -54.8831 -76.479 -41.15 -54.7799 -76.4686 -41.2 -54.6763 -76.4581 -41.25 -54.5722 -76.4474 -41.3 -54.4676 -76.4365 -41.35 -54.3626 -76.4254 -41.4 -54.257 -76.4142 -41.45 -54.1507 -76.4028 -41.5 -54.0439 -76.3911 -41.55 -53.9364 -76.3793 -41.6 -53.8282 -76.3674 -41.65 -53.7192 -76.3552 -41.7 -53.6094 -76.3428 -41.75 -53.4987 -76.3303 -41.8 -53.387 -76.3175 -41.85 -53.2744 -76.3046 -41.9 -53.1607 -76.2914 -41.95 -53.0458 -76.2781 -42 -52.9298 -76.2646 -42.05 -52.8124 -76.2508 -42.1 -52.6936 -76.2369 -42.15 -52.5734 -76.2227 -42.2 -52.4516 -76.2084 -42.25 -52.3281 -76.1938 -42.3 -52.2028 -76.1791 -42.35 -52.0755 -76.1641 -42.4 -51.9462 -76.1489 -42.45 -51.8146 -76.1335 -42.5 -51.6807 -76.1179 -42.55 -51.5442 -76.1021 -42.6 -51.405 -76.0861 -42.65 -51.2628 -76.0699 -42.7 -51.1174 -76.0534 -42.75 -50.9686 -76.0368 -42.8 -50.8161 -76.0199 -42.85 -50.6596 -76.0028 -42.9 -50.4988 -75.9854 -42.95 -50.3332 -75.9679 -43 -50.1626 -75.9501 -43.05 -49.9865 -75.9322 -43.1 -49.8043 -75.914 -43.15 -49.6155 -75.8955 -43.2 -49.4196 -75.8769 -43.25 -49.2157 -75.858 -43.3 -49.0033 -75.8389 -43.35 -48.7812 -75.8196 -43.4 -48.5487 -75.8001 -43.45 -48.3046 -75.7803 -43.5 -48.0475 -75.7603 -43.55 -47.7761 -75.7401 -43.6 -47.4887 -75.7196 -43.65 -47.1833 -75.6989 -43.7 -46.8578 -75.678 -43.75 -46.5095 -75.6569 -43.8 -46.1355 -75.6356 -43.85 -45.7322 -75.614 -43.9 -45.2955 -75.5922 -43.95 -44.8204 -75.5701 -44 -44.3011 -75.5478 -44.05 -43.7307 -75.5253 -44.1 -43.1006 -75.5026 -44.15 -42.4008 -75.4796 -44.2 -41.6187 -75.4564 -44.25 -40.7394 -75.433 -44.3 -39.7442 -75.4093 -44.35 -38.6103 -75.3853 -44.4 -37.3096 -75.3612 -44.45 -35.8074 -75.3368 -44.5 -34.0616 -75.3121 -44.55 -32.021 -75.2872 -44.6 -29.6254 -75.2621 -44.65 -26.8068 -75.2367 -44.7 -23.4938 -75.211 -44.75 -19.6228 -75.1851 -44.8 -15.1574 -75.1589 -44.85 -10.1194 -75.1325 -44.9 -4.62649 -75.1057 -44.95 1.07942 -75.0787 -45 6.64071 -75.0514 -45.05 11.6492 -75.0238 -45.1 15.7496 -74.9958 -45.15 18.7269 -74.9676 -45.2 20.533 -74.939 -45.25 21.2545 -74.91 -45.3 21.0539 -74.8806 -45.35 20.1171 -74.8507 -45.4 18.6202 -74.8205 -45.45 16.7137 -74.7897 -45.5 14.519 -74.7583 -45.55 12.1307 -74.7262 -45.6 9.62096 -74.6935 -45.65 7.04371 -74.6598 -45.7 4.43903 -74.6252 -45.75 1.83629 -74.5893 -45.8 -0.743243 -74.552 -45.85 -3.28445 -74.513 -45.9 -5.77686 -74.472 -45.95 -8.2135 -74.4284 -46 -10.5901 -74.3818 -46.05 -12.9042 -74.3314 -46.1 -15.155 -74.2765 -46.15 -17.343 -74.216 -46.2 -19.4695 -74.1486 -46.25 -21.5364 -74.0729 -46.3 -23.5466 -73.9871 -46.35 -25.5036 -73.8887 -46.4 -27.4116 -73.7752 -46.45 -29.2753 -73.6432 -46.5 -31.1002 -73.4886 -46.55 -32.8923 -73.3066 -46.6 -34.6584 -73.0913 -46.65 -36.4054 -72.8356 -46.7 -38.1407 -72.5308 -46.75 -39.8716 -72.1665 -46.8 -41.6051 -71.7302 -46.85 -43.3474 -71.2065 -46.9 -45.1032 -70.5772 -46.95 -46.875 -69.82 -47 -48.6623 -68.9079 -47.05 -50.4603 -67.8084 -47.1 -52.2595 -66.4817 -47.15 -54.045 -64.8793 -47.2 -55.7962 -62.9416 -47.25 -57.4888 -60.5946 -47.3 -59.0958 -57.7446 -47.35 -60.5914 -54.2704 -47.4 -61.9542 -50.0091 -47.45 -63.1696 -44.7315 -47.5 -64.2318 -38.1005 -47.55 -65.1431 -29.6105 -47.6 -65.9125 -18.5677 -47.65 -66.5537 -4.38632 -47.7 -67.082 12.2002 -47.75 -67.5134 27.7237 -47.8 -67.8627 38.228 -47.85 -68.143 43.3038 -47.9 -68.3658 45.0222 -47.95 -68.5405 45.1695 -48 -68.6752 44.6169 -48.05 -68.7763 43.6959 -48.1 -68.8493 42.5224 -48.15 -68.8986 41.1402 -48.2 -68.9279 39.5716 -48.25 -68.9402 37.8339 -48.3 -68.9381 35.9441 -48.35 -68.9237 33.9194 -48.4 -68.8988 31.7775 -48.45 -68.8648 29.5363 -48.5 -68.8229 27.2128 -48.55 -68.7743 24.8236 -48.6 -68.7199 22.3838 -48.65 -68.6603 19.9073 -48.7 -68.5963 17.4065 -48.75 -68.5285 14.8924 -48.8 -68.4572 12.3743 -48.85 -68.3829 9.86022 -48.9 -68.306 7.35676 -48.95 -68.2267 4.86923 -49 -68.1454 2.40178 -49.05 -68.0621 -0.0425091 -49.1 -67.9772 -2.46145 -49.15 -67.8908 -4.8538 -49.2 -67.803 -7.21894 -49.25 -67.714 -9.55713 -49.3 -67.6239 -11.8692 -49.35 -67.5327 -14.1566 -49.4 -67.4406 -16.4218 -49.45 -67.3477 -18.6678 -49.5 -67.2539 -20.8989 -49.55 -67.1594 -23.1206 -49.6 -67.0642 -25.3402 -49.65 -66.9684 -27.5674 -49.7 -66.872 -29.8143 -49.75 -66.775 -32.0963 -49.8 -66.6775 -34.4332 -49.85 -66.5795 -36.8489 -49.9 -66.481 -39.372 -49.95 -66.3821 -42.0352 -50 -66.2827 -44.8728 -50.05 -66.183 -47.9162 -50.1 -66.0829 -51.1837 -50.15 -65.9824 -54.665 -50.2 -65.8816 -58.3009 -50.25 -65.7805 -61.9637 -50.3 -65.679 -65.4591 -50.35 -65.5773 -68.5648 -50.4 -65.4753 -71.1076 -50.45 -65.3731 -73.0274 -50.5 -65.2706 -74.3802 -50.55 -65.1678 -75.2865 -50.6 -65.0649 -75.8751 -50.65 -64.9617 -76.2515 -50.7 -64.8584 -76.4912 -50.75 -64.7548 -76.644 -50.8 -64.6511 -76.742 -50.85 -64.5473 -76.8053 -50.9 -64.4432 -76.8464 -50.95 -64.3391 -76.8731 -51 -64.2348 -76.8905 -51.05 -64.1304 -76.9018 -51.1 -64.0259 -76.9089 -51.15 -63.9213 -76.9133 -51.2 -63.8167 -76.9158 -51.25 -63.7119 -76.9169 -51.3 -63.6071 -76.9172 -51.35 -63.5022 -76.9168 -51.4 -63.3973 -76.9159 -51.45 -63.2923 -76.9146 -51.5 -63.1873 -76.9131 -51.55 -63.0823 -76.9114 -51.6 -62.9773 -76.9095 -51.65 -62.8722 -76.9075 -51.7 -62.7672 -76.9054 -51.75 -62.6622 -76.9032 -51.8 -62.5572 -76.9009 -51.85 -62.4522 -76.8985 -51.9 -62.3473 -76.8961 -51.95 -62.2424 -76.8935 -52 -62.1375 -76.8909 -52.05 -62.0327 -76.8883 -52.1 -61.928 -76.8856 -52.15 -61.8233 -76.8828 -52.2 -61.7187 -76.8799 -52.25 -61.6142 -76.877 -52.3 -61.5098 -76.874 -52.35 -61.4054 -76.871 -52.4 -61.3012 -76.8679 -52.45 -61.197 -76.8647 -52.5 -61.093 -76.8615 -52.55 -60.989 -76.8582 -52.6 -60.8852 -76.8548 -52.65 -60.7815 -76.8513 -52.7 -60.6779 -76.8478 -52.75 -60.5744 -76.8442 -52.8 -60.4711 -76.8406 -52.85 -60.3679 -76.8368 -52.9 -60.2648 -76.833 -52.95 -60.1618 -76.8291 -53 -60.059 -76.8252 -53.05 -59.9563 -76.8211 -53.1 -59.8537 -76.817 -53.15 -59.7513 -76.8128 -53.2 -59.649 -76.8085 -53.25 -59.5469 -76.8041 -53.3 -59.4449 -76.7996 -53.35 -59.343 -76.7951 -53.4 -59.2412 -76.7905 -53.45 -59.1396 -76.7857 -53.5 -59.0381 -76.7809 -53.55 -58.9368 -76.776 -53.6 -58.8356 -76.771 -53.65 -58.7345 -76.7659 -53.7 -58.6335 -76.7607 -53.75 -58.5326 -76.7554 -53.8 -58.4319 -76.75 -53.85 -58.3312 -76.7445 -53.9 -58.2307 -76.7388 -53.95 -58.1303 -76.7331 -54 -58.03 -76.7273 -54.05 -57.9297 -76.7214 -54.1 -57.8296 -76.7153 -54.15 -57.7295 -76.7091 -54.2 -57.6295 -76.7029 -54.25 -57.5295 -76.6965 -54.3 -57.4296 -76.69 -54.35 -57.3298 -76.6833 -54.4 -57.23 -76.6766 -54.45 -57.1302 -76.6697 -54.5 -57.0305 -76.6627 -54.55 -56.9307 -76.6555 -54.6 -56.831 -76.6482 -54.65 -56.7312 -76.6408 -54.7 -56.6314 -76.6333 -54.75 -56.5316 -76.6256 -54.8 -56.4318 -76.6178 -54.85 -56.3318 -76.6099 -54.9 -56.2318 -76.6018 -54.95 -56.1317 -76.5935 -55 -56.0315 -76.5851 -55.05 -55.9311 -76.5766 -55.1 -55.8306 -76.5679 -55.15 -55.73 -76.559 -55.2 -55.6292 -76.5501 -55.25 -55.5282 -76.5409 -55.3 -55.4269 -76.5316 -55.35 -55.3254 -76.5221 -55.4 -55.2237 -76.5125 -55.45 -55.1216 -76.5027 -55.5 -55.0192 -76.4927 -55.55 -54.9165 -76.4826 -55.6 -54.8134 -76.4723 -55.65 -54.71 -76.4618 -55.7 -54.606 -76.4511 -55.75 -54.5017 -76.4403 -55.8 -54.3968 -76.4293 -55.85 -54.2914 -76.4181 -55.9 -54.1854 -76.4068 -55.95 -54.0788 -76.3952 -56 -53.9715 -76.3835 -56.05 -53.8635 -76.3716 -56.1 -53.7548 -76.3594 -56.15 -53.6453 -76.3471 -56.2 -53.5349 -76.3347 -56.25 -53.4236 -76.322 -56.3 -53.3113 -76.3091 -56.35 -53.198 -76.296 -56.4 -53.0835 -76.2828 -56.45 -52.9679 -76.2693 -56.5 -52.851 -76.2556 -56.55 -52.7327 -76.2417 -56.6 -52.613 -76.2277 -56.65 -52.4918 -76.2134 -56.7 -52.3689 -76.1989 -56.75 -52.2442 -76.1842 -56.8 -52.1176 -76.1693 -56.85 -51.989 -76.1542 -56.9 -51.8582 -76.1389 -56.95 -51.7251 -76.1234 -57 -51.5895 -76.1076 -57.05 -51.4512 -76.0917 -57.1 -51.3101 -76.0755 -57.15 -51.1658 -76.0591 -57.2 -51.0182 -76.0426 -57.25 -50.867 -76.0257 -57.3 -50.7119 -76.0087 -57.35 -50.5525 -75.9915 -57.4 -50.3886 -75.974 -57.45 -50.2198 -75.9563 -57.5 -50.0456 -75.9384 -57.55 -49.8655 -75.9203 -57.6 -49.679 -75.9019 -57.65 -49.4856 -75.8834 -57.7 -49.2845 -75.8646 -57.75 -49.0751 -75.8456 -57.8 -48.8564 -75.8263 -57.85 -48.6275 -75.8068 -57.9 -48.3875 -75.7872 -57.95 -48.1349 -75.7672 -58 -47.8686 -75.7471 -58.05 -47.5867 -75.7267 -58.1 -47.2877 -75.7061 -58.15 -46.9692 -75.6853 -58.2 -46.629 -75.6643 -58.25 -46.264 -75.643 -58.3 -45.8711 -75.6215 -58.35 -45.4461 -75.5997 -58.4 -44.9847 -75.5778 -58.45 -44.4811 -75.5556 -58.5 -43.9288 -75.5331 -58.55 -43.32 -75.5105 -58.6 -42.645 -75.4876 -58.65 -41.8923 -75.4644 -58.7 -41.0478 -75.4411 -58.75 -40.0941 -75.4175 -58.8 -39.01 -75.3936 -58.85 -37.7692 -75.3696 -58.9 -36.3396 -75.3452 -58.95 -34.6815 -75.3207 -59 -32.747 -75.2959 -59.05 -30.4789 -75.2708 -59.1 -27.8115 -75.2455 -59.15 -24.6738 -75.2199 -59.2 -20.9978 -75.1941 -59.25 -16.7352 -75.168 -59.3 -11.8838 -75.1416 -59.35 -6.52491 -75.115 -59.4 -0.85677 -75.0881 -59.45 4.79784 -75.0609 -59.5 10.0374 -75.0333 -59.55 14.477 -75.0055 -59.6 17.8475 -74.9774 -59.65 20.0458 -74.9489 -59.7 21.1187 -74.92 -59.75 21.2097 -74.8907 -59.8 20.5015 -74.8611 -59.85 19.176 -74.8309 -59.9 17.393 -74.8003 -59.95 15.2841 -74.7691 -60 12.9523 -74.7373 -60.05 10.4768 -74.7048 -60.1 7.91728 -74.6715 -60.15 5.31813 -74.6372 -60.2 2.71201 -74.6018 -60.25 0.122674 -74.565 -60.3 -2.43286 -74.5266 -60.35 -4.94269 -74.4863 -60.4 -7.39878 -74.4437 -60.45 -9.79597 -74.3981 -60.5 -12.1313 -74.3491 -60.55 -14.4036 -74.2958 -60.6 -16.6127 -74.2373 -60.65 -18.7597 -74.1725 -60.7 -20.8464 -74.0998 -60.75 -22.8754 -74.0176 -60.8 -24.85 -73.9237 -60.85 -26.7741 -73.8157 -60.9 -28.6521 -73.6903 -60.95 -30.4895 -73.5439 -61 -32.2919 -73.3718 -61.05 -34.0659 -73.1685 -61.1 -35.8185 -72.9274 -61.15 -37.5569 -72.6403 -61.2 -39.2884 -72.2974 -61.25 -41.0203 -71.887 -61.3 -42.7589 -71.3948 -61.35 -44.5097 -70.8036 -61.4 -46.2759 -70.0925 -61.45 -48.0582 -69.2362 -61.5 -49.8533 -68.2042 -61.55 -51.6536 -66.9594 -61.6 -53.4457 -65.4565 -61.65 -55.211 -63.6399 -61.7 -56.9261 -61.4409 -61.75 -58.5649 -58.7734 -61.8 -60.1007 -55.5265 -61.85 -61.5102 -51.5535 -61.9 -62.7763 -46.6516 -61.95 -63.8903 -40.526 -62 -64.8517 -32.7354 -62.05 -65.6677 -22.6421 -62.1 -66.3504 -9.54668 -62.15 -66.915 6.46862 -62.2 -67.3774 22.8767 -62.25 -67.7529 35.3411 -62.3 -68.0551 42.0753 -62.35 -68.2961 44.6839 -62.4 -68.4861 45.2258 -62.45 -68.6335 44.855 -62.5 -68.7453 44.0394 -62.55 -68.8272 42.9446 -62.6 -68.8841 41.63 -62.65 -68.9198 40.1225 -62.7 -68.9376 38.4402 -62.75 -68.9401 36.6 -62.8 -68.9297 34.619 -62.85 -68.9081 32.5148 -62.9 -68.877 30.3053 -62.95 -68.8376 28.0078 -63 -68.7912 25.639 -63.05 -68.7387 23.2147 -63.1 -68.6808 20.7491 -63.15 -68.6182 18.2553 -63.2 -68.5516 15.7445 -63.25 -68.4814 13.2268 -63.3 -68.4081 10.7106 -63.35 -68.3321 8.20286 -63.4 -68.2536 5.70941 -63.45 -68.1729 3.23474 -63.5 -68.0902 0.782331 -63.55 -68.0059 -1.6454 -63.6 -67.92 -4.04685 -63.65 -67.8326 -6.42122 -63.7 -67.744 -8.76851 -63.75 -67.6543 -11.0893 -63.8 -67.5634 -13.3848 -63.85 -67.4717 -15.6572 -63.9 -67.379 -17.9093 -63.95 -67.2855 -20.1448 -64 -67.1912 -22.369 -64.05 -67.0963 -24.5885 -64.1 -67.0007 -26.812 -64.15 -66.9044 -29.0505 -64.2 -66.8076 -31.3186 -64.25 -66.7103 -33.6346 -64.3 -66.6124 -36.0206 -64.35 -66.5141 -38.5038 -64.4 -66.4153 -41.1158 -64.45 -66.3161 -43.8906 -64.5 -66.2165 -46.8614 -64.55 -66.1165 -50.0523 -64.6 -66.0162 -53.465 -64.65 -65.9155 -57.0591 -64.7 -65.8145 -60.7318 -64.75 -65.7131 -64.3087 -64.8 -65.6115 -67.5698 -64.85 -65.5096 -70.3163 -64.9 -65.4074 -72.4458 -64.95 -65.305 -73.9788 -65 -65.2024 -75.0213 -65.05 -65.0995 -75.7042 -65.1 -64.9964 -76.1426 -65.15 -64.8931 -76.4218 -65.2 -64.7896 -76.5997 -65.25 -64.686 -76.7136 -65.3 -64.5822 -76.7869 -65.35 -64.4782 -76.8344 -65.4 -64.3741 -76.8653 -65.45 -64.2699 -76.8854 -65.5 -64.1655 -76.8985 -65.55 -64.0611 -76.9069 -65.6 -63.9565 -76.912 -65.65 -63.8518 -76.9151 -65.7 -63.7471 -76.9166 -65.75 -63.6423 -76.9172 -65.8 -63.5375 -76.917 -65.85 -63.4325 -76.9162 -65.9 -63.3276 -76.9151 -65.95 -63.2226 -76.9137 -66 -63.1176 -76.912 -66.05 -63.0126 -76.9102 -66.1 -62.9075 -76.9082 -66.15 -62.8025 -76.9061 -66.2 -62.6975 -76.904 -66.25 -62.5925 -76.9017 -66.3 -62.4875 -76.8993 -66.35 -62.3825 -76.8969 -66.4 -62.2776 -76.8944 -66.45 -62.1728 -76.8918 -66.5 -62.0679 -76.8892 -66.55 -61.9632 -76.8865 -66.6 -61.8585 -76.8837 -66.65 -61.7539 -76.8809 -66.7 -61.6493 -76.878 -66.75 -61.5449 -76.875 -66.8 -61.4405 -76.872 -66.85 -61.3362 -76.8689 -66.9 -61.232 -76.8658 -66.95 -61.1279 -76.8626 -67 -61.024 -76.8593 -67.05 -60.9201 -76.8559 -67.1 -60.8164 -76.8525 -67.15 -60.7127 -76.849 -67.2 -60.6092 -76.8454 -67.25 -60.5058 -76.8418 -67.3 -60.4026 -76.8381 -67.35 -60.2994 -76.8343 -67.4 -60.1964 -76.8304 -67.45 -60.0935 -76.8265 -67.5 -59.9908 -76.8225 -67.55 -59.8882 -76.8184 -67.6 -59.7857 -76.8142 -67.65 -59.6834 -76.8099 -67.7 -59.5812 -76.8056 -67.75 -59.4791 -76.8012 -67.8 -59.3772 -76.7966 -67.85 -59.2754 -76.792 -67.9 -59.1738 -76.7873 -67.95 -59.0722 -76.7825 -68 -58.9708 -76.7777 -68.05 -58.8696 -76.7727 -68.1 -58.7684 -76.7676 -68.15 -58.6674 -76.7624 -68.2 -58.5665 -76.7572 -68.25 -58.4657 -76.7518 -68.3 -58.3651 -76.7463 -68.35 -58.2645 -76.7408 -68.4 -58.164 -76.7351 -68.45 -58.0637 -76.7293 -68.5 -57.9634 -76.7234 -68.55 -57.8632 -76.7174 -68.6 -57.7631 -76.7112 -68.65 -57.6631 -76.705 -68.7 -57.5631 -76.6986 -68.75 -57.4632 -76.6922 -68.8 -57.3634 -76.6856 -68.85 -57.2636 -76.6789 -68.9 -57.1638 -76.672 -68.95 -57.064 -76.665 -69 -56.9643 -76.6579 -69.05 -56.8645 -76.6507 -69.1 -56.7648 -76.6434 -69.15 -56.665 -76.6359 -69.2 -56.5652 -76.6282 -69.25 -56.4654 -76.6205 -69.3 -56.3654 -76.6126 -69.35 -56.2655 -76.6045 -69.4 -56.1654 -76.5963 -69.45 -56.0652 -76.588 -69.5 -55.9649 -76.5795 -69.55 -55.8645 -76.5708 -69.6 -55.7639 -76.5621 -69.65 -55.6631 -76.5531 -69.7 -55.5622 -76.544 -69.75 -55.461 -76.5348 -69.8 -55.3596 -76.5253 -69.85 -55.2579 -76.5158 -69.9 -55.156 -76.506 -69.95 -55.0537 -76.4961 -70 -54.9511 -76.486 -70.05 -54.8482 -76.4758 -70.1 -54.7448 -76.4654 -70.15 -54.6411 -76.4548 -70.2 -54.5368 -76.444 -70.25 -54.4321 -76.433 -70.3 -54.3269 -76.4219 -70.35 -54.2211 -76.4106 -70.4 -54.1147 -76.3991 -70.45 -54.0077 -76.3875 -70.5 -53.8999 -76.3756 -70.55 -53.7915 -76.3636 -70.6 -53.6822 -76.3513 -70.65 -53.5722 -76.3389 -70.7 -53.4612 -76.3263 -70.75 -53.3492 -76.3135 -70.8 -53.2362 -76.3005 -70.85 -53.1222 -76.2873 -70.9 -53.0069 -76.2739 -70.95 -52.8905 -76.2603 -71 -52.7727 -76.2465 -71.05 -52.6535 -76.2325 -71.1 -52.5328 -76.2182 -71.15 -52.4104 -76.2038 -71.2 -52.2864 -76.1892 -71.25 -52.1604 -76.1744 -71.3 -52.0325 -76.1594 -71.35 -51.9025 -76.1441 -71.4 -51.7702 -76.1287 -71.45 -51.6355 -76.113 -71.5 -51.4981 -76.0971 -71.55 -51.358 -76.081 -71.6 -51.2148 -76.0647 -71.65 -51.0683 -76.0482 -71.7 -50.9183 -76.0315 -71.75 -50.7646 -76.0145 -71.8 -50.6067 -75.9973 -71.85 -50.4444 -75.9799 -71.9 -50.2773 -75.9623 -71.95 -50.1049 -75.9445 -72 -49.9269 -75.9264 -72.05 -49.7426 -75.9082 -72.1 -49.5516 -75.8897 -72.15 -49.3532 -75.8709 -72.2 -49.1466 -75.852 -72.25 -48.9312 -75.8328 -72.3 -48.7059 -75.8134 -72.35 -48.4697 -75.7938 -72.4 -48.2215 -75.774 -72.45 -47.96 -75.7539 -72.5 -47.6836 -75.7336 -72.55 -47.3905 -75.7131 -72.6 -47.0789 -75.6924 -72.65 -46.7463 -75.6714 -72.7 -46.39 -75.6502 -72.75 -46.0069 -75.6288 -72.8 -45.5933 -75.6071 -72.85 -45.1447 -75.5852 -72.9 -44.656 -75.5631 -72.95 -44.1209 -75.5407 -73 -43.5321 -75.5182 -73.05 -42.8806 -75.4953 -73.1 -42.1556 -75.4723 -73.15 -41.3438 -75.449 -73.2 -40.4291 -75.4255 -73.25 -39.3916 -75.4017 -73.3 -38.207 -75.3777 -73.35 -36.8451 -75.3535 -73.4 -35.269 -75.329 -73.45 -33.4337 -75.3043 -73.5 -31.285 -75.2793 -73.55 -28.7601 -75.2541 -73.6 -25.789 -75.2286 -73.65 -22.3015 -75.2028 -73.7 -18.24 -75.1768 -73.75 -13.5831 -75.1506 -73.8 -8.37969 -75.124 -73.85 -2.78565 -75.0972 -73.9 2.91604 -75.0701 -73.95 8.34169 -75.0427 -74 13.0886 -75.015 -74.05 16.8398 -74.9869 -74.1 19.4348 -74.9585 -74.15 20.8748 -74.9298 -74.2 21.2775 -74.9007 -74.25 20.8179 -74.8711 -74.3 19.6814 -74.8412 -74.35 18.0366 -74.8107 -74.4 16.0248 -74.7797 -74.45 13.7582 -74.7482 -74.5 11.3236 -74.7159 -74.55 8.78685 -74.6828 -74.6 6.19691 -74.6489 -74.65 3.59009 -74.6139 -74.7 0.992897 -74.5776 -74.75 -1.57559 -74.5398 -74.8 -4.1019 -74.5002 -74.85 -6.57683 -74.4584 -74.9 -8.9943 -74.4139 -74.95 -11.3507 -74.3661 -75 -13.6443 -74.3143 -75.05 -15.8747 -74.2577 -75.1 -18.0425 -74.1951 -75.15 -20.1493 -74.1253 -75.2 -22.1975 -74.0465 -75.25 -24.19 -73.9569 -75.3 -26.1306 -73.8539 -75.35 -28.0236 -73.7348 -75.4 -29.8741 -73.5959 -75.45 -31.6876 -73.4331 -75.5 -33.4705 -73.241 -75.55 -35.2295 -73.0134 -75.6 -36.9718 -72.7428 -75.65 -38.7048 -72.42 -75.7 -40.4358 -72.0339 -75.75 -42.1715 -71.571 -75.8 -43.9177 -71.0154 -75.85 -45.6785 -70.3472 -75.9 -47.4555 -69.5431 -75.95 -49.2469 -68.5742 -76 -51.0465 -67.4058 -76.05 -52.8431 -65.9955 -76.1 -54.6199 -64.2917 -76.15 -56.3549 -62.2304 -76.2 -58.0224 -59.7319 -76.25 -59.5958 -56.6947 -76.3 -61.0501 -52.9861 -76.35 -62.3661 -48.4249 -76.4 -63.5318 -42.7529 -76.45 -64.5442 -35.5851 -76.5 -65.408 -26.3512 -76.55 -66.1341 -14.3288 -76.6 -66.7368 0.829753 -76.65 -67.2319 17.5731 -76.7 -67.6351 31.7799 -76.75 -67.9605 40.3817 -76.8 -68.221 44.121 -76.85 -68.4272 45.1836 -76.9 -68.5881 45.0439 -76.95 -68.7112 44.3506 -77 -68.8026 43.3404 -77.05 -68.8674 42.096 -77.1 -68.9099 40.6514 -77.15 -68.9334 39.0262 -77.2 -68.9408 37.2373 -77.25 -68.9345 35.3018 -77.3 -68.9165 33.2372 -77.35 -68.8884 31.0612 -77.4 -68.8517 28.7915 -77.45 -68.8076 26.445 -77.5 -68.757 24.0377 -77.55 -68.7008 21.5845 -77.6 -68.6398 19.0989 -77.65 -68.5745 16.5926 -77.7 -68.5055 14.0762 -77.75 -68.4332 11.5586 -77.8 -68.358 9.04734 -77.85 -68.2803 6.54852 -77.9 -68.2003 4.06708 -77.95 -68.1183 1.60685 -78 -68.0345 -0.82944 -78.05 -67.9491 -3.23986 -78.1 -67.8622 -5.62344 -78.15 -67.774 -7.97982 -78.2 -67.6846 -10.3094 -78.25 -67.5942 -12.6133 -78.3 -67.5027 -14.8932 -78.35 -67.4103 -17.1517 -78.4 -67.3171 -19.3924 -78.45 -67.2231 -21.6198 -78.5 -67.1284 -23.84 -78.55 -67.033 -26.0609 -78.6 -66.9369 -28.2929 -78.65 -66.8403 -30.5493 -78.7 -66.7432 -32.8469 -78.75 -66.6455 -35.2064 -78.8 -66.5473 -37.6535 -78.85 -66.4487 -40.2183 -78.9 -66.3496 -42.9344 -78.95 -66.2501 -45.8357 -79 -66.1503 -48.9507 -79.05 -66.05 -52.2906 -79.1 -65.9495 -55.8315 -79.15 -65.8486 -59.4937 -79.2 -65.7473 -63.1261 -79.25 -65.6458 -66.5188 -79.3 -65.544 -69.4564 -79.35 -65.4419 -71.7975 -79.4 -65.3396 -73.5229 -79.45 -65.237 -74.7164 -79.5 -65.1342 -75.5064 -79.55 -65.0312 -76.0161 -79.6 -64.9279 -76.3413 -79.65 -64.8245 -76.5484 -79.7 -64.7209 -76.6806 -79.75 -64.6172 -76.7656 -79.8 -64.5133 -76.8206 -79.85 -64.4092 -76.8563 -79.9 -64.305 -76.8796 -79.95 -64.2007 -76.8947 -80 -64.0963 -76.9044 -80.05 -63.9918 -76.9106 -80.1 -63.8871 -76.9143 -80.15 -63.7824 -76.9163 -80.2 -63.6776 -76.9171 -80.25 -63.5728 -76.9171 -80.3 -63.4679 -76.9165 -80.35 -63.363 -76.9155 -80.4 -63.258 -76.9142 -80.45 -63.153 -76.9126 -80.5 -63.048 -76.9108 -80.55 -62.9429 -76.9089 -80.6 -62.8379 -76.9069 -80.65 -62.7329 -76.9047 -80.7 -62.6279 -76.9025 -80.75 -62.5229 -76.9001 -80.8 -62.4179 -76.8977 -80.85 -62.313 -76.8952 -80.9 -62.2081 -76.8927 -80.95 -62.1033 -76.8901 -81 -61.9985 -76.8874 -81.05 -61.8938 -76.8847 -81.1 -61.7891 -76.8819 -81.15 -61.6846 -76.879 -81.2 -61.5801 -76.876 -81.25 -61.4757 -76.873 -81.3 -61.3714 -76.87 -81.35 -61.2671 -76.8669 -81.4 -61.163 -76.8637 -81.45 -61.059 -76.8604 -81.5 -60.9551 -76.8571 -81.55 -60.8513 -76.8537 -81.6 -60.7476 -76.8502 -81.65 -60.6441 -76.8467 -81.7 -60.5407 -76.843 -81.75 -60.4374 -76.8394 -81.8 -60.3342 -76.8356 -81.85 -60.2311 -76.8318 -81.9 -60.1282 -76.8278 -81.95 -60.0254 -76.8239 -82 -59.9228 -76.8198 -82.05 -59.8203 -76.8156 -82.1 -59.7179 -76.8114 -82.15 -59.6156 -76.8071 -82.2 -59.5135 -76.8027 -82.25 -59.4116 -76.7982 -82.3 -59.3097 -76.7936 -82.35 -59.208 -76.7889 -82.4 -59.1064 -76.7842 -82.45 -59.005 -76.7793 -82.5 -58.9037 -76.7744 -82.55 -58.8025 -76.7693 -82.6 -58.7015 -76.7642 -82.65 -58.6005 -76.759 -82.7 -58.4997 -76.7536 -82.75 -58.399 -76.7482 -82.8 -58.2984 -76.7426 -82.85 -58.1979 -76.737 -82.9 -58.0975 -76.7312 -82.95 -57.9972 -76.7254 -83 -57.897 -76.7194 -83.05 -57.7969 -76.7133 -83.1 -57.6968 -76.7071 -83.15 -57.5968 -76.7008 -83.2 -57.4969 -76.6944 -83.25 -57.397 -76.6878 -83.3 -57.2972 -76.6811 -83.35 -57.1974 -76.6743 -83.4 -57.0976 -76.6674 -83.45 -56.9979 -76.6604 -83.5 -56.8982 -76.6532 -83.55 -56.7984 -76.6459 -83.6 -56.6986 -76.6384 -83.65 -56.5989 -76.6308 -83.7 -56.499 -76.6231 -83.75 -56.3991 -76.6152 -83.8 -56.2992 -76.6072 -83.85 -56.1991 -76.5991 -83.9 -56.099 -76.5908 -83.95 -55.9987 -76.5824 -84 -55.8983 -76.5738 -84.05 -55.7978 -76.565 -84.1 -55.6971 -76.5561 -84.15 -55.5962 -76.5471 -84.2 -55.4951 -76.5379 -84.25 -55.3938 -76.5285 -84.3 -55.2922 -76.519 -84.35 -55.1904 -76.5093 -84.4 -55.0882 -76.4995 -84.45 -54.9857 -76.4894 -84.5 -54.8829 -76.4792 -84.55 -54.7797 -76.4689 -84.6 -54.6761 -76.4584 -84.65 -54.572 -76.4476 -84.7 -54.4675 -76.4368 -84.75 -54.3625 -76.4257 -84.8 -54.2569 -76.4145 -84.85 -54.1507 -76.403 -84.9 -54.0438 -76.3914 -84.95 -53.9364 -76.3796 -85 -53.8281 -76.3676 -85.05 -53.7192 -76.3555 -85.1 -53.6094 -76.3431 -85.15 -53.4987 -76.3306 -85.2 -53.3871 -76.3178 -85.25 -53.2745 -76.3049 -85.3 -53.1608 -76.2917 -85.35 -53.0459 -76.2784 -85.4 -52.9299 -76.2649 -85.45 -52.8126 -76.2511 -85.5 -52.6938 -76.2372 -85.55 -52.5736 -76.2231 -85.6 -52.4519 -76.2087 -85.65 -52.3284 -76.1942 -85.7 -52.2031 -76.1794 -85.75 -52.0759 -76.1644 -85.8 -51.9466 -76.1493 -85.85 -51.8151 -76.1339 -85.9 -51.6812 -76.1183 -85.95 -51.5447 -76.1025 -86 -51.4055 -76.0865 -86.05 -51.2634 -76.0702 -86.1 -51.118 -76.0538 -86.15 -50.9693 -76.0371 -86.2 -50.8168 -76.0202 -86.25 -50.6604 -76.0031 -86.3 -50.4996 -75.9858 -86.35 -50.3342 -75.9683 -86.4 -50.1636 -75.9505 -86.45 -49.9875 -75.9326 -86.5 -49.8055 -75.9144 -86.55 -49.6168 -75.8959 -86.6 -49.4209 -75.8773 -86.65 -49.2172 -75.8584 -86.7 -49.0048 -75.8393 -86.75 -48.783 -75.82 -86.8 -48.5506 -75.8005 -86.85 -48.3066 -75.7807 -86.9 -48.0497 -75.7607 -86.95 -47.7785 -75.7405 -87 -47.4913 -75.7201 -87.05 -47.1862 -75.6994 -87.1 -46.8609 -75.6785 -87.15 -46.5129 -75.6574 -87.2 -46.1393 -75.636 -87.25 -45.7364 -75.6144 -87.3 -45.3001 -75.5926 -87.35 -44.8256 -75.5706 -87.4 -44.3069 -75.5483 -87.45 -43.7372 -75.5258 -87.5 -43.1079 -75.5031 -87.55 -42.409 -75.4801 -87.6 -41.6281 -75.4569 -87.65 -40.7501 -75.4334 -87.7 -39.7565 -75.4098 -87.75 -38.6246 -75.3858 -87.8 -37.3262 -75.3617 -87.85 -35.8269 -75.3373 -87.9 -34.0846 -75.3126 -87.95 -32.0482 -75.2877 -88 -29.6576 -75.2626 -88.05 -26.845 -75.2372 -88.1 -23.539 -75.2116 -88.15 -19.6758 -75.1856 -88.2 -15.2186 -75.1595 -88.25 -10.188 -75.133 -88.3 -4.70038 -75.1063 -88.35 1.00406 -75.0793 -88.4 6.56901 -75.052 -88.45 11.5865 -75.0243 -88.5 15.6998 -74.9964 -88.55 18.692 -74.9681 -88.6 20.5127 -74.9395 -88.65 21.2473 -74.9105 -88.7 21.0575 -74.8812 -88.75 20.1292 -74.8513 -88.8 18.6386 -74.8211 -88.85 16.7365 -74.7903 -88.9 14.5449 -74.7589 -88.95 12.1587 -74.7269 -89 9.65015 -74.6941 -89.05 7.0735 -74.6605 -89.1 4.46898 -74.6258 -89.15 1.86608 -74.59 -89.2 -0.713837 -74.5527 -89.25 -3.25559 -74.5138 -89.3 -5.74865 -74.4727 -89.35 -8.186 -74.4292 -89.4 -10.5633 -74.3826 -89.45 -12.8782 -74.3323 -89.5 -15.1298 -74.2774 -89.55 -17.3186 -74.217 -89.6 -19.4457 -74.1498 -89.65 -21.5133 -74.0742 -89.7 -23.5242 -73.9884 -89.75 -25.4818 -73.8903 -89.8 -27.3903 -73.777 -89.85 -29.2545 -73.6452 -89.9 -31.0798 -73.491 -89.95 -32.8723 -73.3094 -90 -34.6386 -73.0946 -90.05 -36.3858 -72.8394 -90.1 -38.1211 -72.5353 -90.15 -39.852 -72.1719 -90.2 -41.5854 -71.7366 -90.25 -43.3275 -71.2142 -90.3 -45.083 -70.5864 -90.35 -46.8546 -69.8311 -90.4 -48.6417 -68.9213 -90.45 -50.4396 -67.8244 -90.5 -52.2388 -66.501 -90.55 -54.0244 -64.9026 -90.6 -55.7761 -62.9699 -90.65 -57.4694 -60.6289 -90.7 -59.0775 -57.7863 -90.75 -60.5744 -54.3214 -90.8 -61.9388 -50.0719 -90.85 -63.1559 -44.8099 -90.9 -64.2199 -38.1999 -90.95 -65.1328 -29.7391 -91 -65.9039 -18.7355 -91.05 -66.5464 -4.5965 -91.1 -67.076 11.9743 -91.15 -67.5085 27.5428 -91.2 -67.8587 38.1261 -91.25 -68.1398 43.2627 -91.3 -68.3631 45.012 -91.35 -68.5384 45.173 -91.4 -68.6735 44.6267 -91.45 -68.775 43.7096 -91.5 -68.8483 42.5391 -91.55 -68.8979 41.1595 -91.6 -68.9274 39.5932 -91.65 -68.9399 37.8577 -91.7 -68.938 35.9697 -91.75 -68.9238 33.9466 -91.8 -68.8989 31.8062 -91.85 -68.865 29.5661 -91.9 -68.8232 27.2436 -91.95 -68.7747 24.8551 -92 -68.7204 22.4159 -92.05 -68.6609 19.9398 -92.1 -68.5969 17.4392 -92.15 -68.5291 14.9252 -92.2 -68.4579 12.4071 -92.25 -68.3836 9.89291 -92.3 -68.3068 7.38927 -92.35 -68.2275 4.90148 -92.4 -68.1462 2.43374 -92.45 -68.0629 -0.010878 -92.5 -67.9781 -2.43016 -92.55 -67.8917 -4.82287 -92.6 -67.8039 -7.18838 -92.65 -67.7149 -9.52693 -92.7 -67.6248 -11.8393 -92.75 -67.5336 -14.1271 -92.8 -67.4416 -16.3925 -92.85 -67.3486 -18.6388 -92.9 -67.2549 -20.87 -92.95 -67.1604 -23.0918 -93 -67.0652 -25.3114 -93.05 -66.9694 -27.5385 -93.1 -66.873 -29.785 -93.15 -66.776 -32.0665 -93.2 -66.6785 -34.4024 -93.25 -66.5805 -36.8169 -93.3 -66.482 -39.3384 -93.35 -66.3831 -41.9996 -93.4 -66.2837 -44.8348 -93.45 -66.184 -47.8754 -93.5 -66.0839 -51.1399 -93.55 -65.9834 -54.6187 -93.6 -65.8826 -58.2532 -93.65 -65.7815 -61.9169 -93.7 -65.6801 -65.4159 -93.75 -65.5783 -68.5279 -93.8 -65.4764 -71.0787 -93.85 -65.3741 -73.0064 -93.9 -65.2716 -74.3658 -93.95 -65.1689 -75.277 -94 -65.0659 -75.869 -94.05 -64.9628 -76.2477 -94.1 -64.8594 -76.4887 -94.15 -64.7559 -76.6424 -94.2 -64.6522 -76.741 -94.25 -64.5483 -76.8046 -94.3 -64.4443 -76.8459 -94.35 -64.3402 -76.8728 -94.4 -64.2359 -76.8903 -94.45 -64.1315 -76.9016 -94.5 -64.027 -76.9088 -94.55 -63.9224 -76.9132 -94.6 -63.8177 -76.9157 -94.65 -63.713 -76.9169 -94.7 -63.6082 -76.9172 -94.75 -63.5033 -76.9168 -94.8 -63.3984 -76.9159 -94.85 -63.2934 -76.9146 -94.9 -63.1884 -76.9131 -94.95 -63.0834 -76.9114 -95 -62.9784 -76.9096 -95.05 -62.8733 -76.9076 -95.1 -62.7683 -76.9054 -95.15 -62.6633 -76.9032 -95.2 -62.5583 -76.9009 -95.25 -62.4533 -76.8985 -95.3 -62.3484 -76.8961 -95.35 -62.2435 -76.8936 -95.4 -62.1386 -76.891 -95.45 -62.0338 -76.8883 -95.5 -61.9291 -76.8856 -95.55 -61.8244 -76.8828 -95.6 -61.7198 -76.88 -95.65 -61.6153 -76.877 -95.7 -61.5109 -76.8741 -95.75 -61.4065 -76.871 -95.8 -61.3023 -76.8679 -95.85 -61.1981 -76.8647 -95.9 -61.0941 -76.8615 -95.95 -60.9901 -76.8582 -96 -60.8863 -76.8548 -96.05 -60.7826 -76.8514 -96.1 -60.679 -76.8479 -96.15 -60.5755 -76.8443 -96.2 -60.4722 -76.8406 -96.25 -60.369 -76.8369 -96.3 -60.2659 -76.8331 -96.35 -60.1629 -76.8292 -96.4 -60.0601 -76.8252 -96.45 -59.9574 -76.8212 -96.5 -59.8548 -76.817 -96.55 -59.7524 -76.8128 -96.6 -59.6501 -76.8085 -96.65 -59.5479 -76.8042 -96.7 -59.4459 -76.7997 -96.75 -59.344 -76.7952 -96.8 -59.2423 -76.7905 -96.85 -59.1407 -76.7858 -96.9 -59.0392 -76.781 -96.95 -58.9378 -76.7761 -97 -58.8366 -76.771 -97.05 -58.7355 -76.7659 -97.1 -58.6345 -76.7607 -97.15 -58.5337 -76.7554 -97.2 -58.4329 -76.75 -97.25 -58.3323 -76.7445 -97.3 -58.2318 -76.7389 -97.35 -58.1314 -76.7332 -97.4 -58.031 -76.7274 -97.45 -57.9308 -76.7214 -97.5 -57.8306 -76.7154 -97.55 -57.7305 -76.7092 -97.6 -57.6305 -76.7029 -97.65 -57.5306 -76.6966 -97.7 -57.4307 -76.69 -97.75 -57.3309 -76.6834 -97.8 -57.2311 -76.6766 -97.85 -57.1313 -76.6698 -97.9 -57.0315 -76.6627 -97.95 -56.9318 -76.6556 -98 -56.832 -76.6483 -98.05 -56.7323 -76.6409 -98.1 -56.6325 -76.6334 -98.15 -56.5327 -76.6257 -98.2 -56.4328 -76.6179 -98.25 -56.3329 -76.61 -98.3 -56.2329 -76.6019 -98.35 -56.1328 -76.5936 -98.4 -56.0326 -76.5852 -98.45 -55.9322 -76.5767 -98.5 -55.8317 -76.568 -98.55 -55.7311 -76.5592 -98.6 -55.6303 -76.5502 -98.65 -55.5292 -76.541 -98.7 -55.428 -76.5317 -98.75 -55.3265 -76.5222 -98.8 -55.2248 -76.5126 -98.85 -55.1227 -76.5028 -98.9 -55.0203 -76.4928 -98.95 -54.9176 -76.4827 -99 -54.8146 -76.4724 -99.05 -54.7111 -76.4619 -99.1 -54.6072 -76.4513 -99.15 -54.5028 -76.4404 -99.2 -54.3979 -76.4294 -99.25 -54.2925 -76.4183 -99.3 -54.1865 -76.4069 -99.35 -54.0799 -76.3954 -99.4 -53.9727 -76.3836 -99.45 -53.8647 -76.3717 -99.5 -53.756 -76.3596 -99.55 -53.6465 -76.3473 -99.6 -53.5361 -76.3348 -99.65 -53.4248 -76.3221 -99.7 -53.3126 -76.3093 -99.75 -53.1992 -76.2962 -99.8 -53.0848 -76.2829 -99.85 -52.9692 -76.2695 -99.9 -52.8523 -76.2558 -99.95 -52.734 -76.2419 -100 -52.6144 -76.2279 -100.05 -52.4931 -76.2136 -100.1 -52.3702 -76.1991 -100.15 -52.2456 -76.1844 -100.2 -52.119 -76.1695 -100.25 -51.9904 -76.1544 -100.3 -51.8597 -76.1391 -100.35 -51.7266 -76.1236 -100.4 -51.5911 -76.1078 -100.45 -51.4528 -76.0919 -100.5 -51.3117 -76.0757 -100.55 -51.1674 -76.0594 -100.6 -51.0199 -76.0428 -100.65 -50.8687 -76.026 -100.7 -50.7136 -76.0089 -100.75 -50.5544 -75.9917 -100.8 -50.3905 -75.9742 -100.85 -50.2218 -75.9565 -100.9 -50.0476 -75.9386 -100.95 -49.8676 -75.9205 -101 -49.6812 -75.9022 -101.05 -49.4879 -75.8836 -101.1 -49.2869 -75.8648 -101.15 -49.0775 -75.8458 -101.2 -48.8589 -75.8265 -101.25 -48.6302 -75.8071 -101.3 -48.3903 -75.7874 -101.35 -48.1379 -75.7675 -101.4 -47.8717 -75.7473 -101.45 -47.5901 -75.727 -101.5 -47.2913 -75.7064 -101.55 -46.9731 -75.6856 -101.6 -46.6331 -75.6645 -101.65 -46.2684 -75.6432 -101.7 -45.8758 -75.6217 -101.75 -45.4513 -75.6 -101.8 -44.9903 -75.578 -101.85 -44.4872 -75.5558 -101.9 -43.9356 -75.5334 -101.95 -43.3275 -75.5108 -102 -42.6533 -75.4879 -102.05 -41.9017 -75.4647 -102.1 -41.0583 -75.4414 -102.15 -40.106 -75.4178 -102.2 -39.0236 -75.3939 -102.25 -37.7849 -75.3699 -102.3 -36.3577 -75.3455 -102.35 -34.7026 -75.321 -102.4 -32.7717 -75.2962 -102.45 -30.5079 -75.2711 -102.5 -27.8457 -75.2458 -102.55 -24.714 -75.2202 -102.6 -21.0449 -75.1944 -102.65 -16.7893 -75.1683 -102.7 -11.9448 -75.142 -102.75 -6.59099 -75.1153 -102.8 -0.924909 -75.0884 -102.85 4.73208 -75.0612 -102.9 9.97893 -75.0337 -102.95 14.4299 -75.0059 -103 17.814 -74.9777 -103.05 20.0262 -74.9492 -103.1 21.1117 -74.9204 -103.15 21.2134 -74.8911 -103.2 20.5136 -74.8614 -103.25 19.1944 -74.8313 -103.3 17.4161 -74.8007 -103.35 15.3103 -74.7695 -103.4 12.9807 -74.7377 -103.45 10.5065 -74.7052 -103.5 7.94774 -74.6719 -103.55 5.34885 -74.6376 -103.6 2.74265 -74.6022 -103.65 0.153011 -74.5655 -103.7 -2.403 -74.5271 -103.75 -4.91343 -74.4868 -103.8 -7.37018 -74.4442 -103.85 -9.7681 -74.3987 -103.9 -12.1042 -74.3497 -103.95 -14.3772 -74.2965 -104 -16.5871 -74.2381 -104.05 -18.7348 -74.1733 -104.1 -20.8222 -74.1007 -104.15 -22.8519 -74.0186 -104.2 -24.8271 -73.925 -104.25 -26.7517 -73.8171 -104.3 -28.6303 -73.692 -104.35 -30.468 -73.5458 -104.4 -32.2709 -73.374 -104.45 -34.0452 -73.1712 -104.5 -35.798 -72.9305 -104.55 -37.5365 -72.644 -104.6 -39.268 -72.3019 -104.65 -40.9998 -71.8924 -104.7 -42.7384 -71.4013 -104.75 -44.489 -70.8113 -104.8 -46.255 -70.1017 -104.85 -48.0371 -69.2474 -104.9 -49.8321 -68.2177 -104.95 -51.6324 -66.9757 -105 -53.4246 -65.4761 -105.05 -55.1904 -63.6636 -105.1 -56.9063 -61.4697 -105.15 -58.5461 -58.8083 -105.2 -60.0832 -55.5691 -105.25 -61.4943 -51.6058 -105.3 -62.7622 -46.7165 -105.35 -63.878 -40.6078 -105.4 -64.8412 -32.8403 -105.45 -65.6588 -22.7788 -105.5 -66.3431 -9.72179 -105.55 -66.909 6.26738 -105.6 -67.3725 22.6966 -105.65 -67.7489 35.2271 -105.7 -68.0519 42.0241 -105.75 -68.2936 44.6682 -105.8 -68.4841 45.2261 -105.85 -68.632 44.8625 -105.9 -68.7441 44.051 -105.95 -68.8264 42.959 -106 -68.8835 41.6468 -106.05 -68.9195 40.1415 -106.1 -68.9374 38.4612 -106.15 -68.9401 36.6227 -106.2 -68.9298 34.6433 -106.25 -68.9084 32.5405 -106.3 -68.8774 30.3321 -106.35 -68.8381 28.0355 -106.4 -68.7918 25.6675 -106.45 -68.7393 23.2438 -106.5 -68.6815 20.7786 -106.55 -68.619 18.285 -106.6 -68.5524 15.7744 -106.65 -68.4823 13.2567 -106.7 -68.409 10.7404 -106.75 -68.333 8.23258 -106.8 -68.2545 5.73893 -106.85 -68.1738 3.26402 -106.9 -68.0912 0.811326 -106.95 -68.0069 -1.61671 -107 -67.921 -4.01848 -107.05 -67.8336 -6.39316 -107.1 -67.7451 -8.74077 -107.15 -67.6553 -11.0618 -107.2 -67.5645 -13.3577 -107.25 -67.4727 -15.6304 -107.3 -67.3801 -17.8827 -107.35 -67.2866 -20.1184 -107.4 -67.1923 -22.3426 -107.45 -67.0974 -24.5622 -107.5 -67.0018 -26.7855 -107.55 -66.9056 -29.0238 -107.6 -66.8088 -31.2915 -107.65 -66.7114 -33.6067 -107.7 -66.6136 -35.9917 -107.75 -66.5153 -38.4736 -107.8 -66.4165 -41.0838 -107.85 -66.3173 -43.8565 -107.9 -66.2177 -46.8248 -107.95 -66.1177 -50.0131 -108 -66.0174 -53.4233 -108.05 -65.9167 -57.0157 -108.1 -65.8156 -60.6883 -108.15 -65.7143 -64.2676 -108.2 -65.6127 -67.5338 -108.25 -65.5108 -70.2872 -108.3 -65.4086 -72.4241 -108.35 -65.3062 -73.9637 -108.4 -65.2036 -75.0113 -108.45 -65.1007 -75.6978 -108.5 -64.9976 -76.1385 -108.55 -64.8943 -76.4192 -108.6 -64.7908 -76.598 -108.65 -64.6872 -76.7125 -108.7 -64.5834 -76.7862 -108.75 -64.4794 -76.8339 -108.8 -64.3753 -76.865 -108.85 -64.2711 -76.8852 -108.9 -64.1667 -76.8984 -108.95 -64.0623 -76.9068 -109 -63.9577 -76.912 -109.05 -63.8531 -76.9151 -109.1 -63.7483 -76.9166 -109.15 -63.6435 -76.9172 -109.2 -63.5387 -76.917 -109.25 -63.4338 -76.9162 -109.3 -63.3288 -76.9151 -109.35 -63.2238 -76.9137 -109.4 -63.1188 -76.912 -109.45 -63.0138 -76.9102 -109.5 -62.9088 -76.9082 -109.55 -62.8037 -76.9062 -109.6 -62.6987 -76.904 -109.65 -62.5937 -76.9017 -109.7 -62.4887 -76.8994 -109.75 -62.3838 -76.8969 -109.8 -62.2789 -76.8944 -109.85 -62.174 -76.8919 -109.9 -62.0692 -76.8892 -109.95 -61.9644 -76.8865 -110 -61.8597 -76.8838 -110.05 -61.7551 -76.8809 -110.1 -61.6506 -76.878 -110.15 -61.5461 -76.8751 -110.2 -61.4417 -76.8721 -110.25 -61.3374 -76.869 -110.3 -61.2333 -76.8658 -110.35 -61.1292 -76.8626 -110.4 -61.0252 -76.8593 -110.45 -60.9213 -76.856 -110.5 -60.8176 -76.8525 -110.55 -60.7139 -76.8491 -110.6 -60.6104 -76.8455 -110.65 -60.507 -76.8419 -110.7 -60.4038 -76.8381 -110.75 -60.3006 -76.8344 -110.8 -60.1976 -76.8305 -110.85 -60.0947 -76.8266 -110.9 -59.992 -76.8225 -110.95 -59.8894 -76.8184 -111 -59.7869 -76.8143 -111.05 -59.6846 -76.81 -111.1 -59.5824 -76.8056 -111.15 -59.4803 -76.8012 -111.2 -59.3784 -76.7967 -111.25 -59.2766 -76.7921 -111.3 -59.175 -76.7874 -111.35 -59.0734 -76.7826 -111.4 -58.972 -76.7777 -111.45 -58.8708 -76.7727 -111.5 -58.7696 -76.7677 -111.55 -58.6686 -76.7625 -111.6 -58.5677 -76.7572 -111.65 -58.4669 -76.7519 -111.7 -58.3663 -76.7464 -111.75 -58.2657 -76.7408 -111.8 -58.1652 -76.7351 -111.85 -58.0649 -76.7293 -111.9 -57.9646 -76.7235 -111.95 -57.8644 -76.7174 -112 -57.7643 -76.7113 -112.05 -57.6643 -76.7051 -112.1 -57.5643 -76.6987 -112.15 -57.4644 -76.6922 -112.2 -57.3646 -76.6857 -112.25 -57.2647 -76.6789 -112.3 -57.1649 -76.6721 -112.35 -57.0652 -76.6651 -112.4 -56.9654 -76.658 -112.45 -56.8657 -76.6508 -112.5 -56.7659 -76.6434 -112.55 -56.6662 -76.636 -112.6 -56.5664 -76.6283 -112.65 -56.4665 -76.6206 -112.7 -56.3666 -76.6127 -112.75 -56.2666 -76.6046 -112.8 -56.1666 -76.5964 -112.85 -56.0664 -76.5881 -112.9 -55.9661 -76.5796 -112.95 -55.8656 -76.571 -113 -55.7651 -76.5622 -113.05 -55.6643 -76.5532 -113.1 -55.5634 -76.5441 -113.15 -55.4622 -76.5349 -113.2 -55.3608 -76.5254 -113.25 -55.2591 -76.5159 -113.3 -55.1572 -76.5061 -113.35 -55.0549 -76.4962 -113.4 -54.9523 -76.4861 -113.45 -54.8494 -76.4759 -113.5 -54.746 -76.4655 -113.55 -54.6423 -76.4549 -113.6 -54.5381 -76.4441 -113.65 -54.4334 -76.4332 -113.7 -54.3281 -76.4221 -113.75 -54.2224 -76.4108 -113.8 -54.116 -76.3993 -113.85 -54.0089 -76.3876 -113.9 -53.9012 -76.3757 -113.95 -53.7928 -76.3637 -114 -53.6835 -76.3515 -114.05 -53.5734 -76.339 -114.1 -53.4625 -76.3264 -114.15 -53.3505 -76.3136 -114.2 -53.2376 -76.3006 -114.25 -53.1235 -76.2874 -114.3 -53.0083 -76.274 -114.35 -52.8919 -76.2604 -114.4 -52.7741 -76.2466 -114.45 -52.6549 -76.2326 -114.5 -52.5342 -76.2184 -114.55 -52.4119 -76.204 -114.6 -52.2878 -76.1894 -114.65 -52.1619 -76.1746 -114.7 -52.034 -76.1595 -114.75 -51.904 -76.1443 -114.8 -51.7718 -76.1288 -114.85 -51.6371 -76.1132 -114.9 -51.4998 -76.0973 -114.95 -51.3596 -76.0812 -115 -51.2165 -76.0649 -115.05 -51.07 -76.0484 -115.1 -50.9201 -76.0317 -115.15 -50.7664 -76.0147 -115.2 -50.6086 -75.9975 -115.25 -50.4463 -75.9801 -115.3 -50.2793 -75.9625 -115.35 -50.107 -75.9447 -115.4 -49.929 -75.9267 -115.45 -49.7448 -75.9084 -115.5 -49.5539 -75.8899 -115.55 -49.3556 -75.8712 -115.6 -49.1491 -75.8522 -115.65 -48.9338 -75.8331 -115.7 -48.7086 -75.8137 -115.75 -48.4726 -75.7941 -115.8 -48.2245 -75.7742 -115.85 -47.9631 -75.7542 -115.9 -47.6869 -75.7339 -115.95 -47.3941 -75.7134 -116 -47.0827 -75.6926 -116.05 -46.7503 -75.6716 -116.1 -46.3944 -75.6504 -116.15 -46.0116 -75.629 -116.2 -45.5983 -75.6074 -116.25 -45.1502 -75.5855 -116.3 -44.662 -75.5634 -116.35 -44.1275 -75.541 -116.4 -43.5394 -75.5184 -116.45 -42.8887 -75.4956 -116.5 -42.1646 -75.4726 -116.55 -41.3539 -75.4493 -116.6 -40.4406 -75.4258 -116.65 -39.4047 -75.402 -116.7 -38.2219 -75.378 -116.75 -36.8623 -75.3538 -116.8 -35.289 -75.3293 -116.85 -33.457 -75.3046 -116.9 -31.3124 -75.2796 -116.95 -28.7923 -75.2544 -117 -25.8269 -75.2289 -117.05 -22.3459 -75.2032 -117.1 -18.2914 -75.1772 -117.15 -13.6414 -75.1509 -117.2 -8.44376 -75.1243 -117.25 -2.85294 -75.0975 -117.3 2.84958 -75.0704 -117.35 8.28091 -75.043 -117.4 13.0379 -75.0153 -117.45 16.8021 -74.9872 -117.5 19.411 -74.9589 -117.55 20.8641 -74.9301 -117.6 21.2781 -74.901 -117.65 20.8276 -74.8715 -117.7 19.6981 -74.8415 -117.75 18.0584 -74.8111 -117.8 16.0502 -74.7801 -117.85 13.786 -74.7485 -117.9 11.353 -74.7163 -117.95 8.81714 -74.6832 -118 6.22759 -74.6493 -118.05 3.6208 -74.6143 -118.1 1.02337 -74.578 -118.15 -1.54555 -74.5402 -118.2 -4.07241 -74.5007 -118.25 -6.54798 -74.4589 -118.3 -8.96616 -74.4144 -118.35 -11.3233 -74.3667 -118.4 -13.6177 -74.315 -118.45 -15.8488 -74.2584 -118.5 -18.0173 -74.1959 -118.55 -20.1248 -74.1262 -118.6 -22.1736 -74.0475 -118.65 -24.1668 -73.958 -118.7 -26.108 -73.8552 -118.75 -28.0016 -73.7363 -118.8 -29.8525 -73.5977 -118.85 -31.6664 -73.4351 -118.9 -33.4496 -73.2434 -118.95 -35.2089 -73.0164 -119 -36.9513 -72.7463 -119.05 -38.6844 -72.4242 -119.1 -40.4154 -72.0388 -119.15 -42.151 -71.577 -119.2 -43.897 -71.0225 -119.25 -45.6577 -70.3559 -119.3 -47.4345 -69.5535 -119.35 -49.2257 -68.5867 -119.4 -51.0253 -67.4209 -119.45 -52.822 -66.0138 -119.5 -54.5991 -64.3138 -119.55 -56.3348 -62.2571 -119.6 -58.0033 -59.7643 -119.65 -59.5779 -56.7342 -119.7 -61.0338 -53.0344 -119.75 -62.3514 -48.4847 -119.8 -63.5189 -42.8277 -119.85 -64.5331 -35.6805 -119.9 -65.3987 -26.4751 -119.95 -66.1263 -14.4894 -120 -66.7304 0.635426 -120.05 -67.2267 17.3808 -120.1 -67.6308 31.6426 -120.15 -67.9571 40.3127 -120.2 -68.2183 44.0963 -120.25 -68.425 45.18 -120.3 -68.5864 45.0495 -120.35 -68.7099 44.3609 -120.4 -68.8017 43.3538 -120.45 -68.8668 42.112 -120.5 -68.9095 40.6695 -120.55 -68.9332 39.0464 -120.6 -68.9408 37.2594 -120.65 -68.9346 35.3255 -120.7 -68.9167 33.2623 -120.75 -68.8888 31.0875 -120.8 -68.8522 28.8188 -120.85 -68.8081 26.4731 -120.9 -68.7576 24.0665 -120.95 -68.7015 21.6137 -121 -68.6405 19.1284 -121.05 -68.5753 16.6223 -121.1 -68.5063 14.106 -121.15 -68.434 11.5884 -121.2 -68.3589 9.07697 -121.25 -68.2812 6.57797 -121.3 -68.2012 4.09629 -121.35 -68.1193 1.63579 -121.4 -68.0355 -0.800792 -121.45 -67.9501 -3.21153 -121.5 -67.8632 -5.59542 -121.55 -67.7751 -7.95213 -121.6 -67.6857 -10.282 -121.65 -67.5952 -12.5862 -121.7 -67.5038 -14.8664 -121.75 -67.4114 -17.1252 -121.8 -67.3182 -19.366 -121.85 -67.2242 -21.5935 -121.9 -67.1295 -23.8138 -121.95 -67.0341 -26.0347 -122 -66.9381 -28.2664 -122.05 -66.8415 -30.5224 -122.1 -66.7443 -32.8194 -122.15 -66.6466 -35.178 -122.2 -66.5485 -37.624 -122.25 -66.4498 -40.1872 -122.3 -66.3508 -42.9013 -122.35 -66.2513 -45.8002 -122.4 -66.1515 -48.9126 -122.45 -66.0512 -52.2499 -122.5 -65.9507 -55.7887 -122.55 -65.8497 -59.4502 -122.6 -65.7485 -63.0842 -122.65 -65.647 -66.481 -122.7 -65.5452 -69.425 -122.75 -65.4431 -71.7736 -122.8 -65.3408 -73.5059 -122.85 -65.2382 -74.7049 -122.9 -65.1354 -75.4989 -122.95 -65.0324 -76.0113 -123 -64.9292 -76.3383 -123.05 -64.8257 -76.5464 -123.1 -64.7222 -76.6794 -123.15 -64.6184 -76.7648 -123.2 -64.5145 -76.8201 -123.25 -64.4104 -76.856 -123.3 -64.3062 -76.8794 -123.35 -64.2019 -76.8946 -123.4 -64.0975 -76.9044 -123.45 -63.993 -76.9105 -123.5 -63.8884 -76.9142 -123.55 -63.7837 -76.9162 -123.6 -63.6789 -76.9171 -123.65 -63.574 -76.9171 -123.7 -63.4692 -76.9165 -123.75 -63.3642 -76.9155 -123.8 -63.2592 -76.9142 -123.85 -63.1542 -76.9126 -123.9 -63.0492 -76.9108 -123.95 -62.9442 -76.9089 -124 -62.8392 -76.9069 -124.05 -62.7341 -76.9047 -124.1 -62.6291 -76.9025 -124.15 -62.5241 -76.9002 -124.2 -62.4192 -76.8977 -124.25 -62.3142 -76.8953 -124.3 -62.2093 -76.8927 -124.35 -62.1045 -76.8901 -124.4 -61.9997 -76.8874 -124.45 -61.895 -76.8847 -124.5 -61.7904 -76.8819 -124.55 -61.6858 -76.879 -124.6 -61.5813 -76.8761 -124.65 -61.4769 -76.8731 -124.7 -61.3726 -76.87 -124.75 -61.2684 -76.8669 -124.8 -61.1643 -76.8637 -124.85 -61.0602 -76.8604 -124.9 -60.9563 -76.8571 -124.95 -60.8525 -76.8537 -125 -60.7489 -76.8502 -125.05 -60.6453 -76.8467 -125.1 -60.5419 -76.8431 -125.15 -60.4386 -76.8394 -125.2 -60.3354 -76.8356 -125.25 -60.2323 -76.8318 -125.3 -60.1294 -76.8279 -125.35 -60.0266 -76.8239 -125.4 -59.924 -76.8198 -125.45 -59.8215 -76.8157 -125.5 -59.7191 -76.8114 -125.55 -59.6168 -76.8071 -125.6 -59.5147 -76.8027 -125.65 -59.4128 -76.7982 -125.7 -59.3109 -76.7937 -125.75 -59.2092 -76.789 -125.8 -59.1076 -76.7842 -125.85 -59.0062 -76.7794 -125.9 -58.9049 -76.7744 -125.95 -58.8037 -76.7694 -126 -58.7027 -76.7643 -126.05 -58.6017 -76.759 -126.1 -58.5009 -76.7537 -126.15 -58.4002 -76.7483 -126.2 -58.2996 -76.7427 -126.25 -58.1991 -76.7371 -126.3 -58.0987 -76.7313 -126.35 -57.9984 -76.7255 -126.4 -57.8982 -76.7195 -126.45 -57.798 -76.7134 -126.5 -57.698 -76.7072 -126.55 -57.598 -76.7009 -126.6 -57.4981 -76.6944 -126.65 -57.3982 -76.6879 -126.7 -57.2984 -76.6812 -126.75 -57.1986 -76.6744 -126.8 -57.0988 -76.6675 -126.85 -56.9991 -76.6604 -126.9 -56.8993 -76.6533 -126.95 -56.7996 -76.6459 -127 -56.6998 -76.6385 -127.05 -56.6 -76.6309 -127.1 -56.5002 -76.6232 -127.15 -56.4003 -76.6153 -127.2 -56.3004 -76.6073 -127.25 -56.2003 -76.5992 -127.3 -56.1002 -76.5909 -127.35 -55.9999 -76.5825 -127.4 -55.8995 -76.5739 -127.45 -55.799 -76.5651 -127.5 -55.6983 -76.5563 -127.55 -55.5974 -76.5472 -127.6 -55.4963 -76.538 -127.65 -55.395 -76.5286 -127.7 -55.2934 -76.5191 -127.75 -55.1916 -76.5094 -127.8 -55.0894 -76.4996 -127.85 -54.987 -76.4896 -127.9 -54.8841 -76.4794 -127.95 -54.7809 -76.469 -128 -54.6773 -76.4585 -128.05 -54.5733 -76.4478 -128.1 -54.4687 -76.4369 -128.15 -54.3637 -76.4258 -128.2 -54.2581 -76.4146 -128.25 -54.1519 -76.4032 -128.3 -54.0451 -76.3916 -128.35 -53.9376 -76.3798 -128.4 -53.8294 -76.3678 -128.45 -53.7205 -76.3556 -128.5 -53.6107 -76.3433 -128.55 -53.5 -76.3307 -128.6 -53.3884 -76.318 -128.65 -53.2758 -76.305 -128.7 -53.1621 -76.2919 -128.75 -53.0473 -76.2786 -128.8 -52.9313 -76.265 -128.85 -52.814 -76.2513 -128.9 -52.6953 -76.2374 -128.95 -52.5751 -76.2232 -129 -52.4533 -76.2089 -129.05 -52.3298 -76.1943 -129.1 -52.2046 -76.1796 -129.15 -52.0774 -76.1646 -129.2 -51.9481 -76.1495 -129.25 -51.8166 -76.1341 -129.3 -51.6828 -76.1185 -129.35 -51.5463 -76.1027 -129.4 -51.4072 -76.0867 -129.45 -51.2651 -76.0704 -129.5 -51.1198 -76.054 -129.55 -50.9711 -76.0373 -129.6 -50.8187 -76.0204 -129.65 -50.6623 -76.0033 -129.7 -50.5015 -75.986 -129.75 -50.3361 -75.9685 -129.8 -50.1657 -75.9507 -129.85 -49.9897 -75.9328 -129.9 -49.8076 -75.9146 -129.95 -49.6191 -75.8961 -130 -49.4233 -75.8775 -130.05 -49.2197 -75.8586 -130.1 -49.0074 -75.8396 -130.15 -48.7856 -75.8202 -130.2 -48.5534 -75.8007 -130.25 -48.3096 -75.7809 -130.3 -48.0528 -75.761 -130.35 -47.7818 -75.7407 -130.4 -47.4948 -75.7203 -130.45 -47.1899 -75.6996 -130.5 -46.8649 -75.6787 -130.55 -46.5172 -75.6576 -130.6 -46.1438 -75.6363 -130.65 -45.7413 -75.6147 -130.7 -45.3055 -75.5929 -130.75 -44.8314 -75.5708 -130.8 -44.3133 -75.5486 -130.85 -43.7442 -75.5261 -130.9 -43.1157 -75.5033 -130.95 -42.4177 -75.4804 -131 -41.6379 -75.4572 -131.05 -40.7611 -75.4337 -131.1 -39.769 -75.41 -131.15 -38.6388 -75.3861 -131.2 -37.3426 -75.362 -131.25 -35.8459 -75.3376 -131.3 -34.1067 -75.3129 -131.35 -32.0741 -75.288 -131.4 -29.6881 -75.2629 -131.45 -26.8809 -75.2375 -131.5 -23.5812 -75.2119 -131.55 -19.7248 -75.186 -131.6 -15.2746 -75.1598 -131.65 -10.2503 -75.1333 -131.7 -4.76695 -75.1066 -131.75 0.936819 -75.0796 -131.8 6.50578 -75.0523 -131.85 11.532 -75.0247 -131.9 15.6576 -74.9967 -131.95 18.6636 -74.9685 -132 20.4979 -74.9399 -132.05 21.2444 -74.9109 -132.1 21.0644 -74.8815 -132.15 20.1437 -74.8517 -132.2 18.6588 -74.8214 -132.25 16.7608 -74.7906 -132.3 14.5721 -74.7593 -132.35 12.1877 -74.7272 -132.4 9.68022 -74.6945 -132.45 7.10412 -74.6609 -132.5 4.49973 -74.6262 -132.55 1.89668 -74.5904 -132.6 -0.683612 -74.5532 -132.65 -3.22588 -74.5142 -132.7 -5.71957 -74.4732 -132.75 -8.15761 -74.4297 -132.8 -10.5356 -74.3832 -132.85 -12.8513 -74.3329 -132.9 -15.1036 -74.2781 -132.95 -17.2931 -74.2177 -133 -19.421 -74.1506 -133.05 -21.4893 -74.0751 -133.1 -23.5008 -73.9895 -133.15 -25.459 -73.8915 -133.2 -27.3681 -73.7784 -133.25 -29.2328 -73.6469 -133.3 -31.0585 -73.4929 -133.35 -32.8513 -73.3117 -133.4 -34.6179 -73.0973 -133.45 -36.3652 -72.8427 -133.5 -38.1007 -72.5392 -133.55 -39.8316 -72.1766 -133.6 -41.5649 -71.7422 -133.65 -43.3069 -71.221 -133.7 -45.0623 -70.5945 -133.75 -46.8337 -69.8408 -133.8 -48.6205 -68.933 -133.85 -50.4183 -67.8386 -133.9 -52.2176 -66.5181 -133.95 -54.0035 -64.9233 -134 -55.7557 -62.9949 -134.05 -57.4499 -60.6592 -134.1 -59.0591 -57.8232 -134.15 -60.5575 -54.3665 -134.2 -61.9235 -50.1274 -134.25 -63.1425 -44.879 -134.3 -64.2082 -38.2874 -134.35 -65.1229 -29.8522 -134.4 -65.8956 -18.8829 -134.45 -66.5395 -4.78121 -134.5 -67.0704 11.7755 -134.55 -67.5039 27.383 -134.6 -67.855 38.036 -134.65 -68.1368 43.2263 -134.7 -68.3608 45.0032 -134.75 -68.5366 45.1762 -134.8 -68.6721 44.6357 -134.85 -68.7739 43.7221 -134.9 -68.8476 42.5542 -134.95 -68.8974 41.1769 -135 -68.9272 39.6127 -135.05 -68.9399 37.879 -135.1 -68.9381 35.9928 -135.15 -68.924 33.9712 -135.2 -68.8993 31.832 -135.25 -68.8654 29.593 -135.3 -68.8238 27.2714 -135.35 -68.7753 24.8836 -135.4 -68.721 22.4449 -135.45 -68.6616 19.9691 -135.5 -68.5977 17.4688 -135.55 -68.5299 14.9548 -135.6 -68.4587 12.4367 -135.65 -68.3845 9.92248 -135.7 -68.3077 7.41868 -135.75 -68.2284 4.93068 -135.8 -68.1471 2.46268 -135.85 -68.0639 0.0177784 -135.9 -67.9791 -2.40181 -135.95 -67.8927 -4.79484 -136 -67.8049 -7.16067 -136.05 -67.716 -9.49953 -136.1 -67.6259 -11.8122 -136.15 -67.5347 -14.1003 -136.2 -67.4427 -16.3659 -136.25 -67.3497 -18.6124 -136.3 -67.256 -20.8438 -136.35 -67.1615 -23.0656 -136.4 -67.0663 -25.2852 -136.45 -66.9705 -27.5121 -136.5 -66.8741 -29.7584 -136.55 -66.7771 -32.0393 -136.6 -66.6796 -34.3745 -136.65 -66.5816 -36.7879 -136.7 -66.4832 -39.308 -136.75 -66.3842 -41.9673 -136.8 -66.2849 -44.8003 -136.85 -66.1852 -47.8383 -136.9 -66.0851 -51.1001 -136.95 -65.9846 -54.5767 -137 -65.8838 -58.2099 -137.05 -65.7827 -61.8742 -137.1 -65.6813 -65.3765 -137.15 -65.5795 -68.4942 -137.2 -65.4776 -71.0522 -137.25 -65.3753 -72.9872 -137.3 -65.2728 -74.3526 -137.35 -65.1701 -75.2684 -137.4 -65.0671 -75.8635 -137.45 -64.964 -76.2441 -137.5 -64.8606 -76.4864 -137.55 -64.7571 -76.641 -137.6 -64.6534 -76.7401 -137.65 -64.5496 -76.804 -137.7 -64.4455 -76.8455 -137.75 -64.3414 -76.8726 -137.8 -64.2371 -76.8902 -137.85 -64.1327 -76.9015 -137.9 -64.0282 -76.9088 -137.95 -63.9237 -76.9132 -138 -63.819 -76.9157 -138.05 -63.7142 -76.9169 -138.1 -63.6094 -76.9172 -138.15 -63.5045 -76.9168 -138.2 -63.3996 -76.9159 -138.25 -63.2946 -76.9147 -138.3 -63.1896 -76.9132 -138.35 -63.0846 -76.9115 -138.4 -62.9796 -76.9096 -138.45 -62.8746 -76.9076 -138.5 -62.7695 -76.9055 -138.55 -62.6645 -76.9033 -138.6 -62.5595 -76.9009 -138.65 -62.4545 -76.8986 -138.7 -62.3496 -76.8961 -138.75 -62.2447 -76.8936 -138.8 -62.1399 -76.891 -138.85 -62.0351 -76.8883 -138.9 -61.9303 -76.8856 -138.95 -61.8257 -76.8828 -139 -61.7211 -76.88 -139.05 -61.6165 -76.8771 -139.1 -61.5121 -76.8741 -139.15 -61.4078 -76.8711 -139.2 -61.3035 -76.868 -139.25 -61.1994 -76.8648 -139.3 -61.0953 -76.8615 -139.35 -60.9914 -76.8582 -139.4 -60.8875 -76.8549 -139.45 -60.7838 -76.8514 -139.5 -60.6802 -76.8479 -139.55 -60.5767 -76.8443 -139.6 -60.4734 -76.8407 -139.65 -60.3702 -76.8369 -139.7 -60.2671 -76.8331 -139.75 -60.1641 -76.8292 -139.8 -60.0613 -76.8253 -139.85 -59.9586 -76.8212 -139.9 -59.856 -76.8171 -139.95 -59.7536 -76.8129 -140 -59.6513 -76.8086 -140.05 -59.5491 -76.8042 -140.1 -59.4471 -76.7998 -140.15 -59.3452 -76.7952 -140.2 -59.2435 -76.7906 -140.25 -59.1419 -76.7858 -140.3 -59.0404 -76.781 -140.35 -58.939 -76.7761 -140.4 -58.8378 -76.7711 -140.45 -58.7367 -76.766 -140.5 -58.6357 -76.7608 -140.55 -58.5349 -76.7555 -140.6 -58.4341 -76.7501 -140.65 -58.3335 -76.7446 -140.7 -58.233 -76.739 -140.75 -58.1325 -76.7333 -140.8 -58.0322 -76.7274 -140.85 -57.932 -76.7215 -140.9 -57.8318 -76.7155 -140.95 -57.7317 -76.7093 -141 -57.6317 -76.703 -141.05 -57.5318 -76.6966 -141.1 -57.4319 -76.6901 -141.15 -57.332 -76.6835 -141.2 -57.2322 -76.6767 -141.25 -57.1325 -76.6698 -141.3 -57.0327 -76.6628 -141.35 -56.933 -76.6557 -141.4 -56.8332 -76.6484 -141.45 -56.7335 -76.641 -141.5 -56.6337 -76.6335 -141.55 -56.5339 -76.6258 -141.6 -56.434 -76.618 -141.65 -56.3341 -76.61 -141.7 -56.2341 -76.602 -141.75 -56.1339 -76.5937 -141.8 -56.0337 -76.5853 -141.85 -55.9334 -76.5768 -141.9 -55.8329 -76.5681 -141.95 -55.7323 -76.5593 -142 -55.6315 -76.5503 -142.05 -55.5304 -76.5411 -142.1 -55.4292 -76.5318 -142.15 -55.3277 -76.5223 -142.2 -55.226 -76.5127 -142.25 -55.1239 -76.5029 -142.3 -55.0215 -76.493 -142.35 -54.9188 -76.4828 -142.4 -54.8158 -76.4725 -142.45 -54.7123 -76.462 -142.5 -54.6084 -76.4514 -142.55 -54.504 -76.4406 -142.6 -54.3992 -76.4296 -142.65 -54.2938 -76.4184 -142.7 -54.1878 -76.407 -142.75 -54.0812 -76.3955 -142.8 -53.9739 -76.3838 -142.85 -53.866 -76.3718 -142.9 -53.7573 -76.3597 -142.95 -53.6478 -76.3474 -143 -53.5374 -76.335 -143.05 -53.4261 -76.3223 -143.1 -53.3139 -76.3094 -143.15 -53.2006 -76.2963 -143.2 -53.0861 -76.2831 -143.25 -52.9705 -76.2696 -143.3 -52.8537 -76.256 -143.35 -52.7354 -76.2421 -143.4 -52.6158 -76.228 -143.45 -52.4946 -76.2137 -143.5 -52.3717 -76.1993 -143.55 -52.247 -76.1846 -143.6 -52.1205 -76.1697 -143.65 -51.992 -76.1546 -143.7 -51.8612 -76.1393 -143.75 -51.7282 -76.1238 -143.8 -51.5927 -76.108 -143.85 -51.4545 -76.0921 -143.9 -51.3134 -76.0759 -143.95 -51.1692 -76.0595 -144 -51.0216 -76.043 -144.05 -50.8705 -76.0262 -144.1 -50.7155 -76.0091 -144.15 -50.5563 -75.9919 -144.2 -50.3925 -75.9744 -144.25 -50.2238 -75.9567 -144.3 -50.0497 -75.9388 -144.35 -49.8697 -75.9207 -144.4 -49.6834 -75.9024 -144.45 -49.4902 -75.8838 -144.5 -49.2893 -75.865 -144.55 -49.08 -75.846 -144.6 -48.8616 -75.8268 -144.65 -48.633 -75.8073 -144.7 -48.3932 -75.7876 -144.75 -48.141 -75.7677 -144.8 -47.8749 -75.7476 -144.85 -47.5935 -75.7272 -144.9 -47.2949 -75.7066 -144.95 -46.9769 -75.6858 -145 -46.6372 -75.6648 -145.05 -46.2729 -75.6435 -145.1 -45.8806 -75.622 -145.15 -45.4565 -75.6003 -145.2 -44.996 -75.5783 -145.25 -44.4934 -75.5561 -145.3 -43.9424 -75.5337 -145.35 -43.335 -75.511 -145.4 -42.6617 -75.4881 -145.45 -41.911 -75.465 -145.5 -41.0689 -75.4417 -145.55 -40.118 -75.4181 -145.6 -39.0372 -75.3942 -145.65 -37.8006 -75.3701 -145.7 -36.3758 -75.3458 -145.75 -34.7237 -75.3213 -145.8 -32.7963 -75.2965 -145.85 -30.5368 -75.2714 -145.9 -27.8797 -75.2461 -145.95 -24.754 -75.2205 -146 -21.0915 -75.1947 -146.05 -16.843 -75.1686 -146.1 -12.0051 -75.1423 -146.15 -6.65649 -75.1156 -146.2 -0.992441 -75.0887 -146.25 4.66691 -75.0615 -146.3 9.92098 -75.034 -146.35 14.3832 -75.0062 -146.4 17.7809 -74.978 -146.45 20.0068 -74.9496 -146.5 21.105 -74.9207 -146.55 21.2172 -74.8915 -146.6 20.5258 -74.8618 -146.65 19.2129 -74.8317 -146.7 17.4392 -74.8011 -146.75 15.3367 -74.7699 -146.8 13.0091 -74.7381 -146.85 10.5363 -74.7056 -146.9 7.97823 -74.6723 -146.95 5.3796 -74.638 -147 2.77334 -74.6026 -147.05 0.183393 -74.5659 -147.1 -2.37309 -74.5276 -147.15 -4.88411 -74.4873 -147.2 -7.34154 -74.4447 -147.25 -9.74017 -74.3993 -147.3 -12.077 -74.3503 -147.35 -14.3508 -74.2972 -147.4 -16.5614 -74.2388 -147.45 -18.7098 -74.1741 -147.5 -20.7979 -74.1016 -147.55 -22.8282 -74.0197 -147.6 -24.8041 -73.9261 -147.65 -26.7293 -73.8185 -147.7 -28.6083 -73.6936 -147.75 -30.4466 -73.5477 -147.8 -32.2498 -73.3762 -147.85 -34.0244 -73.1738 -147.9 -35.7774 -72.9336 -147.95 -37.516 -72.6477 -148 -39.2476 -72.3063 -148.05 -40.9794 -71.8977 -148.1 -42.7178 -71.4076 -148.15 -44.4683 -70.8189 -148.2 -46.2341 -70.1109 -148.25 -48.016 -69.2584 -148.3 -49.8109 -68.231 -148.35 -51.6112 -66.9917 -148.4 -53.4036 -65.4955 -148.45 -55.1698 -63.6871 -148.5 -56.8864 -61.4981 -148.55 -58.5273 -58.8428 -148.6 -60.0658 -55.6112 -148.65 -61.4785 -51.6575 -148.7 -62.7482 -46.7806 -148.75 -63.8657 -40.6885 -148.8 -64.8307 -32.9439 -148.85 -65.65 -22.9139 -148.9 -66.3357 -9.89477 -148.95 -66.9029 6.06821 -149 -67.3676 22.5177 -149.05 -67.7449 35.1134 -149.1 -68.0487 41.9728 -149.15 -68.2911 44.6524 -149.2 -68.4821 45.2263 -149.25 -68.6304 44.8699 -149.3 -68.743 44.0623 -149.35 -68.8256 42.9732 -149.4 -68.883 41.6634 -149.45 -68.9192 40.1602 -149.5 -68.9373 38.4819 -149.55 -68.9402 36.6452 -149.6 -68.93 34.6673 -149.65 -68.9087 32.5659 -149.7 -68.8778 30.3586 -149.75 -68.8386 28.063 -149.8 -68.7924 25.6958 -149.85 -68.74 23.2726 -149.9 -68.6822 20.8078 -149.95 -68.6197 18.3145 -150 -68.5532 15.804 -150.05 -68.4831 13.2864 -150.1 -68.4099 10.77 -150.15 -68.3339 8.26203 -150.2 -68.2554 5.76818 -150.25 -68.1748 3.29303 -150.3 -68.0922 0.840051 -150.35 -68.0079 -1.58828 -150.4 -67.922 -3.99037 -150.45 -67.8347 -6.36537 -150.5 -67.7461 -8.71329 -150.55 -67.6564 -11.0347 -150.6 -67.5656 -13.3308 -150.65 -67.4738 -15.6037 -150.7 -67.3812 -17.8563 -150.75 -67.2877 -20.0921 -150.8 -67.1935 -22.3165 -150.85 -67.0985 -24.536 -150.9 -67.0029 -26.7593 -150.95 -66.9067 -28.9973 -151 -66.8099 -31.2645 -151.05 -66.7126 -33.579 -151.1 -66.6147 -35.9631 -151.15 -66.5164 -38.4437 -151.2 -66.4177 -41.0522 -151.25 -66.3185 -43.8228 -151.3 -66.2189 -46.7886 -151.35 -66.1189 -49.9741 -151.4 -66.0185 -53.3819 -151.45 -65.9179 -56.9726 -151.5 -65.8168 -60.6452 -151.55 -65.7155 -64.2268 -151.6 -65.6139 -67.4979 -151.65 -65.512 -70.2583 -151.7 -65.4098 -72.4026 -151.75 -65.3074 -73.9487 -151.8 -65.2048 -75.0013 -151.85 -65.1019 -75.6913 -151.9 -64.9988 -76.1343 -151.95 -64.8955 -76.4166 -152 -64.7921 -76.5964 -152.05 -64.6884 -76.7114 -152.1 -64.5846 -76.7855 -152.15 -64.4807 -76.8335 -152.2 -64.3766 -76.8647 -152.25 -64.2723 -76.8851 -152.3 -64.168 -76.8982 -152.35 -64.0635 -76.9067 -152.4 -63.9589 -76.9119 -152.45 -63.8543 -76.915 -152.5 -63.7496 -76.9166 -152.55 -63.6448 -76.9172 -152.6 -63.5399 -76.917 -152.65 -63.435 -76.9162 -152.7 -63.3301 -76.9151 -152.75 -63.2251 -76.9137 -152.8 -63.1201 -76.9121 -152.85 -63.015 -76.9102 -152.9 -62.91 -76.9083 -152.95 -62.805 -76.9062 -153 -62.7 -76.904 -153.05 -62.5949 -76.9017 -153.1 -62.49 -76.8994 -153.15 -62.385 -76.897 -153.2 -62.2801 -76.8945 -153.25 -62.1752 -76.8919 -153.3 -62.0704 -76.8892 -153.35 -61.9657 -76.8865 -153.4 -61.861 -76.8838 -153.45 -61.7563 -76.881 -153.5 -61.6518 -76.8781 -153.55 -61.5473 -76.8751 -153.6 -61.443 -76.8721 -153.65 -61.3387 -76.869 -153.7 -61.2345 -76.8659 -153.75 -61.1304 -76.8626 -153.8 -61.0264 -76.8594 -153.85 -60.9225 -76.856 -153.9 -60.8188 -76.8526 -153.95 -60.7152 -76.8491 -154 -60.6116 -76.8455 -154.05 -60.5082 -76.8419 -154.1 -60.405 -76.8382 -154.15 -60.3018 -76.8344 -154.2 -60.1988 -76.8305 -154.25 -60.096 -76.8266 -154.3 -59.9932 -76.8226 -154.35 -59.8906 -76.8185 -154.4 -59.7881 -76.8143 -154.45 -59.6858 -76.81 -154.5 -59.5836 -76.8057 -154.55 -59.4815 -76.8013 -154.6 -59.3796 -76.7968 -154.65 -59.2778 -76.7921 -154.7 -59.1762 -76.7875 -154.75 -59.0746 -76.7827 -154.8 -58.9732 -76.7778 -154.85 -58.872 -76.7728 -154.9 -58.7708 -76.7677 -154.95 -58.6698 -76.7626 -155 -58.5689 -76.7573 -155.05 -58.4681 -76.7519 -155.1 -58.3674 -76.7465 -155.15 -58.2669 -76.7409 -155.2 -58.1664 -76.7352 -155.25 -58.066 -76.7294 -155.3 -57.9658 -76.7235 -155.35 -57.8656 -76.7175 -155.4 -57.7655 -76.7114 -155.45 -57.6655 -76.7052 -155.5 -57.5655 -76.6988 -155.55 -57.4656 -76.6923 -155.6 -57.3657 -76.6857 -155.65 -57.2659 -76.679 -155.7 -57.1661 -76.6722 -155.75 -57.0664 -76.6652 -155.8 -56.9666 -76.6581 -155.85 -56.8669 -76.6509 -155.9 -56.7671 -76.6435 -155.95 -56.6674 -76.636 -156 -56.5676 -76.6284 -156.05 -56.4677 -76.6207 -156.1 -56.3678 -76.6127 -156.15 -56.2678 -76.6047 -156.2 -56.1677 -76.5965 -156.25 -56.0676 -76.5882 -156.3 -55.9673 -76.5797 -156.35 -55.8668 -76.5711 -156.4 -55.7662 -76.5623 -156.45 -55.6655 -76.5533 -156.5 -55.5645 -76.5442 -156.55 -55.4634 -76.535 -156.6 -55.362 -76.5256 -156.65 -55.2603 -76.516 -156.7 -55.1584 -76.5062 -156.75 -55.0561 -76.4963 -156.8 -54.9535 -76.4863 -156.85 -54.8506 -76.476 -156.9 -54.7473 -76.4656 -156.95 -54.6435 -76.455 -157 -54.5393 -76.4442 -157.05 -54.4346 -76.4333 -157.1 -54.3294 -76.4222 -157.15 -54.2236 -76.4109 -157.2 -54.1172 -76.3994 -157.25 -54.0102 -76.3877 -157.3 -53.9025 -76.3759 -157.35 -53.794 -76.3638 -157.4 -53.6848 -76.3516 -157.45 -53.5748 -76.3392 -157.5 -53.4638 -76.3266 -157.55 -53.3519 -76.3138 -157.6 -53.2389 -76.3008 -157.65 -53.1249 -76.2876 -157.7 -53.0097 -76.2742 -157.75 -52.8932 -76.2606 -157.8 -52.7755 -76.2468 -157.85 -52.6563 -76.2328 -157.9 -52.5356 -76.2186 -157.95 -52.4133 -76.2042 -158 -52.2893 -76.1896 -158.05 -52.1634 -76.1747 -158.1 -52.0356 -76.1597 -158.15 -51.9056 -76.1445 -158.2 -51.7733 -76.129 -158.25 -51.6387 -76.1134 -158.3 -51.5014 -76.0975 -158.35 -51.3613 -76.0814 -158.4 -51.2182 -76.0651 -158.45 -51.0718 -76.0486 -158.5 -50.9219 -76.0318 -158.55 -50.7682 -76.0149 -158.6 -50.6105 -75.9977 -158.65 -50.4483 -75.9803 -158.7 -50.2813 -75.9627 -158.75 -50.109 -75.9449 -158.8 -49.9311 -75.9269 -158.85 -49.747 -75.9086 -158.9 -49.5562 -75.8901 -158.95 -49.358 -75.8714 -159 -49.1516 -75.8525 -159.05 -48.9364 -75.8333 -159.1 -48.7113 -75.8139 -159.15 -48.4754 -75.7943 -159.2 -48.2275 -75.7745 -159.25 -47.9663 -75.7544 -159.3 -47.6903 -75.7341 -159.35 -47.3977 -75.7136 -159.4 -47.0865 -75.6929 -159.45 -46.7544 -75.6719 -159.5 -46.3987 -75.6507 -159.55 -46.0163 -75.6293 -159.6 -45.6034 -75.6076 -159.65 -45.1557 -75.5857 -159.7 -44.668 -75.5636 -159.75 -44.1341 -75.5413 -159.8 -43.5467 -75.5187 -159.85 -42.8968 -75.4959 -159.9 -42.1736 -75.4728 -159.95 -41.3641 -75.4496 -160 -40.452 -75.426 -160.05 -39.4177 -75.4023 -160.1 -38.2368 -75.3783 -160.15 -36.8795 -75.3541 -160.2 -35.309 -75.3296 -160.25 -33.4803 -75.3049 -160.3 -31.3398 -75.2799 -160.35 -28.8245 -75.2547 -160.4 -25.8648 -75.2292 -160.45 -22.3902 -75.2035 -160.5 -18.3426 -75.1775 -160.55 -13.6996 -75.1512 -160.6 -8.50773 -75.1247 -160.65 -2.92015 -75.0978 -160.7 2.78314 -75.0707 -160.75 8.22007 -75.0433 -160.8 12.9872 -75.0156 -160.85 16.7644 -74.9876 -160.9 19.3872 -74.9592 -160.95 20.8534 -74.9305 -161 21.2786 -74.9014 -161.05 20.8372 -74.8719 -161.1 19.7147 -74.8419 -161.15 18.0801 -74.8115 -161.2 16.0755 -74.7805 -161.25 13.8138 -74.7489 -161.3 11.3824 -74.7167 -161.35 8.84743 -74.6836 -161.4 6.25827 -74.6497 -161.45 3.65151 -74.6147 -161.5 1.05385 -74.5785 -161.55 -1.51549 -74.5407 -161.6 -4.04292 -74.5011 -161.65 -6.51913 -74.4594 -161.7 -8.93801 -74.4149 -161.75 -11.2959 -74.3673 -161.8 -13.591 -74.3156 -161.85 -15.8228 -74.2591 -161.9 -17.9921 -74.1967 -161.95 -20.1003 -74.127 -162 -22.1498 -74.0485 -162.05 -24.1436 -73.9591 -162.1 -26.0854 -73.8565 -162.15 -27.9795 -73.7378 -162.2 -29.8309 -73.5995 -162.25 -31.6453 -73.4372 -162.3 -33.4288 -73.2459 -162.35 -35.1883 -73.0193 -162.4 -36.9309 -72.7498 -162.45 -38.664 -72.4283 -162.5 -40.395 -72.0438 -162.55 -42.1305 -71.583 -162.6 -43.8764 -71.0297 -162.65 -45.6368 -70.3645 -162.7 -47.4134 -69.5638 -162.75 -49.2045 -68.5992 -162.8 -51.0041 -67.4359 -162.85 -52.8009 -66.032 -162.9 -54.5784 -64.3357 -162.95 -56.3147 -62.2837 -163 -57.9841 -59.7966 -163.05 -59.56 -56.7735 -163.1 -61.0174 -53.0825 -163.15 -62.3367 -48.5441 -163.2 -63.5061 -42.9021 -163.25 -64.5221 -35.7754 -163.3 -65.3893 -26.5984 -163.35 -66.1185 -14.6494 -163.4 -66.7239 0.441737 -163.45 -67.2214 17.1885 -163.5 -67.6265 31.5048 -163.55 -67.9537 40.2431 -163.6 -68.2155 44.0714 -163.65 -68.4229 45.1762 -163.7 -68.5847 45.055 -163.75 -68.7086 44.3711 -163.8 -68.8008 43.3671 -163.85 -68.8662 42.1278 -163.9 -68.9091 40.6876 -163.95 -68.933 39.0665 -164 -68.9408 37.2813 -164.05 -68.9348 35.3491 -164.1 -68.917 33.2873 -164.15 -68.8892 31.1137 -164.2 -68.8527 28.846 -164.25 -68.8087 26.5011 -164.3 -68.7583 24.0951 -164.35 -68.7022 21.6429 -164.4 -68.6413 19.1578 -164.45 -68.5761 16.6519 -164.5 -68.5071 14.1357 -164.55 -68.4349 11.618 -164.6 -68.3598 9.1065 -164.65 -68.2821 6.60732 -164.7 -68.2022 4.12542 -164.75 -68.1202 1.66465 -164.8 -68.0365 -0.772226 -164.85 -67.9511 -3.18328 -164.9 -67.8643 -5.56749 -164.95 -67.7761 -7.92452 -165 -67.6868 -10.2547 -165.05 -67.5963 -12.5592 -165.1 -67.5049 -14.8397 -165.15 -67.4125 -17.0987 -165.2 -67.3193 -19.3397 -165.25 -67.2253 -21.5673 -165.3 -67.1306 -23.7877 -165.35 -67.0352 -26.0085 -165.4 -66.9392 -28.24 -165.45 -66.8426 -30.4956 -165.5 -66.7455 -32.792 -165.55 -66.6478 -35.1498 -165.6 -66.5496 -37.5945 -165.65 -66.451 -40.1562 -165.7 -66.352 -42.8682 -165.75 -66.2525 -45.7648 -165.8 -66.1526 -48.8746 -165.85 -66.0524 -52.2092 -165.9 -65.9518 -55.7461 -165.95 -65.8509 -59.4068 -166 -65.7497 -63.0422 -166.05 -65.6482 -66.4432 -166.1 -65.5464 -69.3936 -166.15 -65.4443 -71.7495 -166.2 -65.342 -73.4888 -166.25 -65.2394 -74.6934 -166.3 -65.1366 -75.4914 -166.35 -65.0336 -76.0065 -166.4 -64.9304 -76.3352 -166.45 -64.827 -76.5445 -166.5 -64.7234 -76.6781 -166.55 -64.6196 -76.764 -166.6 -64.5157 -76.8196 -166.65 -64.4117 -76.8556 -166.7 -64.3075 -76.8791 -166.75 -64.2032 -76.8944 -166.8 -64.0987 -76.9043 -166.85 -63.9942 -76.9105 -166.9 -63.8896 -76.9142 -166.95 -63.7849 -76.9162 -167 -63.6801 -76.9171 -167.05 -63.5753 -76.9171 -167.1 -63.4704 -76.9165 -167.15 -63.3655 -76.9155 -167.2 -63.2605 -76.9142 -167.25 -63.1555 -76.9126 -167.3 -63.0505 -76.9109 -167.35 -62.9454 -76.9089 -167.4 -62.8404 -76.9069 -167.45 -62.7354 -76.9048 -167.5 -62.6304 -76.9025 -167.55 -62.5254 -76.9002 -167.6 -62.4204 -76.8978 -167.65 -62.3155 -76.8953 -167.7 -62.2106 -76.8928 -167.75 -62.1057 -76.8901 -167.8 -62.001 -76.8875 -167.85 -61.8963 -76.8847 -167.9 -61.7916 -76.8819 -167.95 -61.687 -76.8791 -168 -61.5825 -76.8761 -168.05 -61.4781 -76.8731 -168.1 -61.3738 -76.8701 -168.15 -61.2696 -76.8669 -168.2 -61.1655 -76.8637 -168.25 -61.0615 -76.8605 -168.3 -60.9576 -76.8571 -168.35 -60.8538 -76.8537 -168.4 -60.7501 -76.8503 -168.45 -60.6465 -76.8467 -168.5 -60.5431 -76.8431 -168.55 -60.4398 -76.8394 -168.6 -60.3366 -76.8357 -168.65 -60.2335 -76.8318 -168.7 -60.1306 -76.8279 -168.75 -60.0278 -76.8239 -168.8 -59.9252 -76.8199 -168.85 -59.8227 -76.8157 -168.9 -59.7203 -76.8115 -168.95 -59.618 -76.8072 -169 -59.5159 -76.8028 -169.05 -59.414 -76.7983 -169.1 -59.3121 -76.7937 -169.15 -59.2104 -76.789 -169.2 -59.1088 -76.7843 -169.25 -59.0074 -76.7794 -169.3 -58.9061 -76.7745 -169.35 -58.8049 -76.7695 -169.4 -58.7038 -76.7643 -169.45 -58.6029 -76.7591 -169.5 -58.5021 -76.7538 -169.55 -58.4014 -76.7483 -169.6 -58.3008 -76.7428 -169.65 -58.2003 -76.7371 -169.7 -58.0999 -76.7314 -169.75 -57.9996 -76.7255 -169.8 -57.8994 -76.7196 -169.85 -57.7992 -76.7135 -169.9 -57.6992 -76.7073 -169.95 -57.5992 -76.701 -170 -57.4993 -76.6945 -170.05 -57.3994 -76.688 -170.1 -57.2996 -76.6813 -170.15 -57.1998 -76.6745 -170.2 -57.1 -76.6676 -170.25 -57.0002 -76.6605 -170.3 -56.9005 -76.6533 -170.35 -56.8008 -76.646 -170.4 -56.701 -76.6386 -170.45 -56.6012 -76.631 -170.5 -56.5014 -76.6233 -170.55 -56.4015 -76.6154 -170.6 -56.3015 -76.6074 -170.65 -56.2015 -76.5993 -170.7 -56.1013 -76.591 -170.75 -56.0011 -76.5826 -170.8 -55.9007 -76.574 -170.85 -55.8002 -76.5652 -170.9 -55.6995 -76.5564 -170.95 -55.5986 -76.5473 -171 -55.4975 -76.5381 -171.05 -55.3962 -76.5288 -171.1 -55.2946 -76.5192 -171.15 -55.1928 -76.5095 -171.2 -55.0906 -76.4997 -171.25 -54.9882 -76.4897 -171.3 -54.8853 -76.4795 -171.35 -54.7822 -76.4691 -171.4 -54.6785 -76.4586 -171.45 -54.5745 -76.4479 -171.5 -54.47 -76.437 -171.55 -54.3649 -76.426 -171.6 -54.2594 -76.4147 -171.65 -54.1532 -76.4033 -171.7 -54.0464 -76.3917 -171.75 -53.9389 -76.3799 -171.8 -53.8307 -76.3679 -171.85 -53.7217 -76.3558 -171.9 -53.612 -76.3434 -171.95 -53.5013 -76.3309 -172 -53.3897 -76.3181 -172.05 -53.2771 -76.3052 -172.1 -53.1635 -76.292 -172.15 -53.0487 -76.2787 -172.2 -52.9326 -76.2652 -172.25 -52.8153 -76.2515 -172.3 -52.6967 -76.2375 -172.35 -52.5765 -76.2234 -172.4 -52.4548 -76.2091 -172.45 -52.3313 -76.1945 -172.5 -52.2061 -76.1798 -172.55 -52.0789 -76.1648 -172.6 -51.9496 -76.1496 -172.65 -51.8182 -76.1343 -172.7 -51.6844 -76.1187 -172.75 -51.548 -76.1029 -172.8 -51.4088 -76.0868 -172.85 -51.2668 -76.0706 -172.9 -51.1215 -76.0542 -172.95 -50.9728 -76.0375 -173 -50.8205 -76.0206 -173.05 -50.6641 -76.0035 -173.1 -50.5035 -75.9862 -173.15 -50.3381 -75.9687 -173.2 -50.1677 -75.9509 -173.25 -49.9918 -75.933 -173.3 -49.8098 -75.9148 -173.35 -49.6213 -75.8964 -173.4 -49.4257 -75.8777 -173.45 -49.2221 -75.8589 -173.5 -49.01 -75.8398 -173.55 -48.7883 -75.8205 -173.6 -48.5562 -75.8009 -173.65 -48.3125 -75.7812 -173.7 -48.0559 -75.7612 -173.75 -47.7851 -75.741 -173.8 -47.4983 -75.7205 -173.85 -47.1936 -75.6999 -173.9 -46.8688 -75.679 -173.95 -46.5214 -75.6579 -174 -46.1484 -75.6365 -174.05 -45.7462 -75.6149 -174.1 -45.3108 -75.5931 -174.15 -44.8372 -75.5711 -174.2 -44.3197 -75.5488 -174.25 -43.7512 -75.5263 -174.3 -43.1235 -75.5036 -174.35 -42.4264 -75.4806 -174.4 -41.6476 -75.4574 -174.45 -40.7721 -75.434 -174.5 -39.7814 -75.4103 -174.55 -38.653 -75.3864 -174.6 -37.359 -75.3623 -174.65 -35.8649 -75.3379 -174.7 -34.1288 -75.3132 -174.75 -32.1 -75.2883 -174.8 -29.7186 -75.2632 -174.85 -26.9167 -75.2378 -174.9 -23.6232 -75.2122 -174.95 -19.7737 -75.1863 -175 -15.3304 -75.1601 -175.05 -10.3125 -75.1336 -175.1 -4.8334 -75.1069 -175.15 0.869647 -75.0799 -175.2 6.44256 -75.0526 -175.25 11.4774 -75.025 -175.3 15.6153 -74.9971 -175.35 18.635 -74.9688 -175.4 20.4829 -74.9402 -175.45 21.2414 -74.9112 -175.5 21.0712 -74.8819 -175.55 20.1582 -74.852 -175.6 18.679 -74.8218 -175.65 16.7851 -74.791 -175.7 14.5991 -74.7596 -175.75 12.2166 -74.7276 -175.8 9.71025 -74.6949 -175.85 7.13469 -74.6613 -175.9 4.53045 -74.6266 -175.95 1.92724 -74.5908 -176 -0.653413 -74.5536 -176.05 -3.1962 -74.5147 -176.1 -5.6905 -74.4737 -176.15 -8.12923 -74.4303 -176.2 -10.508 -74.3837 -176.25 -12.8243 -74.3335 -176.3 -15.0775 -74.2788 -176.35 -17.2677 -74.2185 -176.4 -19.3963 -74.1514 -176.45 -21.4653 -74.0761 -176.5 -23.4774 -73.9906 -176.55 -25.4363 -73.8928 -176.6 -27.3459 -73.7799 -176.65 -29.211 -73.6486 -176.7 -31.0372 -73.4949 -176.75 -32.8304 -73.314 -176.8 -34.5972 -73.1001 -176.85 -36.3448 -72.846 -176.9 -38.0803 -72.5431 -176.95 -39.8112 -72.1812 -177 -41.5445 -71.7478 -177.05 -43.2863 -71.2277 -177.1 -45.0415 -70.6026 -177.15 -46.8127 -69.8505 -177.2 -48.5994 -68.9447 -177.25 -50.3971 -67.8527 -177.3 -52.1964 -66.5352 -177.35 -53.9826 -64.9439 -177.4 -55.7354 -63.0198 -177.45 -57.4303 -60.6894 -177.5 -59.0407 -57.86 -177.55 -60.5406 -54.4114 -177.6 -61.9083 -50.1827 -177.65 -63.129 -44.9479 -177.7 -64.1965 -38.3746 -177.75 -65.113 -29.9649 -177.8 -65.8873 -19.0298 -177.85 -66.5326 -4.9653 -177.9 -67.0647 11.5769 -177.95 -67.4993 27.2227 -178 -67.8513 37.9452 -178.05 -68.1338 43.1895 -178.1 -68.3585 44.9942 -178.15 -68.5348 45.1793 -178.2 -68.6707 44.6446 -178.25 -68.7729 43.7344 -178.3 -68.8468 42.5692 -178.35 -68.8969 41.1942 -178.4 -68.9269 39.6321 -178.45 -68.9398 37.9004 -178.5 -68.9382 36.0158 -178.55 -68.9242 33.9957 -178.6 -68.8996 31.8578 -178.65 -68.8659 29.6199 -178.7 -68.8243 27.2991 -178.75 -68.7759 24.912 -178.8 -68.7217 22.4738 -178.85 -68.6623 19.9984 -178.9 -68.5985 17.4983 -178.95 -68.5308 14.9844 -179 -68.4596 12.4663 -179.05 -68.3854 9.95198 -179.1 -68.3086 7.44803 -179.15 -68.2294 4.95981 -179.2 -68.1481 2.49156 -179.25 -68.0649 0.0463673 -179.3 -67.9801 -2.37353 -179.35 -67.8937 -4.76687 -179.4 -67.806 -7.13303 -179.45 -67.717 -9.4722 -179.5 -67.6269 -11.7852 -179.55 -67.5358 -14.0735 -179.6 -67.4437 -16.3394 -179.65 -67.3508 -18.5861 -179.7 -67.2571 -20.8177 -179.75 -67.1626 -23.0396 -179.8 -67.0674 -25.2591 -179.85 -66.9716 -27.4859 -179.9 -66.8752 -29.7318 -179.95 -66.7783 -32.0122 -180 -66.6808 -34.3466 -180.05 -66.5828 -36.759 -180.1 -66.4843 -39.2776 -180.15 -66.3854 -41.9351 -180.2 -66.2861 -44.7658 -180.25 -66.1864 -47.8012 -180.3 -66.0863 -51.0604 -180.35 -65.9858 -54.5347 -180.4 -65.885 -58.1666 -180.45 -65.7839 -61.8316 -180.5 -65.6825 -65.3371 -180.55 -65.5807 -68.4605 -180.6 -65.4788 -71.0257 -180.65 -65.3765 -72.9679 -180.7 -65.274 -74.3395 -180.75 -65.1713 -75.2597 -180.8 -65.0684 -75.8579 -180.85 -64.9652 -76.2406 -180.9 -64.8619 -76.4842 -180.95 -64.7583 -76.6396 -181 -64.6546 -76.7392 -181.05 -64.5508 -76.8034 -181.1 -64.4468 -76.8452 -181.15 -64.3426 -76.8723 -181.2 -64.2384 -76.89 -181.25 -64.134 -76.9014 -181.3 -64.0295 -76.9087 -181.35 -63.9249 -76.9132 -181.4 -63.8202 -76.9157 -181.45 -63.7155 -76.9169 -181.5 -63.6106 -76.9172 -181.55 -63.5058 -76.9168 -181.6 -63.4008 -76.9159 -181.65 -63.2959 -76.9147 -181.7 -63.1909 -76.9132 -181.75 -63.0859 -76.9115 -181.8 -62.9808 -76.9096 -181.85 -62.8758 -76.9076 -181.9 -62.7708 -76.9055 -181.95 -62.6658 -76.9033 -182 -62.5608 -76.901 -182.05 -62.4558 -76.8986 -182.1 -62.3508 -76.8961 -182.15 -62.2459 -76.8936 -182.2 -62.1411 -76.891 -182.25 -62.0363 -76.8884 -182.3 -61.9316 -76.8857 -182.35 -61.8269 -76.8829 -182.4 -61.7223 -76.88 -182.45 -61.6178 -76.8771 -182.5 -61.5133 -76.8741 -182.55 -61.409 -76.8711 -182.6 -61.3047 -76.868 -182.65 -61.2006 -76.8648 -182.7 -61.0965 -76.8616 -182.75 -60.9926 -76.8583 -182.8 -60.8887 -76.8549 -182.85 -60.785 -76.8515 -182.9 -60.6814 -76.8479 -182.95 -60.578 -76.8444 -183 -60.4746 -76.8407 -183.05 -60.3714 -76.837 -183.1 -60.2683 -76.8332 -183.15 -60.1653 -76.8293 -183.2 -60.0625 -76.8253 -183.25 -59.9598 -76.8213 -183.3 -59.8572 -76.8171 -183.35 -59.7548 -76.8129 -183.4 -59.6525 -76.8086 -183.45 -59.5503 -76.8043 -183.5 -59.4483 -76.7998 -183.55 -59.3464 -76.7953 -183.6 -59.2447 -76.7906 -183.65 -59.1431 -76.7859 -183.7 -59.0416 -76.7811 -183.75 -58.9402 -76.7762 -183.8 -58.839 -76.7712 -183.85 -58.7379 -76.7661 -183.9 -58.6369 -76.7609 -183.95 -58.5361 -76.7556 -184 -58.4353 -76.7502 -184.05 -58.3347 -76.7447 -184.1 -58.2341 -76.7391 -184.15 -58.1337 -76.7333 -184.2 -58.0334 -76.7275 -184.25 -57.9331 -76.7216 -184.3 -57.833 -76.7155 -184.35 -57.7329 -76.7094 -184.4 -57.6329 -76.7031 -184.45 -57.533 -76.6967 -184.5 -57.4331 -76.6902 -184.55 -57.3332 -76.6836 -184.6 -57.2334 -76.6768 -184.65 -57.1336 -76.6699 -184.7 -57.0339 -76.6629 -184.75 -56.9341 -76.6558 -184.8 -56.8344 -76.6485 -184.85 -56.7346 -76.6411 -184.9 -56.6349 -76.6336 -184.95 -56.535 -76.6259 -185 -56.4352 -76.6181 -185.05 -56.3352 -76.6101 -185.1 -56.2352 -76.602 -185.15 -56.1351 -76.5938 -185.2 -56.0349 -76.5854 -185.25 -55.9346 -76.5769 -185.3 -55.8341 -76.5682 -185.35 -55.7335 -76.5594 -185.4 -55.6326 -76.5504 -185.45 -55.5316 -76.5412 -185.5 -55.4304 -76.5319 -185.55 -55.3289 -76.5225 -185.6 -55.2272 -76.5128 -185.65 -55.1251 -76.503 -185.7 -55.0228 -76.4931 -185.75 -54.9201 -76.4829 -185.8 -54.817 -76.4726 -185.85 -54.7135 -76.4622 -185.9 -54.6096 -76.4515 -185.95 -54.5053 -76.4407 -186 -54.4004 -76.4297 -186.05 -54.295 -76.4185 -186.1 -54.189 -76.4072 -186.15 -54.0824 -76.3956 -186.2 -53.9752 -76.3839 -186.25 -53.8673 -76.372 -186.3 -53.7586 -76.3599 -186.35 -53.6491 -76.3476 -186.4 -53.5387 -76.3351 -186.45 -53.4275 -76.3224 -186.5 -53.3152 -76.3096 -186.55 -53.2019 -76.2965 -186.6 -53.0875 -76.2832 -186.65 -52.9719 -76.2698 -186.7 -52.8551 -76.2561 -186.75 -52.7368 -76.2422 -186.8 -52.6172 -76.2282 -186.85 -52.496 -76.2139 -186.9 -52.3731 -76.1994 -186.95 -52.2485 -76.1848 -187 -52.122 -76.1699 -187.05 -51.9935 -76.1548 -187.1 -51.8628 -76.1395 -187.15 -51.7298 -76.1239 -187.2 -51.5943 -76.1082 -187.25 -51.4561 -76.0923 -187.3 -51.315 -76.0761 -187.35 -51.1709 -76.0597 -187.4 -51.0234 -76.0432 -187.45 -50.8723 -76.0264 -187.5 -50.7173 -76.0093 -187.55 -50.5582 -75.9921 -187.6 -50.3945 -75.9746 -187.65 -50.2258 -75.957 -187.7 -50.0518 -75.9391 -187.75 -49.8719 -75.9209 -187.8 -49.6857 -75.9026 -187.85 -49.4925 -75.884 -187.9 -49.2917 -75.8652 -187.95 -49.0826 -75.8462 -188 -48.8642 -75.827 -188.05 -48.6358 -75.8075 -188.1 -48.3961 -75.7879 -188.15 -48.144 -75.768 -188.2 -47.8782 -75.7478 -188.25 -47.5969 -75.7275 -188.3 -47.2985 -75.7069 -188.35 -46.9808 -75.6861 -188.4 -46.6414 -75.665 -188.45 -46.2773 -75.6437 -188.5 -45.8854 -75.6222 -188.55 -45.4617 -75.6005 -188.6 -45.0016 -75.5786 -188.65 -44.4996 -75.5564 -188.7 -43.9492 -75.5339 -188.75 -43.3425 -75.5113 -188.8 -42.6701 -75.4884 -188.85 -41.9204 -75.4653 -188.9 -41.0794 -75.4419 -188.95 -40.1299 -75.4183 -189 -39.0508 -75.3945 -189.05 -37.8162 -75.3704 -189.1 -36.3938 -75.3461 -189.15 -34.7446 -75.3216 -189.2 -32.8208 -75.2968 -189.25 -30.5656 -75.2717 -189.3 -27.9136 -75.2464 -189.35 -24.7938 -75.2208 -189.4 -21.138 -75.195 -189.45 -16.8966 -75.1689 -189.5 -12.0654 -75.1426 -189.55 -6.72189 -75.116 -189.6 -1.05992 -75.089 -189.65 4.60174 -75.0618 -189.7 9.86298 -75.0343 -189.75 14.3364 -75.0065 -189.8 17.7476 -74.9784 -189.85 19.9874 -74.9499 -189.9 21.0981 -74.921 -189.95 21.2209 -74.8918 -190 20.5379 -74.8621 -190.05 19.2314 -74.832 -190.1 17.4623 -74.8014 -190.15 15.3629 -74.7703 -190.2 13.0376 -74.7385 -190.25 10.5661 -74.706 -190.3 8.00869 -74.6727 -190.35 5.41033 -74.6384 -190.4 2.80401 -74.6031 -190.45 0.213751 -74.5663 -190.5 -2.34321 -74.528 -190.55 -4.85482 -74.4878 -190.6 -7.31291 -74.4452 -190.65 -9.71226 -74.3998 -190.7 -12.0498 -74.3509 -190.75 -14.3243 -74.2978 -190.8 -16.5357 -74.2395 -190.85 -18.6848 -74.1749 -190.9 -20.7736 -74.1025 -190.95 -22.8046 -74.0207 -191 -24.7811 -73.9273 -191.05 -26.7068 -73.8198 -191.1 -28.5864 -73.6951 -191.15 -30.4251 -73.5495 -191.2 -32.2287 -73.3784 -191.25 -34.0036 -73.1763 -191.3 -35.7568 -72.9367 -191.35 -37.4956 -72.6513 -191.4 -39.2272 -72.3107 -191.45 -40.9589 -71.9029 -191.5 -42.6973 -71.4139 -191.55 -44.4475 -70.8265 -191.6 -46.2132 -70.12 -191.65 -47.9949 -69.2694 -191.7 -49.7897 -68.2443 -191.75 -51.59 -67.0077 -191.8 -53.3826 -65.5148 -191.85 -55.1492 -63.7105 -191.9 -56.8666 -61.5265 -191.95 -58.5085 -58.8772 -192 -60.0483 -55.6532 -192.05 -61.4626 -51.7091 -192.1 -62.7341 -46.8445 -192.15 -63.8535 -40.7689 -192.2 -64.8202 -33.0471 -192.25 -65.6411 -23.0483 -192.3 -66.3283 -10.0672 -192.35 -66.8969 5.86934 -192.4 -67.3626 22.3384 -192.45 -67.7409 34.9991 -192.5 -68.0455 41.9209 -192.55 -68.2885 44.6364 -192.6 -68.4801 45.2264 -192.65 -68.6289 44.8773 -192.7 -68.7418 44.0736 -192.75 -68.8248 42.9874 -192.8 -68.8824 41.68 -192.85 -68.9188 40.179 -192.9 -68.9372 38.5026 -192.95 -68.9402 36.6677 -193 -68.9302 34.6914 -193.05 -68.909 32.5912 -193.1 -68.8782 30.3851 -193.15 -68.8391 28.0904 -193.2 -68.793 25.7239 -193.25 -68.7406 23.3013 -193.3 -68.6829 20.837 -193.35 -68.6205 18.3439 -193.4 -68.554 15.8336 -193.45 -68.484 13.316 -193.5 -68.4108 10.7996 -193.55 -68.3348 8.29143 -193.6 -68.2564 5.79738 -193.65 -68.1757 3.32199 -193.7 -68.0932 0.868733 -193.75 -68.0089 -1.5599 -193.8 -67.923 -3.9623 -193.85 -67.8357 -6.33762 -193.9 -67.7472 -8.68586 -193.95 -67.6574 -11.0075 -194 -67.5667 -13.3039 -194.05 -67.4749 -15.5771 -194.1 -67.3823 -17.8299 -194.15 -67.2888 -20.0659 -194.2 -67.1946 -22.2904 -194.25 -67.0996 -24.5099 -194.3 -67.004 -26.7331 -194.35 -66.9078 -28.9709 -194.4 -66.811 -31.2376 -194.45 -66.7137 -33.5515 -194.5 -66.6159 -35.9346 -194.55 -66.5176 -38.4138 -194.6 -66.4188 -41.0207 -194.65 -66.3196 -43.7891 -194.7 -66.22 -46.7525 -194.75 -66.1201 -49.9353 -194.8 -66.0197 -53.3406 -194.85 -65.919 -56.9296 -194.9 -65.818 -60.6021 -194.95 -65.7167 -64.186 -195 -65.6151 -67.4621 -195.05 -65.5132 -70.2293 -195.1 -65.411 -72.381 -195.15 -65.3086 -73.9336 -195.2 -65.206 -74.9913 -195.25 -65.1031 -75.6848 -195.3 -65 -76.1302 -195.35 -64.8968 -76.4139 -195.4 -64.7933 -76.5947 -195.45 -64.6896 -76.7103 -195.5 -64.5858 -76.7848 -195.55 -64.4819 -76.833 -195.6 -64.3778 -76.8644 -195.65 -64.2735 -76.8849 -195.7 -64.1692 -76.8981 -195.75 -64.0647 -76.9066 -195.8 -63.9602 -76.9119 -195.85 -63.8555 -76.915 -195.9 -63.7508 -76.9166 -195.95 -63.646 -76.9172 -196 -63.5412 -76.917 -196.05 -63.4362 -76.9162 -196.1 -63.3313 -76.9151 -196.15 -63.2263 -76.9137 -196.2 -63.1213 -76.9121 -196.25 -63.0163 -76.9103 -196.3 -62.9112 -76.9083 -196.35 -62.8062 -76.9062 -196.4 -62.7012 -76.904 -196.45 -62.5962 -76.9018 -196.5 -62.4912 -76.8994 -196.55 -62.3863 -76.897 -196.6 -62.2813 -76.8945 -196.65 -62.1765 -76.8919 -196.7 -62.0716 -76.8893 -196.75 -61.9669 -76.8866 -196.8 -61.8622 -76.8838 -196.85 -61.7576 -76.881 -196.9 -61.653 -76.8781 -196.95 -61.5486 -76.8751 -197 -61.4442 -76.8721 -197.05 -61.3399 -76.869 -197.1 -61.2357 -76.8659 -197.15 -61.1316 -76.8627 -197.2 -61.0276 -76.8594 -197.25 -60.9238 -76.856 -197.3 -60.82 -76.8526 -197.35 -60.7164 -76.8491 -197.4 -60.6129 -76.8456 -197.45 -60.5095 -76.8419 -197.5 -60.4062 -76.8382 -197.55 -60.3031 -76.8344 -197.6 -60.2 -76.8306 -197.65 -60.0972 -76.8266 -197.7 -59.9944 -76.8226 -197.75 -59.8918 -76.8185 -197.8 -59.7893 -76.8144 -197.85 -59.687 -76.8101 -197.9 -59.5848 -76.8058 -197.95 -59.4827 -76.8013 -198 -59.3808 -76.7968 -198.05 -59.279 -76.7922 -198.1 -59.1773 -76.7875 -198.15 -59.0758 -76.7827 -198.2 -58.9744 -76.7778 -198.25 -58.8731 -76.7729 -198.3 -58.772 -76.7678 -198.35 -58.671 -76.7626 -198.4 -58.5701 -76.7574 -198.45 -58.4693 -76.752 -198.5 -58.3686 -76.7465 -198.55 -58.2681 -76.741 -198.6 -58.1676 -76.7353 -198.65 -58.0672 -76.7295 -198.7 -57.967 -76.7236 -198.75 -57.8668 -76.7176 -198.8 -57.7667 -76.7115 -198.85 -57.6666 -76.7052 -198.9 -57.5667 -76.6989 -198.95 -57.4668 -76.6924 -199 -57.3669 -76.6858 -199.05 -57.2671 -76.6791 -199.1 -57.1673 -76.6723 -199.15 -57.0675 -76.6653 -199.2 -56.9678 -76.6582 -199.25 -56.868 -76.651 -199.3 -56.7683 -76.6436 -199.35 -56.6685 -76.6361 -199.4 -56.5687 -76.6285 -199.45 -56.4689 -76.6207 -199.5 -56.369 -76.6128 -199.55 -56.269 -76.6048 -199.6 -56.1689 -76.5966 -199.65 -56.0687 -76.5883 -199.7 -55.9684 -76.5798 -199.75 -55.868 -76.5712 -199.8 -55.7674 -76.5624 -199.85 -55.6667 -76.5534 -199.9 -55.5657 -76.5443 -199.95 -55.4646 -76.5351 -200 -55.3632 -76.5257 -200.05 -55.2615 -76.5161 -200.1 -55.1596 -76.5064 -200.15 -55.0573 -76.4965 -200.2 -54.9547 -76.4864 -200.25 -54.8518 -76.4761 -200.3 -54.7485 -76.4657 -200.35 -54.6447 -76.4551 -200.4 -54.5405 -76.4444 -200.45 -54.4358 -76.4334 -200.5 -54.3306 -76.4223 -200.55 -54.2249 -76.411 -200.6 -54.1185 -76.3995 -200.65 -54.0115 -76.3879 -200.7 -53.9038 -76.376 -200.75 -53.7953 -76.364 -200.8 -53.6861 -76.3518 -200.85 -53.5761 -76.3393 -200.9 -53.4651 -76.3267 -200.95 -53.3532 -76.3139 -201 -53.2403 -76.3009 -201.05 -53.1262 -76.2877 -201.1 -53.011 -76.2743 -201.15 -52.8946 -76.2607 -201.2 -52.7769 -76.247 -201.25 -52.6577 -76.233 -201.3 -52.5371 -76.2188 -201.35 -52.4148 -76.2043 -201.4 -52.2908 -76.1897 -201.45 -52.1649 -76.1749 -201.5 -52.0371 -76.1599 -201.55 -51.9071 -76.1447 -201.6 -51.7749 -76.1292 -201.65 -51.6403 -76.1135 -201.7 -51.503 -76.0977 -201.75 -51.363 -76.0816 -201.8 -51.2199 -76.0653 -201.85 -51.0735 -76.0488 -201.9 -50.9237 -76.032 -201.95 -50.7701 -76.0151 -202 -50.6124 -75.9979 -202.05 -50.4502 -75.9806 -202.1 -50.2833 -75.9629 -202.15 -50.1111 -75.9451 -202.2 -49.9333 -75.9271 -202.25 -49.7492 -75.9088 -202.3 -49.5585 -75.8903 -202.35 -49.3603 -75.8716 -202.4 -49.1541 -75.8527 -202.45 -48.939 -75.8335 -202.5 -48.714 -75.8141 -202.55 -48.4783 -75.7945 -202.6 -48.2305 -75.7747 -202.65 -47.9695 -75.7546 -202.7 -47.6936 -75.7344 -202.75 -47.4012 -75.7138 -202.8 -47.0903 -75.6931 -202.85 -46.7584 -75.6721 -202.9 -46.403 -75.6509 -202.95 -46.0209 -75.6295 -203 -45.6084 -75.6079 -203.05 -45.1612 -75.586 -203.1 -44.674 -75.5639 -203.15 -44.1407 -75.5415 -203.2 -43.554 -75.519 -203.25 -42.9049 -75.4962 -203.3 -42.1826 -75.4731 -203.35 -41.3742 -75.4498 -203.4 -40.4634 -75.4263 -203.45 -39.4307 -75.4026 -203.5 -38.2517 -75.3786 -203.55 -36.8967 -75.3543 -203.6 -35.3289 -75.3299 -203.65 -33.5035 -75.3052 -203.7 -31.367 -75.2802 -203.75 -28.8565 -75.255 -203.8 -25.9025 -75.2295 -203.85 -22.4343 -75.2038 -203.9 -18.3938 -75.1778 -203.95 -13.7577 -75.1515 -204 -8.5716 -75.125 -204.05 -2.98729 -75.0982 -204.1 2.71672 -75.0711 -204.15 8.1592 -75.0437 -204.2 12.9363 -75.0159 -204.25 16.7264 -74.9879 -204.3 19.3631 -74.9595 -204.35 20.8425 -74.9308 -204.4 21.279 -74.9017 -204.45 20.8468 -74.8722 -204.5 19.7312 -74.8422 -204.55 18.1018 -74.8118 -204.6 16.1008 -74.7809 -204.65 13.8416 -74.7493 -204.7 11.4118 -74.717 -204.75 8.87767 -74.684 -204.8 6.28892 -74.6501 -204.85 3.6822 -74.6151 -204.9 1.0843 -74.5789 -204.95 -1.48546 -74.5412 -205 -4.01344 -74.5016 -205.05 -6.4903 -74.4599 -205.1 -8.90988 -74.4155 -205.15 -11.2685 -74.3678 -205.2 -13.5644 -74.3163 -205.25 -15.7969 -74.2598 -205.3 -17.9669 -74.1975 -205.35 -20.0758 -74.1279 -205.4 -22.126 -74.0495 -205.45 -24.1205 -73.9602 -205.5 -26.0629 -73.8578 -205.55 -27.9575 -73.7393 -205.6 -29.8094 -73.6012 -205.65 -31.6241 -73.4393 -205.7 -33.4079 -73.2483 -205.75 -35.1677 -73.0222 -205.8 -36.9104 -72.7532 -205.85 -38.6436 -72.4324 -205.9 -40.3746 -72.0487 -205.95 -42.11 -71.5889 -206 -43.8557 -71.0368 -206.05 -45.616 -70.373 -206.1 -47.3924 -69.5741 -206.15 -49.1834 -68.6116 -206.2 -50.9829 -67.4509 -206.25 -52.7799 -66.0501 -206.3 -54.5577 -64.3577 -206.35 -56.2946 -62.3103 -206.4 -57.965 -59.8288 -206.45 -59.5421 -56.8127 -206.5 -61.001 -53.1305 -206.55 -62.3221 -48.6034 -206.6 -63.4932 -42.9763 -206.65 -64.511 -35.87 -206.7 -65.3799 -26.7211 -206.75 -66.1106 -14.8087 -206.8 -66.7174 0.248479 -206.85 -67.2161 16.9961 -206.9 -67.6222 31.3664 -206.95 -67.9502 40.1729 -207 -68.2128 44.0461 -207.05 -68.4207 45.1723 -207.1 -68.5831 45.0605 -207.15 -68.7074 44.3813 -207.2 -68.7998 43.3804 -207.25 -68.8656 42.1436 -207.3 -68.9087 40.7056 -207.35 -68.9328 39.0865 -207.4 -68.9408 37.3032 -207.45 -68.9349 35.3726 -207.5 -68.9173 33.3122 -207.55 -68.8896 31.1399 -207.6 -68.8532 28.8731 -207.65 -68.8093 26.5291 -207.7 -68.7589 24.1237 -207.75 -68.7029 21.6719 -207.8 -68.642 19.1872 -207.85 -68.5769 16.6815 -207.9 -68.508 14.1653 -207.95 -68.4358 11.6476 -208 -68.3607 9.13597 -208.05 -68.2831 6.63661 -208.1 -68.2032 4.15448 -208.15 -68.1212 1.69345 -208.2 -68.0375 -0.743724 -208.25 -67.9521 -3.15509 -208.3 -67.8653 -5.53961 -208.35 -67.7772 -7.89697 -208.4 -67.6878 -10.2274 -208.45 -67.5974 -12.5322 -208.5 -67.5059 -14.813 -208.55 -67.4136 -17.0722 -208.6 -67.3204 -19.3134 -208.65 -67.2264 -21.5412 -208.7 -67.1317 -23.7616 -208.75 -67.0363 -25.9823 -208.8 -66.9403 -28.2136 -208.85 -66.8437 -30.4689 -208.9 -66.7466 -32.7647 -208.95 -66.6489 -35.1216 -209 -66.5508 -37.5651 -209.05 -66.4522 -40.1253 -209.1 -66.3531 -42.8353 -209.15 -66.2537 -45.7296 -209.2 -66.1538 -48.8367 -209.25 -66.0536 -52.1687 -209.3 -65.953 -55.7035 -209.35 -65.8521 -59.3635 -209.4 -65.7509 -63.0003 -209.45 -65.6494 -66.4054 -209.5 -65.5476 -69.3622 -209.55 -65.4455 -71.7255 -209.6 -65.3432 -73.4717 -209.65 -65.2406 -74.6818 -209.7 -65.1378 -75.4839 -209.75 -65.0348 -76.0017 -209.8 -64.9316 -76.3322 -209.85 -64.8282 -76.5425 -209.9 -64.7246 -76.6769 -209.95 -64.6209 -76.7632 -210 -64.5169 -76.819 -210.05 -64.4129 -76.8553 -210.1 -64.3087 -76.8789 -210.15 -64.2044 -76.8943 -210.2 -64.1 -76.9042 -210.25 -63.9954 -76.9104 -210.3 -63.8908 -76.9142 -210.35 -63.7861 -76.9162 -210.4 -63.6814 -76.9171 -210.45 -63.5765 -76.9171 -210.5 -63.4716 -76.9165 -210.55 -63.3667 -76.9155 -210.6 -63.2617 -76.9142 -210.65 -63.1567 -76.9126 -210.7 -63.0517 -76.9109 -210.75 -62.9467 -76.909 -210.8 -62.8416 -76.9069 -210.85 -62.7366 -76.9048 -210.9 -62.6316 -76.9025 -210.95 -62.5266 -76.9002 -211 -62.4216 -76.8978 -211.05 -62.3167 -76.8953 -211.1 -62.2118 -76.8928 -211.15 -62.107 -76.8902 -211.2 -62.0022 -76.8875 -211.25 -61.8975 -76.8848 -211.3 -61.7928 -76.882 -211.35 -61.6883 -76.8791 -211.4 -61.5838 -76.8762 -211.45 -61.4794 -76.8732 -211.5 -61.3751 -76.8701 -211.55 -61.2708 -76.867 -211.6 -61.1667 -76.8638 -211.65 -61.0627 -76.8605 -211.7 -60.9588 -76.8572 -211.75 -60.855 -76.8538 -211.8 -60.7513 -76.8503 -211.85 -60.6478 -76.8468 -211.9 -60.5443 -76.8432 -211.95 -60.441 -76.8395 -212 -60.3378 -76.8357 -212.05 -60.2348 -76.8319 -212.1 -60.1318 -76.828 -212.15 -60.029 -76.824 -212.2 -59.9264 -76.8199 -212.25 -59.8239 -76.8158 -212.3 -59.7215 -76.8115 -212.35 -59.6192 -76.8072 -212.4 -59.5171 -76.8028 -212.45 -59.4152 -76.7983 -212.5 -59.3133 -76.7938 -212.55 -59.2116 -76.7891 -212.6 -59.11 -76.7843 -212.65 -59.0086 -76.7795 -212.7 -58.9073 -76.7746 -212.75 -58.8061 -76.7695 -212.8 -58.705 -76.7644 -212.85 -58.6041 -76.7592 -212.9 -58.5033 -76.7538 -212.95 -58.4026 -76.7484 -213 -58.302 -76.7428 -213.05 -58.2015 -76.7372 -213.1 -58.1011 -76.7315 -213.15 -58.0007 -76.7256 -213.2 -57.9005 -76.7196 -213.25 -57.8004 -76.7135 -213.3 -57.7004 -76.7073 -213.35 -57.6004 -76.701 -213.4 -57.5004 -76.6946 -213.45 -57.4006 -76.688 -213.5 -57.3007 -76.6814 -213.55 -57.2009 -76.6746 -213.6 -57.1012 -76.6677 -213.65 -57.0014 -76.6606 -213.7 -56.9017 -76.6534 -213.75 -56.8019 -76.6461 -213.8 -56.7022 -76.6387 -213.85 -56.6024 -76.6311 -213.9 -56.5026 -76.6234 -213.95 -56.4027 -76.6155 -214 -56.3027 -76.6075 -214.05 -56.2027 -76.5994 -214.1 -56.1025 -76.5911 -214.15 -56.0023 -76.5827 -214.2 -55.9019 -76.5741 -214.25 -55.8014 -76.5654 -214.3 -55.7007 -76.5565 -214.35 -55.5998 -76.5474 -214.4 -55.4987 -76.5382 -214.45 -55.3974 -76.5289 -214.5 -55.2958 -76.5193 -214.55 -55.194 -76.5097 -214.6 -55.0918 -76.4998 -214.65 -54.9894 -76.4898 -214.7 -54.8866 -76.4796 -214.75 -54.7834 -76.4693 -214.8 -54.6798 -76.4587 -214.85 -54.5757 -76.448 -214.9 -54.4712 -76.4371 -214.95 -54.3662 -76.4261 -215 -54.2606 -76.4149 -215.05 -54.1544 -76.4034 -215.1 -54.0476 -76.3918 -215.15 -53.9402 -76.38 -215.2 -53.832 -76.3681 -215.25 -53.723 -76.3559 -215.3 -53.6133 -76.3436 -215.35 -53.5026 -76.331 -215.4 -53.391 -76.3183 -215.45 -53.2785 -76.3053 -215.5 -53.1648 -76.2922 -215.55 -53.05 -76.2789 -215.6 -52.934 -76.2654 -215.65 -52.8167 -76.2516 -215.7 -52.6981 -76.2377 -215.75 -52.5779 -76.2236 -215.8 -52.4562 -76.2092 -215.85 -52.3328 -76.1947 -215.9 -52.2076 -76.1799 -215.95 -52.0804 -76.165 -216 -51.9512 -76.1498 -216.05 -51.8197 -76.1344 -216.1 -51.6859 -76.1189 -216.15 -51.5496 -76.1031 -216.2 -51.4105 -76.087 -216.25 -51.2685 -76.0708 -216.3 -51.1232 -76.0544 -216.35 -50.9746 -76.0377 -216.4 -50.8223 -76.0208 -216.45 -50.666 -76.0037 -216.5 -50.5054 -75.9864 -216.55 -50.3401 -75.9689 -216.6 -50.1697 -75.9512 -216.65 -49.9939 -75.9332 -216.7 -49.812 -75.915 -216.75 -49.6236 -75.8966 -216.8 -49.428 -75.8779 -216.85 -49.2246 -75.8591 -216.9 -49.0125 -75.84 -216.95 -48.791 -75.8207 -217 -48.559 -75.8012 -217.05 -48.3154 -75.7814 -217.1 -48.059 -75.7614 -217.15 -47.7884 -75.7412 -217.2 -47.5018 -75.7208 -217.25 -47.1973 -75.7001 -217.3 -46.8728 -75.6792 -217.35 -46.5257 -75.6581 -217.4 -46.153 -75.6368 -217.45 -45.7511 -75.6152 -217.5 -45.3161 -75.5934 -217.55 -44.843 -75.5714 -217.6 -44.3261 -75.5491 -217.65 -43.7583 -75.5266 -217.7 -43.1313 -75.5039 -217.75 -42.435 -75.4809 -217.8 -41.6573 -75.4577 -217.85 -40.783 -75.4343 -217.9 -39.7939 -75.4106 -217.95 -38.6672 -75.3867 -218 -37.3753 -75.3625 -218.05 -35.8838 -75.3382 -218.1 -34.1508 -75.3135 -218.15 -32.1258 -75.2886 -218.2 -29.7489 -75.2635 -218.25 -26.9524 -75.2381 -218.3 -23.665 -75.2125 -218.35 -19.8224 -75.1866 -218.4 -15.3862 -75.1604 -218.45 -10.3746 -75.134 -218.5 -4.89978 -75.1072 -218.55 0.802514 -75.0802 -218.6 6.37931 -75.0529 -218.65 11.4228 -75.0253 -218.7 15.5728 -74.9974 -218.75 18.6063 -74.9691 -218.8 20.4677 -74.9405 -218.85 21.2382 -74.9116 -218.9 21.0779 -74.8822 -218.95 20.1726 -74.8524 -219 18.6991 -74.8221 -219.05 16.8093 -74.7914 -219.1 14.6262 -74.76 -219.15 12.2455 -74.728 -219.2 9.74024 -74.6953 -219.25 7.16524 -74.6617 -219.3 4.56115 -74.6271 -219.35 1.95779 -74.5913 -219.4 -0.623234 -74.5541 -219.45 -3.16653 -74.5152 -219.5 -5.66146 -74.4742 -219.55 -8.10086 -74.4308 -219.6 -10.4803 -74.3843 -219.65 -12.7974 -74.3341 -219.7 -15.0513 -74.2795 -219.75 -17.2423 -74.2192 -219.8 -19.3716 -74.1523 -219.85 -21.4412 -74.077 -219.9 -23.4541 -73.9917 -219.95 -25.4135 -73.894 -220 -27.3237 -73.7813 -220.05 -29.1893 -73.6502 -220.1 -31.0159 -73.4969 -220.15 -32.8095 -73.3163 -220.2 -34.5766 -73.1028 -220.25 -36.3243 -72.8492 -220.3 -38.0599 -72.547 -220.35 -39.7908 -72.1859 -220.4 -41.524 -71.7534 -220.45 -43.2657 -71.2344 -220.5 -45.0207 -70.6107 -220.55 -46.7918 -69.8602 -220.6 -48.5783 -68.9564 -220.65 -50.3759 -67.8668 -220.7 -52.1753 -66.5522 -220.75 -53.9617 -64.9644 -220.8 -55.715 -63.0447 -220.85 -57.4108 -60.7196 -220.9 -59.0224 -57.8966 -220.95 -60.5237 -54.4562 -221 -61.893 -50.2378 -221.05 -63.1155 -45.0165 -221.1 -64.1849 -38.4615 -221.15 -65.1031 -30.0771 -221.2 -65.8789 -19.176 -221.25 -66.5257 -5.14888 -221.3 -67.0591 11.3782 -221.35 -67.4947 27.0617 -221.4 -67.8475 37.8537 -221.45 -68.1309 43.1523 -221.5 -68.3561 44.9849 -221.55 -68.5329 45.1824 -221.6 -68.6693 44.6534 -221.65 -68.7719 43.7467 -221.7 -68.8461 42.5842 -221.75 -68.8965 41.2115 -221.8 -68.9267 39.6515 -221.85 -68.9398 37.9216 -221.9 -68.9383 36.0388 -221.95 -68.9244 34.0202 -222 -68.9 31.8836 -222.05 -68.8663 29.6467 -222.1 -68.8248 27.3269 -222.15 -68.7765 24.9404 -222.2 -68.7224 22.5027 -222.25 -68.663 20.0277 -222.3 -68.5993 17.5278 -222.35 -68.5316 15.014 -222.4 -68.4605 12.4959 -222.45 -68.3863 9.98151 -222.5 -68.3095 7.4774 -222.55 -68.2303 4.98897 -222.6 -68.1491 2.52047 -222.65 -68.0659 0.0749878 -222.7 -67.9811 -2.34522 -222.75 -67.8947 -4.73888 -222.8 -67.807 -7.10537 -222.85 -67.7181 -9.44484 -222.9 -67.628 -11.7582 -222.95 -67.5369 -14.0467 -223 -67.4448 -16.3129 -223.05 -67.3519 -18.5597 -223.1 -67.2582 -20.7915 -223.15 -67.1637 -23.0135 -223.2 -67.0686 -25.233 -223.25 -66.9728 -27.4596 -223.3 -66.8764 -29.7052 -223.35 -66.7794 -31.9852 -223.4 -66.6819 -34.3188 -223.45 -66.5839 -36.73 -223.5 -66.4855 -39.2472 -223.55 -66.3866 -41.9029 -223.6 -66.2872 -44.7314 -223.65 -66.1875 -47.7642 -223.7 -66.0874 -51.0208 -223.75 -65.987 -54.4927 -223.8 -65.8862 -58.1234 -223.85 -65.7851 -61.789 -223.9 -65.6837 -65.2976 -223.95 -65.5819 -68.4268 -224 -65.48 -70.9992 -224.05 -65.3777 -72.9486 -224.1 -65.2752 -74.3262 -224.15 -65.1725 -75.251 -224.2 -65.0696 -75.8523 -224.25 -64.9664 -76.237 -224.3 -64.8631 -76.4819 -224.35 -64.7596 -76.6381 -224.4 -64.6559 -76.7382 -224.45 -64.552 -76.8028 -224.5 -64.448 -76.8448 -224.55 -64.3439 -76.8721 -224.6 -64.2396 -76.8898 -224.65 -64.1352 -76.9013 -224.7 -64.0307 -76.9086 -224.75 -63.9261 -76.9131 -224.8 -63.8214 -76.9157 -224.85 -63.7167 -76.9169 -224.9 -63.6119 -76.9172 -224.95 -63.507 -76.9168 -225 -63.4021 -76.9159 -225.05 -63.2971 -76.9147 -225.1 -63.1921 -76.9132 -225.15 -63.0871 -76.9115 -225.2 -62.9821 -76.9096 -225.25 -62.877 -76.9076 -225.3 -62.772 -76.9055 -225.35 -62.667 -76.9033 -225.4 -62.562 -76.901 -225.45 -62.457 -76.8986 -225.5 -62.3521 -76.8962 -225.55 -62.2472 -76.8937 -225.6 -62.1423 -76.8911 -225.65 -62.0375 -76.8884 -225.7 -61.9328 -76.8857 -225.75 -61.8281 -76.8829 -225.8 -61.7235 -76.8801 -225.85 -61.619 -76.8771 -225.9 -61.5146 -76.8742 -225.95 -61.4102 -76.8711 -226 -61.306 -76.868 -226.05 -61.2018 -76.8649 -226.1 -61.0977 -76.8616 -226.15 -60.9938 -76.8583 -226.2 -60.89 -76.8549 -226.25 -60.7863 -76.8515 -226.3 -60.6827 -76.848 -226.35 -60.5792 -76.8444 -226.4 -60.4758 -76.8407 -226.45 -60.3726 -76.837 -226.5 -60.2695 -76.8332 -226.55 -60.1665 -76.8293 -226.6 -60.0637 -76.8253 -226.65 -59.961 -76.8213 -226.7 -59.8584 -76.8172 -226.75 -59.756 -76.813 -226.8 -59.6537 -76.8087 -226.85 -59.5516 -76.8043 -226.9 -59.4495 -76.7999 -226.95 -59.3476 -76.7953 -227 -59.2459 -76.7907 -227.05 -59.1443 -76.786 -227.1 -59.0428 -76.7811 -227.15 -58.9414 -76.7762 -227.2 -58.8402 -76.7712 -227.25 -58.7391 -76.7661 -227.3 -58.6381 -76.7609 -227.35 -58.5373 -76.7556 -227.4 -58.4365 -76.7502 -227.45 -58.3359 -76.7447 -227.5 -58.2353 -76.7391 -227.55 -58.1349 -76.7334 -227.6 -58.0346 -76.7276 -227.65 -57.9343 -76.7216 -227.7 -57.8342 -76.7156 -227.75 -57.7341 -76.7094 -227.8 -57.6341 -76.7032 -227.85 -57.5341 -76.6968 -227.9 -57.4342 -76.6903 -227.95 -57.3344 -76.6836 -228 -57.2346 -76.6769 -228.05 -57.1348 -76.67 -228.1 -57.0351 -76.663 -228.15 -56.9353 -76.6559 -228.2 -56.8356 -76.6486 -228.25 -56.7358 -76.6412 -228.3 -56.636 -76.6337 -228.35 -56.5362 -76.626 -228.4 -56.4364 -76.6182 -228.45 -56.3364 -76.6102 -228.5 -56.2364 -76.6021 -228.55 -56.1363 -76.5939 -228.6 -56.0361 -76.5855 -228.65 -55.9358 -76.577 -228.7 -55.8353 -76.5683 -228.75 -55.7346 -76.5595 -228.8 -55.6338 -76.5505 -228.85 -55.5328 -76.5413 -228.9 -55.4316 -76.532 -228.95 -55.3301 -76.5226 -229 -55.2284 -76.5129 -229.05 -55.1263 -76.5032 -229.1 -55.024 -76.4932 -229.15 -54.9213 -76.4831 -229.2 -54.8182 -76.4728 -229.25 -54.7147 -76.4623 -229.3 -54.6109 -76.4517 -229.35 -54.5065 -76.4408 -229.4 -54.4016 -76.4298 -229.45 -54.2963 -76.4187 -229.5 -54.1903 -76.4073 -229.55 -54.0837 -76.3958 -229.6 -53.9765 -76.384 -229.65 -53.8685 -76.3721 -229.7 -53.7599 -76.36 -229.75 -53.6504 -76.3477 -229.8 -53.54 -76.3353 -229.85 -53.4288 -76.3226 -229.9 -53.3165 -76.3097 -229.95 -53.2033 -76.2967 -230 -53.0889 -76.2834 -230.05 -52.9733 -76.2699 -230.1 -52.8564 -76.2563 -230.15 -52.7382 -76.2424 -230.2 -52.6186 -76.2284 -230.25 -52.4974 -76.2141 -230.3 -52.3746 -76.1996 -230.35 -52.25 -76.1849 -230.4 -52.1235 -76.17 -230.45 -51.995 -76.155 -230.5 -51.8643 -76.1396 -230.55 -51.7314 -76.1241 -230.6 -51.5959 -76.1084 -230.65 -51.4577 -76.0925 -230.7 -51.3167 -76.0763 -230.75 -51.1726 -76.0599 -230.8 -51.0251 -76.0434 -230.85 -50.8741 -76.0266 -230.9 -50.7192 -76.0095 -230.95 -50.5601 -75.9923 -231 -50.3964 -75.9748 -231.05 -50.2278 -75.9572 -231.1 -50.0538 -75.9393 -231.15 -49.8741 -75.9212 -231.2 -49.6879 -75.9028 -231.25 -49.4948 -75.8843 -231.3 -49.2941 -75.8655 -231.35 -49.0851 -75.8465 -231.4 -48.8668 -75.8272 -231.45 -48.6385 -75.8078 -231.5 -48.399 -75.7881 -231.55 -48.1471 -75.7682 -231.6 -47.8814 -75.7481 -231.65 -47.6004 -75.7277 -231.7 -47.3021 -75.7071 -231.75 -46.9847 -75.6863 -231.8 -46.6455 -75.6653 -231.85 -46.2818 -75.644 -231.9 -45.8902 -75.6225 -231.95 -45.4669 -75.6008 -232 -45.0073 -75.5788 -232.05 -44.5058 -75.5566 -232.1 -43.956 -75.5342 -232.15 -43.35 -75.5116 -232.2 -42.6784 -75.4887 -232.25 -41.9297 -75.4656 -232.3 -41.0899 -75.4422 -232.35 -40.1418 -75.4186 -232.4 -39.0644 -75.3948 -232.45 -37.8317 -75.3707 -232.5 -36.4118 -75.3464 -232.55 -34.7656 -75.3219 -232.6 -32.8453 -75.297 -232.65 -30.5944 -75.272 -232.7 -27.9474 -75.2467 -232.75 -24.8336 -75.2211 -232.8 -21.1844 -75.1953 -232.85 -16.95 -75.1692 -232.9 -12.1255 -75.1429 -232.95 -6.78719 -75.1163 -233 -1.12734 -75.0894 -233.05 4.53657 -75.0622 -233.1 9.80492 -75.0347 -233.15 14.2895 -75.0069 -233.2 17.7142 -74.9787 -233.25 19.9678 -74.9502 -233.3 21.0912 -74.9214 -233.35 21.2246 -74.8921 -233.4 20.5499 -74.8625 -233.45 19.2498 -74.8324 -233.5 17.4853 -74.8018 -233.55 15.3892 -74.7706 -233.6 13.0659 -74.7389 -233.65 10.5958 -74.7064 -233.7 8.03913 -74.6731 -233.75 5.44103 -74.6388 -233.8 2.83465 -74.6035 -233.85 0.24409 -74.5668 -233.9 -2.31334 -74.5285 -233.95 -4.82554 -74.4883 -234 -7.28429 -74.4457 -234.05 -9.68436 -74.4004 -234.1 -12.0227 -74.3515 -234.15 -14.2979 -74.2985 -234.2 -16.51 -74.2402 -234.25 -18.6599 -74.1757 -234.3 -20.7494 -74.1034 -234.35 -22.781 -74.0217 -234.4 -24.7581 -73.9285 -234.45 -26.6844 -73.8212 -234.5 -28.5645 -73.6967 -234.55 -30.4037 -73.5514 -234.6 -32.2076 -73.3806 -234.65 -33.9828 -73.1789 -234.7 -35.7363 -72.9397 -234.75 -37.4752 -72.655 -234.8 -39.2068 -72.315 -234.85 -40.9385 -71.9082 -234.9 -42.6767 -71.4202 -234.95 -44.4269 -70.8341 -235 -46.1923 -70.1291 -235.05 -47.9739 -69.2804 -235.1 -49.7685 -68.2575 -235.15 -51.5688 -67.0237 -235.2 -53.3616 -65.5341 -235.25 -55.1286 -63.7338 -235.3 -56.8467 -61.5547 -235.35 -58.4897 -58.9115 -235.4 -60.0309 -55.695 -235.45 -61.4468 -51.7604 -235.5 -62.72 -46.9081 -235.55 -63.8412 -40.849 -235.6 -64.8097 -33.1498 -235.65 -65.6323 -23.1823 -235.7 -66.321 -10.239 -235.75 -66.8908 5.67058 -235.8 -67.3577 22.1584 -235.85 -67.7369 34.8838 -235.9 -68.0423 41.8685 -235.95 -68.286 44.62 -236 -68.4782 45.2263 -236.05 -68.6274 44.8846 -236.1 -68.7407 44.0849 -236.15 -68.8239 43.0015 -236.2 -68.8819 41.6966 -236.25 -68.9185 40.1977 -236.3 -68.9371 38.5233 -236.35 -68.9403 36.6902 -236.4 -68.9304 34.7154 -236.45 -68.9093 32.6166 -236.5 -68.8786 30.4117 -236.55 -68.8397 28.1179 -236.6 -68.7935 25.7522 -236.65 -68.7413 23.3301 -236.7 -68.6836 20.8662 -236.75 -68.6213 18.3734 -236.8 -68.5548 15.8632 -236.85 -68.4848 13.3456 -236.9 -68.4116 10.8292 -236.95 -68.3357 8.32091 -237 -68.2573 5.82667 -237.05 -68.1767 3.35103 -237.1 -68.0942 0.897498 -237.15 -68.0099 -1.53143 -237.2 -67.924 -3.93416 -237.25 -67.8368 -6.30979 -237.3 -67.7482 -8.65835 -237.35 -67.6585 -10.9803 -237.4 -67.5677 -13.277 -237.45 -67.476 -15.5505 -237.5 -67.3834 -17.8035 -237.55 -67.2899 -20.0397 -237.6 -67.1957 -22.2642 -237.65 -67.1008 -24.4838 -237.7 -67.0052 -26.7068 -237.75 -66.909 -28.9444 -237.8 -66.8122 -31.2107 -237.85 -66.7149 -33.5238 -237.9 -66.6171 -35.906 -237.95 -66.5187 -38.384 -238 -66.42 -40.9891 -238.05 -66.3208 -43.7554 -238.1 -66.2212 -46.7163 -238.15 -66.1212 -49.8965 -238.2 -66.0209 -53.2993 -238.25 -65.9202 -56.8865 -238.3 -65.8192 -60.5589 -238.35 -65.7179 -64.1451 -238.4 -65.6163 -67.4261 -238.45 -65.5144 -70.2002 -238.5 -65.4122 -72.3592 -238.55 -65.3098 -73.9185 -238.6 -65.2072 -74.9812 -238.65 -65.1043 -75.6783 -238.7 -65.0012 -76.126 -238.75 -64.898 -76.4113 -238.8 -64.7945 -76.593 -238.85 -64.6909 -76.7092 -238.9 -64.5871 -76.7841 -238.95 -64.4831 -76.8326 -239 -64.379 -76.8641 -239.05 -64.2748 -76.8847 -239.1 -64.1704 -76.898 -239.15 -64.066 -76.9065 -239.2 -63.9614 -76.9119 -239.25 -63.8568 -76.915 -239.3 -63.752 -76.9166 -239.35 -63.6472 -76.9172 -239.4 -63.5424 -76.917 -239.45 -63.4375 -76.9163 -239.5 -63.3325 -76.9151 -239.55 -63.2275 -76.9137 -239.6 -63.1225 -76.9121 -239.65 -63.0175 -76.9103 -239.7 -62.9125 -76.9083 -239.75 -62.8075 -76.9062 -239.8 -62.7024 -76.9041 -239.85 -62.5974 -76.9018 -239.9 -62.4924 -76.8994 -239.95 -62.3875 -76.897 -240 -62.2826 -76.8945 -240.05 -62.1777 -76.8919 -240.1 -62.0729 -76.8893 -240.15 -61.9681 -76.8866 -240.2 -61.8634 -76.8839 -240.25 -61.7588 -76.881 -240.3 -61.6543 -76.8781 -240.35 -61.5498 -76.8752 -240.4 -61.4454 -76.8722 -240.45 -61.3411 -76.8691 -240.5 -61.2369 -76.8659 -240.55 -61.1328 -76.8627 -240.6 -61.0289 -76.8594 -240.65 -60.925 -76.8561 -240.7 -60.8212 -76.8527 -240.75 -60.7176 -76.8492 -240.8 -60.6141 -76.8456 -240.85 -60.5107 -76.842 -240.9 -60.4074 -76.8383 -240.95 -60.3043 -76.8345 -241 -60.2013 -76.8306 -241.05 -60.0984 -76.8267 -241.1 -59.9956 -76.8227 -241.15 -59.893 -76.8186 -241.2 -59.7905 -76.8144 -241.25 -59.6882 -76.8101 -241.3 -59.586 -76.8058 -241.35 -59.4839 -76.8014 -241.4 -59.382 -76.7969 -241.45 -59.2802 -76.7923 -241.5 -59.1785 -76.7876 -241.55 -59.077 -76.7828 -241.6 -58.9756 -76.7779 -241.65 -58.8743 -76.7729 -241.7 -58.7732 -76.7679 -241.75 -58.6722 -76.7627 -241.8 -58.5713 -76.7574 -241.85 -58.4705 -76.7521 -241.9 -58.3698 -76.7466 -241.95 -58.2692 -76.741 -242 -58.1688 -76.7353 -242.05 -58.0684 -76.7296 -242.1 -57.9681 -76.7237 -242.15 -57.8679 -76.7177 -242.2 -57.7678 -76.7115 -242.25 -57.6678 -76.7053 -242.3 -57.5678 -76.6989 -242.35 -57.4679 -76.6925 -242.4 -57.3681 -76.6859 -242.45 -57.2683 -76.6792 -242.5 -57.1685 -76.6723 -242.55 -57.0687 -76.6654 -242.6 -56.969 -76.6583 -242.65 -56.8692 -76.6511 -242.7 -56.7695 -76.6437 -242.75 -56.6697 -76.6362 -242.8 -56.5699 -76.6286 -242.85 -56.4701 -76.6208 -242.9 -56.3701 -76.6129 -242.95 -56.2702 -76.6049 -243 -56.1701 -76.5967 -243.05 -56.0699 -76.5884 -243.1 -55.9696 -76.5799 -243.15 -55.8692 -76.5713 -243.2 -55.7686 -76.5625 -243.25 -55.6679 -76.5535 -243.3 -55.5669 -76.5444 -243.35 -55.4658 -76.5352 -243.4 -55.3644 -76.5258 -243.45 -55.2627 -76.5162 -243.5 -55.1608 -76.5065 -243.55 -55.0585 -76.4966 -243.6 -54.956 -76.4865 -243.65 -54.853 -76.4763 -243.7 -54.7497 -76.4658 -243.75 -54.646 -76.4553 -243.8 -54.5418 -76.4445 -243.85 -54.4371 -76.4336 -243.9 -54.3319 -76.4225 -243.95 -54.2261 -76.4112 -244 -54.1197 -76.3997 -244.05 -54.0127 -76.388 -244.1 -53.905 -76.3762 -244.15 -53.7966 -76.3641 -244.2 -53.6874 -76.3519 -244.25 -53.5774 -76.3395 -244.3 -53.4664 -76.3269 -244.35 -53.3545 -76.3141 -244.4 -53.2416 -76.3011 -244.45 -53.1276 -76.2879 -244.5 -53.0124 -76.2745 -244.55 -52.896 -76.2609 -244.6 -52.7783 -76.2471 -244.65 -52.6591 -76.2331 -244.7 -52.5385 -76.2189 -244.75 -52.4162 -76.2045 -244.8 -52.2922 -76.1899 -244.85 -52.1664 -76.1751 -244.9 -52.0386 -76.1601 -244.95 -51.9087 -76.1448 -245 -51.7765 -76.1294 -245.05 -51.6419 -76.1137 -245.1 -51.5047 -76.0979 -245.15 -51.3646 -76.0818 -245.2 -51.2216 -76.0655 -245.25 -51.0753 -76.049 -245.3 -50.9255 -76.0322 -245.35 -50.7719 -76.0153 -245.4 -50.6142 -75.9981 -245.45 -50.4521 -75.9808 -245.5 -50.2853 -75.9632 -245.55 -50.1132 -75.9453 -245.6 -49.9354 -75.9273 -245.65 -49.7515 -75.909 -245.7 -49.5608 -75.8905 -245.75 -49.3627 -75.8718 -245.8 -49.1566 -75.8529 -245.85 -48.9415 -75.8337 -245.9 -48.7167 -75.8144 -245.95 -48.4811 -75.7948 -246 -48.2335 -75.7749 -246.05 -47.9726 -75.7549 -246.1 -47.697 -75.7346 -246.15 -47.4048 -75.7141 -246.2 -47.094 -75.6934 -246.25 -46.7625 -75.6724 -246.3 -46.4074 -75.6512 -246.35 -46.0256 -75.6298 -246.4 -45.6135 -75.6081 -246.45 -45.1667 -75.5863 -246.5 -44.68 -75.5641 -246.55 -44.1473 -75.5418 -246.6 -43.5612 -75.5192 -246.65 -42.9129 -75.4964 -246.7 -42.1916 -75.4734 -246.75 -41.3842 -75.4501 -246.8 -40.4748 -75.4266 -246.85 -39.4436 -75.4029 -246.9 -38.2666 -75.3789 -246.95 -36.9138 -75.3546 -247 -35.3487 -75.3302 -247.05 -33.5267 -75.3054 -247.1 -31.3942 -75.2805 -247.15 -28.8885 -75.2553 -247.2 -25.9401 -75.2298 -247.25 -22.4784 -75.2041 -247.3 -18.4448 -75.1781 -247.35 -13.8156 -75.1518 -247.4 -8.63536 -75.1253 -247.45 -3.05437 -75.0985 -247.5 2.6503 -75.0714 -247.55 8.09826 -75.044 -247.6 12.8853 -75.0163 -247.65 16.6884 -74.9882 -247.7 19.339 -74.9599 -247.75 20.8314 -74.9312 -247.8 21.2793 -74.9021 -247.85 20.8562 -74.8726 -247.9 19.7476 -74.8426 -247.95 18.1234 -74.8122 -248 16.1261 -74.7812 -248.05 13.8693 -74.7497 -248.1 11.4411 -74.7174 -248.15 8.90789 -74.6844 -248.2 6.31955 -74.6505 -248.25 3.71287 -74.6156 -248.3 1.11474 -74.5793 -248.35 -1.45544 -74.5416 -248.4 -3.98398 -74.5021 -248.45 -6.46148 -74.4604 -248.5 -8.88176 -74.416 -248.55 -11.2411 -74.3684 -248.6 -13.5377 -74.3169 -248.65 -15.771 -74.2605 -248.7 -17.9417 -74.1983 -248.75 -20.0513 -74.1288 -248.8 -22.1022 -74.0505 -248.85 -24.0973 -73.9614 -248.9 -26.0403 -73.8591 -248.95 -27.9355 -73.7408 -249 -29.7878 -73.603 -249.05 -31.6029 -73.4414 -249.1 -33.3871 -73.2508 -249.15 -35.1471 -73.0251 -249.2 -36.89 -72.7567 -249.25 -38.6233 -72.4365 -249.3 -40.3542 -72.0537 -249.35 -42.0895 -71.5948 -249.4 -43.8351 -71.0439 -249.45 -45.5952 -70.3816 -249.5 -47.3714 -69.5844 -249.55 -49.1622 -68.624 -249.6 -50.9617 -67.4659 -249.65 -52.7588 -66.0682 -249.7 -54.537 -64.3795 -249.75 -56.2745 -62.3367 -249.8 -57.9458 -59.8609 -249.85 -59.5241 -56.8518 -249.9 -60.9846 -53.1784 -249.95 -62.3074 -48.6625 -250 -63.4803 -43.0502 diff --git a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/cable_in_neuron.hoc b/tests/python/Rallpacks/moose_vs_neuron/rallpack3/cable_in_neuron.hoc deleted file mode 100644 index a285d8c0..00000000 --- a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/cable_in_neuron.hoc +++ /dev/null @@ -1,68 +0,0 @@ -/* This is a template file which is used by a python script to generate - * rallpack3 for various cable size. -*/ - -dia = 1.0 -len = 1.0 -incompts = 1000 -entire_len = incompts * len -runtime = 250.0 - -create cable -access cable -nseg = incompts - -/* -** Initialization routines -*/ - -cable {nseg=incompts L=entire_len diam=dia insert hh} - - -proc geometry() { - L = entire_len - diam = 1 - Ra = 100.0 -} - -proc membrane() { - insert hh - - ena = 50 - ek = -77 - el = -65 - gnabar = .12 - gkbar = .036 - gl_hh = 1 / 40000 - - cm = 1 -} - -/* -** Simulation and output of data -*/ - -proc run() { local io - geometry() - membrane() - v = -65.0 - t=0 - - m = m_hh - h = h_hh - n = n_hh - - dt = 0.05 - io = 0 - wopen("cable.out") - fstim(1) fstim(0, 0, 0, 251, .100) - fprint("%g %g %g\n", t, v(0.0005), v(0.9995)) - while (t < runtime) { - fadvance() - fprint("%g %g %g\n", t, v(0.0005), v(0.9995)) - } - wopen() -} - -finitialize() -run() diff --git a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/compare.hs b/tests/python/Rallpacks/moose_vs_neuron/rallpack3/compare.hs deleted file mode 100644 index f8d194ed..00000000 --- a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/compare.hs +++ /dev/null @@ -1,15 +0,0 @@ --- This haskell script compares data generated by NEURON and MOOSE. This is not --- a generic script. -import System.Environment -import qualified Data.Text.IO as IO -import qualified Data.Text as T - -txtToData text = map toFloat lines where - lines = T.lines text - -main = do - args <- getArgs - a <- mapM IO.readFile args - let r = map txtToData a - print r - putStrLn "Done" diff --git a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/compare.py b/tests/python/Rallpacks/moose_vs_neuron/rallpack3/compare.py deleted file mode 100755 index b1ef6ac7..00000000 --- a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/compare.py +++ /dev/null @@ -1,130 +0,0 @@ -# -*- coding: utf-8 -*- -""" -compare.py: Compare data generated by MOOSE and NEURON. - -Last modified: Wed May 28, 2014 02:48PM - -""" - -__author__ = "Dilawar Singh" -__copyright__ = "Copyright 2013, NCBS Bangalore" -__credits__ = ["NCBS Bangalore", "Bhalla Lab"] -__license__ = "GPL" -__version__ = "1.0.0" -__maintainer__ = "Dilawar Singh" -__email__ = "dilawars@ncbs.res.in" -__status__ = "Development" - -import os -import sys -from collections import defaultdict -import pylab -import numpy as np - -EPSILON = 1e-10 - -def findMaxima(y, x, filters=[], **kwargs): - """Find the location of peaks in data - - If type of peak is cap then - - """ - maximas = [] - index = [] - for i, a in enumerate(y[1:-1]): - if a > y[i] and a > y[i+2]: - # Check if point satisfies addtional condition. - insert = True - for f in filters: - if not f(a): - insert = False - break - if insert: - maximas.append(a) - index.append(x[i+1]) - return index, maximas - -def findMinima(y, x, filters=[], **kwargs): - """Find all minimas on the curve - """ - minimas = [] - index = [] - for i, a in enumerate(y[1:-1]): - if a > y[i] and a > y[i+2]: - # Check if point satisfies addtional condition. - insert = True - for f in filters: - if not f(a): - insert = False - break - if insert: - minimas.append(a) - index.append(i+1) - return index, minimas - -def compareData(x1, y1, x2, y2): - """Given two plots (x1, y1) and (x2, y2), Do some statistics on them - """ - - # First compare that there x-axis are same. else report warning. - x1 = np.array(x1) - x2 = np.array(x2) - y1 = np.array(y1) - y2 = np.array(y2) - - assert(len(x1) == len(x2)), "X axis must have equal no of entries" - for i, x in enumerate(x1): - msg = "Value mismatch in x-axis: {}-{} = {}".format(x, x2[i], x-x2[i]) - assert np.absolute(x - x2[i]) < EPSILON, msg - - # Good, now do a simple root-mean square test on both y-axis. - pylab.figure() - maximasY1 = findMaxima(y1, x1, filters=[(lambda x : x > 20) ]) - maximasY2 = findMaxima(y2, x2, filters=[(lambda x : x > 20) ]) - pylab.plot(maximasY1[0], maximasY1[1], '^') - pylab.plot(maximasY2[0], maximasY2[1], 'o') - pylab.show() - - -def compare(mooseData, nrnData, outputFile = None): - """Compare two data-vectors """ - mooseX, mooseY = mooseData - nrnX, nrnY = nrnData - mooseX = [ x * 1e3 for x in mooseX ] - for v in mooseY: - mooseY[v] = [ 1e3 * y for y in mooseY[v]] - for i, v in enumerate( mooseY ): - peaksY1 = compareData(mooseX, mooseY.values()[i], nrnX, nrnY.values()[i]) - print(peaksY1) - -def txtToData(txt): - """Convert text to data""" - vecX = [] - vecY = defaultdict(list) - for line in txt.split("\n"): - line = line.strip() - values = line.split() - if not values: - continue - vecX.append(float(values[0].strip())) - for i, v in enumerate(values[1:]): - v = v.strip() - vecY[i].append(float(v)) - return vecX, vecY - -def main(): - print("[INFO] Second file will be scaled by a factor of 1e3") - mooseFile = sys.argv[1] - nrnFile = sys.argv[2] - outputFile = None - if len(sys.argv) > 3: - outputFile = sys.argv[3] - - with open(mooseFile, "r") as f: - mooseData = txtToData(f.read()) - with open(nrnFile, "r") as f: - nrnData = txtToData(f.read()) - compare(mooseData, nrnData, outputFile) - -if __name__ == '__main__': - main() diff --git a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/data/cable.out b/tests/python/Rallpacks/moose_vs_neuron/rallpack3/data/cable.out deleted file mode 100644 index 8605a66e..00000000 --- a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/data/cable.out +++ /dev/null @@ -1,5001 +0,0 @@ -0 -65 -65 -0.05 -60.4369 -64.8419 -0.1 -58.0802 -64.6861 -0.15 -56.3003 -64.5326 -0.2 -54.8136 -64.3812 -0.25 -53.5128 -64.232 -0.3 -52.3437 -64.0846 -0.35 -51.2742 -63.9391 -0.4 -50.2831 -63.7954 -0.45 -49.3552 -63.6532 -0.5 -48.4792 -63.5125 -0.55 -47.6459 -63.3733 -0.6 -46.8476 -63.2354 -0.65 -46.078 -63.0988 -0.7 -45.3309 -62.9635 -0.75 -44.6012 -62.8292 -0.8 -43.8836 -62.6961 -0.85 -43.1734 -62.564 -0.9 -42.4659 -62.4328 -0.95 -41.7563 -62.3026 -1 -41.04 -62.1731 -1.05 -40.3124 -62.0445 -1.1 -39.5687 -61.9165 -1.15 -38.8039 -61.7892 -1.2 -38.0131 -61.6624 -1.25 -37.1911 -61.5362 -1.3 -36.3323 -61.4103 -1.35 -35.431 -61.2848 -1.4 -34.4814 -61.1596 -1.45 -33.4771 -61.0346 -1.5 -32.4118 -60.9096 -1.55 -31.2789 -60.7848 -1.6 -30.0718 -60.6598 -1.65 -28.784 -60.5347 -1.7 -27.4096 -60.4094 -1.75 -25.9433 -60.2838 -1.8 -24.381 -60.1578 -1.85 -22.7208 -60.0312 -1.9 -20.9631 -59.9041 -1.95 -19.1118 -59.7763 -2 -17.1754 -59.6477 -2.05 -15.1673 -59.5181 -2.1 -13.1072 -59.3875 -2.15 -11.0212 -59.2558 -2.2 -8.94198 -59.1228 -2.25 -6.90841 -58.9884 -2.3 -4.96454 -58.8525 -2.35 -3.15792 -58.7149 -2.4 -1.53741 -58.5754 -2.45 -0.15074 -58.4339 -2.5 0.958158 -58.2901 -2.55 1.7517 -58.144 -2.6 2.20089 -57.9952 -2.65 2.28705 -57.8435 -2.7 2.00298 -57.6888 -2.75 1.35335 -57.5305 -2.8 0.354302 -57.3684 -2.85 -0.967636 -57.2022 -2.9 -2.57727 -57.0314 -2.95 -4.43293 -56.8557 -3 -6.48893 -56.6743 -3.05 -8.69796 -56.4868 -3.1 -11.0134 -56.2924 -3.15 -13.3912 -56.0903 -3.2 -15.7914 -55.8796 -3.25 -18.1792 -55.6593 -3.3 -20.5254 -55.4281 -3.35 -22.8068 -55.1844 -3.4 -25.0062 -54.9266 -3.45 -27.1117 -54.6526 -3.5 -29.1168 -54.3598 -3.55 -31.0195 -54.0454 -3.6 -32.8218 -53.7059 -3.65 -34.5285 -53.3367 -3.7 -36.1471 -52.9326 -3.75 -37.6867 -52.4874 -3.8 -39.1572 -51.9929 -3.85 -40.5688 -51.4395 -3.9 -41.9315 -50.8149 -3.95 -43.2545 -50.1042 -4 -44.5457 -49.2885 -4.05 -45.8116 -48.344 -4.1 -47.0569 -47.2411 -4.15 -48.2844 -45.9422 -4.2 -49.4947 -44.4001 -4.25 -50.6864 -42.555 -4.3 -51.8558 -40.3328 -4.35 -52.9977 -37.6419 -4.4 -54.1051 -34.373 -4.45 -55.1704 -30.4023 -4.5 -56.1852 -25.6054 -4.55 -57.1421 -19.8884 -4.6 -58.0342 -13.247 -4.65 -58.8566 -5.85081 -4.7 -59.6062 1.88516 -4.75 -60.2819 9.32233 -4.8 -60.8847 15.767 -4.85 -61.4171 20.7035 -4.9 -61.883 23.9262 -4.95 -62.287 25.5071 -5 -62.6344 25.6753 -5.05 -62.9305 24.7074 -5.1 -63.1806 22.8654 -5.15 -63.3895 20.3742 -5.2 -63.5619 17.4194 -5.25 -63.7019 14.1513 -5.3 -63.8135 10.6901 -5.35 -63.8997 7.13063 -5.4 -63.9638 3.54588 -5.45 -64.0082 -0.00982931 -5.5 -64.0352 -3.49769 -5.55 -64.0469 -6.89163 -5.6 -64.0451 -10.1756 -5.65 -64.0312 -13.3415 -5.7 -64.0066 -16.3868 -5.75 -63.9725 -19.3138 -5.8 -63.9301 -22.1278 -5.85 -63.8801 -24.8374 -5.9 -63.8234 -27.4535 -5.95 -63.7608 -29.9897 -6 -63.6928 -32.4618 -6.05 -63.6201 -34.8883 -6.1 -63.5432 -37.2893 -6.15 -63.4624 -39.687 -6.2 -63.3782 -42.1041 -6.25 -63.291 -44.5627 -6.3 -63.2011 -47.082 -6.35 -63.1087 -49.675 -6.4 -63.0141 -52.3438 -6.45 -62.9176 -55.0741 -6.5 -62.8193 -57.8301 -6.55 -62.7195 -60.5516 -6.6 -62.6183 -63.1581 -6.65 -62.5159 -65.5617 -6.7 -62.4123 -67.686 -6.75 -62.3078 -69.4839 -6.8 -62.2025 -70.9466 -6.85 -62.0963 -72.098 -6.9 -61.9896 -72.9822 -6.95 -61.8822 -73.6496 -7 -61.7744 -74.148 -7.05 -61.6662 -74.5176 -7.1 -61.5576 -74.7902 -7.15 -61.4487 -74.9902 -7.2 -61.3396 -75.1358 -7.25 -61.2303 -75.2406 -7.3 -61.1209 -75.3145 -7.35 -61.0114 -75.365 -7.4 -60.9019 -75.3976 -7.45 -60.7923 -75.4163 -7.5 -60.6828 -75.4244 -7.55 -60.5733 -75.424 -7.6 -60.464 -75.4169 -7.65 -60.3547 -75.4046 -7.7 -60.2456 -75.388 -7.75 -60.1366 -75.3679 -7.8 -60.0278 -75.345 -7.85 -59.9193 -75.3196 -7.9 -59.8109 -75.2923 -7.95 -59.7029 -75.2632 -8 -59.595 -75.2327 -8.05 -59.4875 -75.2009 -8.1 -59.3802 -75.1679 -8.15 -59.2732 -75.1339 -8.2 -59.1666 -75.0989 -8.25 -59.0603 -75.0631 -8.3 -58.9543 -75.0265 -8.35 -58.8486 -74.9892 -8.4 -58.7433 -74.9511 -8.45 -58.6384 -74.9124 -8.5 -58.5339 -74.873 -8.55 -58.4297 -74.833 -8.6 -58.3258 -74.7924 -8.65 -58.2224 -74.7513 -8.7 -58.1194 -74.7096 -8.75 -58.0167 -74.6673 -8.8 -57.9145 -74.6245 -8.85 -57.8126 -74.5812 -8.9 -57.7111 -74.5373 -8.95 -57.6101 -74.493 -9 -57.5094 -74.4481 -9.05 -57.4091 -74.4028 -9.1 -57.3093 -74.3569 -9.15 -57.2098 -74.3107 -9.2 -57.1108 -74.2639 -9.25 -57.0121 -74.2167 -9.3 -56.9139 -74.169 -9.35 -56.816 -74.1209 -9.4 -56.7185 -74.0723 -9.45 -56.6215 -74.0233 -9.5 -56.5248 -73.9739 -9.55 -56.4285 -73.924 -9.6 -56.3326 -73.8738 -9.65 -56.237 -73.8231 -9.7 -56.1419 -73.772 -9.75 -56.0471 -73.7206 -9.8 -55.9527 -73.6687 -9.85 -55.8586 -73.6165 -9.9 -55.7649 -73.564 -9.95 -55.6716 -73.511 -10 -55.5786 -73.4577 -10.05 -55.486 -73.4041 -10.1 -55.3936 -73.3501 -10.15 -55.3017 -73.2958 -10.2 -55.21 -73.2412 -10.25 -55.1187 -73.1863 -10.3 -55.0276 -73.1311 -10.35 -54.9369 -73.0756 -10.4 -54.8465 -73.0198 -10.45 -54.7564 -72.9637 -10.5 -54.6666 -72.9074 -10.55 -54.577 -72.8508 -10.6 -54.4877 -72.794 -10.65 -54.3987 -72.7369 -10.7 -54.3099 -72.6796 -10.75 -54.2214 -72.6221 -10.8 -54.1331 -72.5644 -10.85 -54.0451 -72.5065 -10.9 -53.9573 -72.4484 -10.95 -53.8697 -72.3901 -11 -53.7823 -72.3316 -11.05 -53.6951 -72.273 -11.1 -53.6082 -72.2142 -11.15 -53.5214 -72.1553 -11.2 -53.4347 -72.0962 -11.25 -53.3483 -72.037 -11.3 -53.2619 -71.9778 -11.35 -53.1758 -71.9184 -11.4 -53.0898 -71.8589 -11.45 -53.0039 -71.7993 -11.5 -52.9181 -71.7397 -11.55 -52.8324 -71.68 -11.6 -52.7469 -71.6202 -11.65 -52.6614 -71.5604 -11.7 -52.576 -71.5005 -11.75 -52.4907 -71.4407 -11.8 -52.4054 -71.3807 -11.85 -52.3202 -71.3208 -11.9 -52.235 -71.2609 -11.95 -52.1498 -71.201 -12 -52.0647 -71.1411 -12.05 -51.9795 -71.0813 -12.1 -51.8943 -71.0214 -12.15 -51.8092 -70.9616 -12.2 -51.7239 -70.9019 -12.25 -51.6386 -70.8422 -12.3 -51.5533 -70.7826 -12.35 -51.4679 -70.7231 -12.4 -51.3823 -70.6636 -12.45 -51.2967 -70.6043 -12.5 -51.2109 -70.545 -12.55 -51.125 -70.4858 -12.6 -51.0389 -70.4267 -12.65 -50.9526 -70.3678 -12.7 -50.8662 -70.309 -12.75 -50.7795 -70.2503 -12.8 -50.6926 -70.1918 -12.85 -50.6055 -70.1334 -12.9 -50.518 -70.0752 -12.95 -50.4303 -70.0171 -13 -50.3422 -69.9592 -13.05 -50.2538 -69.9015 -13.1 -50.165 -69.844 -13.15 -50.0758 -69.7866 -13.2 -49.9862 -69.7295 -13.25 -49.8961 -69.6725 -13.3 -49.8056 -69.6157 -13.35 -49.7145 -69.5592 -13.4 -49.6228 -69.5028 -13.45 -49.5305 -69.4467 -13.5 -49.4376 -69.3908 -13.55 -49.344 -69.3351 -13.6 -49.2497 -69.2796 -13.65 -49.1546 -69.2244 -13.7 -49.0586 -69.1694 -13.75 -48.9618 -69.1147 -13.8 -48.8641 -69.0603 -13.85 -48.7653 -69.0061 -13.9 -48.6654 -68.9521 -13.95 -48.5645 -68.8985 -14 -48.4622 -68.8451 -14.05 -48.3587 -68.7919 -14.1 -48.2538 -68.739 -14.15 -48.1474 -68.6864 -14.2 -48.0393 -68.6341 -14.25 -47.9296 -68.582 -14.3 -47.818 -68.5302 -14.35 -47.7045 -68.4787 -14.4 -47.5888 -68.4275 -14.45 -47.4709 -68.3766 -14.5 -47.3505 -68.326 -14.55 -47.2275 -68.2757 -14.6 -47.1016 -68.2256 -14.65 -46.9727 -68.1759 -14.7 -46.8405 -68.1265 -14.75 -46.7047 -68.0774 -14.8 -46.565 -68.0286 -14.85 -46.4211 -67.9802 -14.9 -46.2727 -67.932 -14.95 -46.1193 -67.8842 -15 -45.9605 -67.8367 -15.05 -45.7958 -67.7894 -15.1 -45.6247 -67.7425 -15.15 -45.4466 -67.6959 -15.2 -45.2607 -67.6496 -15.25 -45.0664 -67.6036 -15.3 -44.8628 -67.558 -15.35 -44.6489 -67.5126 -15.4 -44.4237 -67.4675 -15.45 -44.1859 -67.4228 -15.5 -43.9342 -67.3784 -15.55 -43.6671 -67.3343 -15.6 -43.3828 -67.2906 -15.65 -43.0792 -67.2471 -15.7 -42.7541 -67.204 -15.75 -42.4048 -67.1612 -15.8 -42.0283 -67.1188 -15.85 -41.6211 -67.0767 -15.9 -41.1792 -67.0349 -15.95 -40.6978 -66.9935 -16 -40.1716 -66.9523 -16.05 -39.5943 -66.9115 -16.1 -38.9584 -66.871 -16.15 -38.2554 -66.8308 -16.2 -37.4754 -66.791 -16.25 -36.6066 -66.7514 -16.3 -35.6358 -66.7121 -16.35 -34.5475 -66.6731 -16.4 -33.324 -66.6344 -16.45 -31.9459 -66.596 -16.5 -30.3915 -66.558 -16.55 -28.6386 -66.5202 -16.6 -26.6652 -66.4827 -16.65 -24.4523 -66.4454 -16.7 -21.9877 -66.4085 -16.75 -19.2714 -66.3719 -16.8 -16.3224 -66.3355 -16.85 -13.1863 -66.2995 -16.9 -9.94114 -66.2636 -16.95 -6.69921 -66.2281 -17 -3.60159 -66.1928 -17.05 -0.803249 -66.1578 -17.1 1.54876 -66.123 -17.15 3.33796 -66.0884 -17.2 4.49538 -66.054 -17.25 5.00517 -66.0198 -17.3 4.89902 -65.9857 -17.35 4.24335 -65.9518 -17.4 3.12406 -65.9179 -17.45 1.63303 -65.8841 -17.5 -0.141716 -65.8501 -17.55 -2.12181 -65.8161 -17.6 -4.2411 -65.7819 -17.65 -6.44599 -65.7473 -17.7 -8.69443 -65.7122 -17.75 -10.9544 -65.6765 -17.8 -13.2022 -65.6399 -17.85 -15.4206 -65.6021 -17.9 -17.5979 -65.5629 -17.95 -19.7263 -65.5217 -18 -21.8012 -65.4779 -18.05 -23.8208 -65.431 -18.1 -25.7849 -65.38 -18.15 -27.6952 -65.3239 -18.2 -29.555 -65.2613 -18.25 -31.3682 -65.1906 -18.3 -33.1403 -65.1097 -18.35 -34.877 -65.0161 -18.4 -36.5849 -64.9065 -18.45 -38.2709 -64.7769 -18.5 -39.9416 -64.6226 -18.55 -41.6038 -64.4374 -18.6 -43.263 -64.2138 -18.65 -44.9238 -63.9425 -18.7 -46.589 -63.612 -18.75 -48.2585 -63.2079 -18.8 -49.9294 -62.7123 -18.85 -51.5948 -62.1032 -18.9 -53.2437 -61.353 -18.95 -54.861 -60.4272 -19 -56.4282 -59.2829 -19.05 -57.9247 -57.8657 -19.1 -59.3299 -56.1068 -19.15 -60.6257 -53.918 -19.2 -61.7984 -51.1843 -19.25 -62.8401 -47.7528 -19.3 -63.7495 -43.4156 -19.35 -64.5308 -37.8849 -19.4 -65.1928 -30.7661 -19.45 -65.7467 -21.5665 -19.5 -66.2052 -9.87695 -19.55 -66.5809 4.0047 -19.6 -66.8855 18.1656 -19.65 -67.1297 29.5813 -19.7 -67.3226 36.6086 -19.75 -67.4723 39.8988 -19.8 -67.5854 40.8953 -19.85 -67.6675 40.6661 -19.9 -67.7233 39.7707 -19.95 -67.7567 38.4661 -20 -67.771 36.8711 -20.05 -67.7691 35.0482 -20.1 -67.7531 33.0383 -20.15 -67.7251 30.8731 -20.2 -67.6867 28.5804 -20.25 -67.6393 26.1851 -20.3 -67.5842 23.7099 -20.35 -67.5222 21.1752 -20.4 -67.4544 18.5991 -20.45 -67.3814 15.9974 -20.5 -67.3039 13.3837 -20.55 -67.2224 10.7694 -20.6 -67.1375 8.16389 -20.65 -67.0495 5.57477 -20.7 -66.9587 3.00791 -20.75 -66.8656 0.467774 -20.8 -66.7703 -2.04256 -20.85 -66.673 -4.52104 -20.9 -66.5741 -6.96674 -20.95 -66.4736 -9.37945 -21 -66.3718 -11.76 -21.05 -66.2687 -14.1098 -21.1 -66.1645 -16.4311 -21.15 -66.0593 -18.7273 -21.2 -65.9531 -21.0026 -21.25 -65.8461 -23.2626 -21.3 -65.7384 -25.5148 -21.35 -65.6299 -27.7689 -21.4 -65.5208 -30.0368 -21.45 -65.4111 -32.3342 -21.5 -65.3009 -34.6802 -21.55 -65.1902 -37.098 -21.6 -65.079 -39.615 -21.65 -64.9674 -42.2618 -21.7 -64.8555 -45.0697 -21.75 -64.7432 -48.0658 -21.8 -64.6305 -51.2638 -21.85 -64.5176 -54.6496 -21.9 -64.4044 -58.1635 -21.95 -64.2909 -61.685 -22 -64.1773 -65.0359 -22.05 -64.0634 -68.0172 -22.1 -63.9494 -70.4734 -22.15 -63.8352 -72.3474 -22.2 -63.7209 -73.6852 -22.25 -63.6064 -74.5928 -22.3 -63.4919 -75.1876 -22.35 -63.3772 -75.5687 -22.4 -63.2625 -75.8093 -22.45 -63.1478 -75.9591 -22.5 -63.033 -76.0504 -22.55 -62.9181 -76.104 -22.6 -62.8033 -76.1331 -22.65 -62.6885 -76.1461 -22.7 -62.5737 -76.1485 -22.75 -62.4589 -76.1435 -22.8 -62.3442 -76.1336 -22.85 -62.2296 -76.1201 -22.9 -62.115 -76.1041 -22.95 -62.0005 -76.0863 -23 -61.8861 -76.0669 -23.05 -61.7718 -76.0465 -23.1 -61.6576 -76.0251 -23.15 -61.5436 -76.0028 -23.2 -61.4296 -75.9799 -23.25 -61.3159 -75.9564 -23.3 -61.2023 -75.9322 -23.35 -61.0888 -75.9075 -23.4 -60.9755 -75.8823 -23.45 -60.8625 -75.8565 -23.5 -60.7496 -75.8303 -23.55 -60.6369 -75.8035 -23.6 -60.5244 -75.7762 -23.65 -60.4121 -75.7484 -23.7 -60.3001 -75.7202 -23.75 -60.1882 -75.6914 -23.8 -60.0766 -75.6621 -23.85 -59.9653 -75.6324 -23.9 -59.8541 -75.6021 -23.95 -59.7433 -75.5713 -24 -59.6327 -75.5401 -24.05 -59.5223 -75.5083 -24.1 -59.4122 -75.476 -24.15 -59.3023 -75.4432 -24.2 -59.1927 -75.4099 -24.25 -59.0834 -75.3761 -24.3 -58.9743 -75.3418 -24.35 -58.8656 -75.3069 -24.4 -58.757 -75.2716 -24.45 -58.6488 -75.2357 -24.5 -58.5408 -75.1993 -24.55 -58.4331 -75.1625 -24.6 -58.3257 -75.1251 -24.65 -58.2185 -75.0871 -24.7 -58.1116 -75.0487 -24.75 -58.005 -75.0098 -24.8 -57.8986 -74.9703 -24.85 -57.7925 -74.9304 -24.9 -57.6866 -74.8899 -24.95 -57.581 -74.849 -25 -57.4757 -74.8075 -25.05 -57.3705 -74.7655 -25.1 -57.2657 -74.7231 -25.15 -57.161 -74.6801 -25.2 -57.0566 -74.6366 -25.25 -56.9525 -74.5927 -25.3 -56.8485 -74.5483 -25.35 -56.7448 -74.5033 -25.4 -56.6412 -74.458 -25.45 -56.5379 -74.4121 -25.5 -56.4347 -74.3658 -25.55 -56.3317 -74.319 -25.6 -56.2289 -74.2717 -25.65 -56.1263 -74.224 -25.7 -56.0238 -74.1758 -25.75 -55.9215 -74.1272 -25.8 -55.8192 -74.0782 -25.85 -55.7172 -74.0287 -25.9 -55.6152 -73.9788 -25.95 -55.5133 -73.9285 -26 -55.4115 -73.8777 -26.05 -55.3097 -73.8266 -26.1 -55.2081 -73.775 -26.15 -55.1064 -73.7231 -26.2 -55.0048 -73.6708 -26.25 -54.9032 -73.6181 -26.3 -54.8016 -73.565 -26.35 -54.7 -73.5116 -26.4 -54.5983 -73.4578 -26.45 -54.4966 -73.4037 -26.5 -54.3948 -73.3492 -26.55 -54.2929 -73.2944 -26.6 -54.1909 -73.2393 -26.65 -54.0887 -73.1838 -26.7 -53.9864 -73.1281 -26.75 -53.8839 -73.072 -26.8 -53.7812 -73.0157 -26.85 -53.6783 -72.9591 -26.9 -53.5751 -72.9023 -26.95 -53.4716 -72.8452 -27 -53.3677 -72.7878 -27.05 -53.2636 -72.7302 -27.1 -53.159 -72.6723 -27.15 -53.054 -72.6143 -27.2 -52.9486 -72.556 -27.25 -52.8426 -72.4975 -27.3 -52.7362 -72.4388 -27.35 -52.6291 -72.38 -27.4 -52.5215 -72.321 -27.45 -52.4131 -72.2618 -27.5 -52.3041 -72.2024 -27.55 -52.1942 -72.1429 -27.6 -52.0836 -72.0833 -27.65 -51.972 -72.0236 -27.7 -51.8595 -71.9637 -27.75 -51.746 -71.9038 -27.8 -51.6314 -71.8437 -27.85 -51.5156 -71.7836 -27.9 -51.3985 -71.7233 -27.95 -51.2802 -71.663 -28 -51.1603 -71.6027 -28.05 -51.0389 -71.5423 -28.1 -50.9159 -71.4818 -28.15 -50.7911 -71.4214 -28.2 -50.6645 -71.3609 -28.25 -50.5358 -71.3004 -28.3 -50.4049 -71.2398 -28.35 -50.2716 -71.1793 -28.4 -50.1358 -71.1189 -28.45 -49.9973 -71.0584 -28.5 -49.8559 -70.998 -28.55 -49.7114 -70.9376 -28.6 -49.5634 -70.8772 -28.65 -49.4118 -70.817 -28.7 -49.2562 -70.7567 -28.75 -49.0963 -70.6966 -28.8 -48.9318 -70.6365 -28.85 -48.7621 -70.5765 -28.9 -48.587 -70.5166 -28.95 -48.4059 -70.4568 -29 -48.2182 -70.3971 -29.05 -48.0233 -70.3375 -29.1 -47.8206 -70.2781 -29.15 -47.6092 -70.2187 -29.2 -47.3884 -70.1596 -29.25 -47.157 -70.1005 -29.3 -46.9141 -70.0416 -29.35 -46.6584 -69.9829 -29.4 -46.3884 -69.9244 -29.45 -46.1025 -69.866 -29.5 -45.7989 -69.8077 -29.55 -45.4753 -69.7497 -29.6 -45.1292 -69.6918 -29.65 -44.7579 -69.6341 -29.7 -44.3579 -69.5766 -29.75 -43.9252 -69.5193 -29.8 -43.4553 -69.4622 -29.85 -42.9427 -69.4053 -29.9 -42.381 -69.3487 -29.95 -41.7624 -69.2922 -30 -41.0778 -69.236 -30.05 -40.3162 -69.1799 -30.1 -39.4646 -69.1241 -30.15 -38.5069 -69.0686 -30.2 -37.4243 -69.0133 -30.25 -36.1938 -68.9582 -30.3 -34.7881 -68.9034 -30.35 -33.175 -68.8488 -30.4 -31.3171 -68.7944 -30.45 -29.1723 -68.7403 -30.5 -26.6954 -68.6864 -30.55 -23.8423 -68.6328 -30.6 -20.5774 -68.5794 -30.65 -16.8858 -68.5262 -30.7 -12.7896 -68.4733 -30.75 -8.36852 -68.4206 -30.8 -3.77385 -68.3681 -30.85 0.771531 -68.3159 -30.9 4.99954 -68.2639 -30.95 8.6464 -68.2122 -31 11.5073 -68.1607 -31.05 13.4724 -68.1094 -31.1 14.5315 -68.0583 -31.15 14.753 -68.0074 -31.2 14.2522 -67.9567 -31.25 13.1627 -67.9061 -31.3 11.6151 -67.8557 -31.35 9.72606 -67.8053 -31.4 7.59384 -67.755 -31.45 5.29767 -67.7047 -31.5 2.89969 -67.6543 -31.55 0.447506 -67.6037 -31.6 -2.02307 -67.5528 -31.65 -4.48566 -67.5015 -31.7 -6.92114 -67.4497 -31.75 -9.31608 -67.3971 -31.8 -11.6613 -67.3434 -31.85 -13.9509 -67.2884 -31.9 -16.1816 -67.2316 -31.95 -18.3517 -67.1725 -32 -20.4614 -67.1105 -32.05 -22.5118 -67.0449 -32.1 -24.5052 -66.9746 -32.15 -26.4448 -66.8985 -32.2 -28.3347 -66.815 -32.25 -30.1796 -66.7225 -32.3 -31.9851 -66.6186 -32.35 -33.7572 -66.5007 -32.4 -35.5028 -66.3653 -32.45 -37.2287 -66.2084 -32.5 -38.9421 -66.0247 -32.55 -40.6501 -65.8081 -32.6 -42.3591 -65.5507 -32.65 -44.0743 -65.2431 -32.7 -45.7996 -64.8735 -32.75 -47.5359 -64.4274 -32.8 -49.2813 -63.887 -32.85 -51.0294 -63.2302 -32.9 -52.7694 -62.4299 -32.95 -54.4853 -61.4522 -33 -56.1567 -60.2552 -33.05 -57.7598 -58.7863 -33.1 -59.2703 -56.9791 -33.15 -60.6658 -54.7491 -33.2 -61.9285 -51.9863 -33.25 -63.0478 -48.5448 -33.3 -64.0208 -44.2256 -33.35 -64.8517 -38.7516 -33.4 -65.5503 -31.7362 -33.45 -66.1297 -22.6801 -33.5 -66.6047 -11.122 -33.55 -66.9898 2.77051 -33.6 -67.2987 17.2121 -33.65 -67.5434 29.0811 -33.7 -67.7343 36.4869 -33.75 -67.8803 39.9921 -33.8 -67.9887 41.0988 -33.85 -68.0656 40.9392 -33.9 -68.116 40.1038 -33.95 -68.144 38.8594 -34 -68.1531 37.3264 -34.05 -68.1461 35.5672 -34.1 -68.1255 33.6214 -34.15 -68.0933 31.5197 -34.2 -68.051 29.2887 -34.25 -68.0001 26.9526 -34.3 -67.9419 24.5332 -34.35 -67.8772 22.0505 -34.4 -67.807 19.5221 -34.45 -67.7319 16.9637 -34.5 -67.6526 14.3888 -34.55 -67.5697 11.8089 -34.6 -67.4835 9.23348 -34.65 -67.3944 6.67038 -34.7 -67.3029 4.12578 -34.75 -67.2091 1.60447 -34.8 -67.1133 -0.890136 -34.85 -67.0157 -3.35561 -34.9 -66.9165 -5.79067 -34.95 -66.816 -8.19475 -35 -66.7141 -10.5682 -35.05 -66.611 -12.9122 -35.1 -66.5069 -15.2283 -35.15 -66.4019 -17.5196 -35.2 -66.2959 -19.7895 -35.25 -66.1891 -22.0429 -35.3 -66.0816 -24.2862 -35.35 -65.9734 -26.5278 -35.4 -65.8646 -28.7785 -35.45 -65.7552 -31.0517 -35.5 -65.6453 -33.3647 -35.55 -65.5348 -35.7388 -35.6 -65.4239 -38.1992 -35.65 -65.3125 -40.7752 -35.7 -65.2008 -43.4988 -35.75 -65.0886 -46.4005 -35.8 -64.9761 -49.5031 -35.85 -64.8633 -52.8099 -35.9 -64.7502 -56.2876 -35.95 -64.6369 -59.8474 -36 -64.5232 -63.3371 -36.05 -64.4094 -66.5572 -36.1 -64.2953 -69.3169 -36.15 -64.181 -71.5016 -36.2 -64.0665 -73.1077 -36.25 -63.9519 -74.2193 -36.3 -63.8372 -74.9558 -36.35 -63.7223 -75.4302 -36.4 -63.6073 -75.7301 -36.45 -63.4922 -75.917 -36.5 -63.3771 -76.0316 -36.55 -63.2618 -76.0999 -36.6 -63.1466 -76.1383 -36.65 -63.0313 -76.1573 -36.7 -62.9159 -76.1636 -36.75 -62.8006 -76.1614 -36.8 -62.6853 -76.1533 -36.85 -62.57 -76.1413 -36.9 -62.4547 -76.1264 -36.95 -62.3395 -76.1093 -37 -62.2243 -76.0907 -37.05 -62.1092 -76.0709 -37.1 -61.9942 -76.0501 -37.15 -61.8793 -76.0284 -37.2 -61.7645 -76.0061 -37.25 -61.6498 -75.983 -37.3 -61.5352 -75.9594 -37.35 -61.4207 -75.9352 -37.4 -61.3064 -75.9105 -37.45 -61.1923 -75.8852 -37.5 -61.0783 -75.8595 -37.55 -60.9645 -75.8332 -37.6 -60.8508 -75.8065 -37.65 -60.7374 -75.7792 -37.7 -60.6241 -75.7515 -37.75 -60.5111 -75.7232 -37.8 -60.3982 -75.6945 -37.85 -60.2856 -75.6652 -37.9 -60.1731 -75.6355 -37.95 -60.0609 -75.6053 -38 -59.949 -75.5745 -38.05 -59.8373 -75.5433 -38.1 -59.7258 -75.5115 -38.15 -59.6145 -75.4793 -38.2 -59.5035 -75.4465 -38.25 -59.3928 -75.4132 -38.3 -59.2823 -75.3795 -38.35 -59.172 -75.3452 -38.4 -59.062 -75.3104 -38.45 -58.9523 -75.2751 -38.5 -58.8428 -75.2392 -38.55 -58.7336 -75.2029 -38.6 -58.6247 -75.166 -38.65 -58.516 -75.1287 -38.7 -58.4075 -75.0908 -38.75 -58.2994 -75.0524 -38.8 -58.1914 -75.0135 -38.85 -58.0838 -74.9741 -38.9 -57.9764 -74.9342 -38.95 -57.8692 -74.8937 -39 -57.7623 -74.8528 -39.05 -57.6557 -74.8114 -39.1 -57.5492 -74.7694 -39.15 -57.443 -74.727 -39.2 -57.3371 -74.684 -39.25 -57.2313 -74.6406 -39.3 -57.1258 -74.5967 -39.35 -57.0205 -74.5523 -39.4 -56.9154 -74.5074 -39.45 -56.8105 -74.462 -39.5 -56.7058 -74.4162 -39.55 -56.6013 -74.3699 -39.6 -56.497 -74.3231 -39.65 -56.3928 -74.2759 -39.7 -56.2888 -74.2282 -39.75 -56.1849 -74.18 -39.8 -56.0812 -74.1314 -39.85 -55.9776 -74.0824 -39.9 -55.8741 -74.033 -39.95 -55.7707 -73.9831 -40 -55.6674 -73.9328 -40.05 -55.5642 -73.8821 -40.1 -55.4611 -73.8309 -40.15 -55.358 -73.7794 -40.2 -55.2549 -73.7275 -40.25 -55.1518 -73.6752 -40.3 -55.0488 -73.6225 -40.35 -54.9457 -73.5694 -40.4 -54.8427 -73.516 -40.45 -54.7395 -73.4622 -40.5 -54.6363 -73.4081 -40.55 -54.533 -73.3536 -40.6 -54.4297 -73.2989 -40.65 -54.3261 -73.2437 -40.7 -54.2224 -73.1883 -40.75 -54.1186 -73.1326 -40.8 -54.0145 -73.0766 -40.85 -53.9102 -73.0203 -40.9 -53.8057 -72.9637 -40.95 -53.7009 -72.9068 -41 -53.5958 -72.8497 -41.05 -53.4903 -72.7923 -41.1 -53.3845 -72.7347 -41.15 -53.2782 -72.6769 -41.2 -53.1715 -72.6188 -41.25 -53.0643 -72.5605 -41.3 -52.9566 -72.5021 -41.35 -52.8483 -72.4434 -41.4 -52.7394 -72.3845 -41.45 -52.6298 -72.3255 -41.5 -52.5196 -72.2663 -41.55 -52.4086 -72.207 -41.6 -52.2967 -72.1475 -41.65 -52.184 -72.0879 -41.7 -52.0703 -72.0281 -41.75 -51.9556 -71.9683 -41.8 -51.8398 -71.9083 -41.85 -51.7229 -71.8482 -41.9 -51.6047 -71.7881 -41.95 -51.4852 -71.7278 -42 -51.3643 -71.6675 -42.05 -51.2418 -71.6072 -42.1 -51.1177 -71.5468 -42.15 -50.9918 -71.4863 -42.2 -50.864 -71.4258 -42.25 -50.7343 -71.3653 -42.3 -50.6023 -71.3048 -42.35 -50.468 -71.2443 -42.4 -50.3312 -71.1837 -42.45 -50.1917 -71.1232 -42.5 -50.0493 -71.0628 -42.55 -49.9038 -71.0023 -42.6 -49.7549 -70.9419 -42.65 -49.6023 -70.8816 -42.7 -49.4458 -70.8213 -42.75 -49.2849 -70.761 -42.8 -49.1195 -70.7008 -42.85 -48.949 -70.6407 -42.9 -48.773 -70.5807 -42.95 -48.591 -70.5208 -43 -48.4025 -70.461 -43.05 -48.2068 -70.4012 -43.1 -48.0033 -70.3416 -43.15 -47.7913 -70.2822 -43.2 -47.5697 -70.2228 -43.25 -47.3378 -70.1636 -43.3 -47.0942 -70.1045 -43.35 -46.8379 -70.0456 -43.4 -46.5674 -69.9869 -43.45 -46.281 -69.9283 -43.5 -45.9769 -69.8699 -43.55 -45.6529 -69.8116 -43.6 -45.3065 -69.7535 -43.65 -44.9348 -69.6956 -43.7 -44.5345 -69.6379 -43.75 -44.1016 -69.5804 -43.8 -43.6314 -69.523 -43.85 -43.1185 -69.4659 -43.9 -42.5563 -69.4089 -43.95 -41.9372 -69.3522 -44 -41.2519 -69.2957 -44.05 -40.4892 -69.2394 -44.1 -39.6359 -69.1834 -44.15 -38.6758 -69.1275 -44.2 -37.5896 -69.0719 -44.25 -36.3539 -69.0166 -44.3 -34.9406 -68.9615 -44.35 -33.3166 -68.9066 -44.4 -31.4431 -68.8519 -44.45 -29.2763 -68.7975 -44.5 -26.7687 -68.7433 -44.55 -23.8737 -68.6894 -44.6 -20.5529 -68.6357 -44.65 -16.7888 -68.5822 -44.7 -12.6034 -68.5289 -44.75 -8.07828 -68.4759 -44.8 -3.37185 -68.4232 -44.85 1.28212 -68.3706 -44.9 5.60287 -68.3183 -44.95 9.31651 -68.2663 -45 12.2142 -68.2144 -45.05 14.1887 -68.1628 -45.1 15.2368 -68.1114 -45.15 15.4354 -68.0601 -45.2 14.9069 -68.0091 -45.25 13.7895 -67.9582 -45.3 12.2167 -67.9074 -45.35 10.3061 -67.8568 -45.4 8.15582 -67.8061 -45.45 5.84471 -67.7555 -45.5 3.4342 -67.7047 -45.55 0.971229 -67.6538 -45.6 -1.509 -67.6027 -45.65 -3.98053 -67.5511 -45.7 -6.42462 -67.4989 -45.75 -8.82805 -67.446 -45.8 -11.1818 -67.3921 -45.85 -13.4801 -67.3368 -45.9 -15.7196 -67.2797 -45.95 -17.8988 -67.2204 -46 -20.0177 -67.1582 -46.05 -22.0775 -67.0924 -46.1 -24.0802 -67.0219 -46.15 -26.0291 -66.9457 -46.2 -27.928 -66.8623 -46.25 -29.7816 -66.7698 -46.3 -31.5952 -66.6661 -46.35 -33.3749 -66.5484 -46.4 -35.1273 -66.4134 -46.45 -36.8594 -66.257 -46.5 -38.5783 -66.0742 -46.55 -40.2912 -65.8587 -46.6 -42.0047 -65.6027 -46.65 -43.7243 -65.297 -46.7 -45.4541 -64.9298 -46.75 -47.1959 -64.4868 -46.8 -48.9482 -63.9504 -46.85 -50.7057 -63.2988 -46.9 -52.458 -62.5049 -46.95 -54.1898 -61.5354 -47 -55.881 -60.3488 -47.05 -57.5082 -58.8931 -47.1 -59.0463 -57.1028 -47.15 -60.4718 -54.8945 -47.2 -61.7657 -52.1597 -47.25 -62.9157 -48.7548 -47.3 -63.9176 -44.4842 -47.35 -64.7746 -39.0756 -47.4 -65.4959 -32.1486 -47.45 -66.0945 -23.2078 -47.5 -66.5853 -11.7801 -47.55 -66.9832 2.02378 -47.6 -67.3023 16.5153 -47.65 -67.5551 28.5862 -47.7 -67.7525 36.2227 -47.75 -67.9035 39.889 -47.8 -68.0159 41.0842 -47.85 -68.0958 40.9708 -47.9 -68.1486 40.1621 -47.95 -68.1786 38.9358 -48 -68.1892 37.4171 -48.05 -68.1835 35.6698 -48.1 -68.1639 33.7343 -48.15 -68.1324 31.6416 -48.2 -68.0908 29.4183 -48.25 -68.0405 27.0888 -48.3 -67.9826 24.6749 -48.35 -67.9183 22.1966 -48.4 -67.8484 19.6718 -48.45 -67.7736 17.1161 -48.5 -67.6946 14.5432 -48.55 -67.6118 11.9646 -48.6 -67.5258 9.38995 -48.65 -67.4369 6.82715 -48.7 -67.3455 4.28245 -48.75 -67.2519 1.76072 -48.8 -67.1562 -0.734542 -48.85 -67.0588 -3.20088 -48.9 -66.9597 -5.6369 -48.95 -66.8593 -8.04206 -49 -66.7575 -10.4166 -49.05 -66.6546 -12.7616 -49.1 -66.5506 -15.0788 -49.15 -66.4456 -17.3709 -49.2 -66.3398 -19.6414 -49.25 -66.2331 -21.8953 -49.3 -66.1257 -24.1385 -49.35 -66.0176 -26.3795 -49.4 -65.9088 -28.6288 -49.45 -65.7995 -30.8999 -49.5 -65.6896 -33.2094 -49.55 -65.5792 -35.5786 -49.6 -65.4684 -38.0324 -49.65 -65.3571 -40.5999 -49.7 -65.2454 -43.3128 -49.75 -65.1333 -46.2022 -49.8 -65.0208 -49.2916 -49.85 -64.9081 -52.586 -49.9 -64.795 -56.055 -49.95 -64.6816 -59.6143 -50 -64.568 -63.1151 -50.05 -64.4542 -66.36 -50.1 -64.3401 -69.155 -50.15 -64.2258 -71.379 -50.2 -64.1114 -73.0211 -50.25 -63.9967 -74.1613 -50.3 -63.882 -74.9184 -50.35 -63.7671 -75.4067 -50.4 -63.6521 -75.7156 -50.45 -63.5369 -75.9084 -50.5 -63.4217 -76.0266 -50.55 -63.3065 -76.0972 -50.6 -63.1912 -76.1371 -50.65 -63.0758 -76.1571 -50.7 -62.9604 -76.1641 -50.75 -62.845 -76.1623 -50.8 -62.7296 -76.1545 -50.85 -62.6143 -76.1427 -50.9 -62.4989 -76.1279 -50.95 -62.3836 -76.111 -51 -62.2684 -76.0925 -51.05 -62.1532 -76.0728 -51.1 -62.0381 -76.052 -51.15 -61.923 -76.0304 -51.2 -61.8081 -76.0081 -51.25 -61.6933 -75.9851 -51.3 -61.5786 -75.9615 -51.35 -61.464 -75.9374 -51.4 -61.3496 -75.9127 -51.45 -61.2353 -75.8875 -51.5 -61.1212 -75.8618 -51.55 -61.0072 -75.8355 -51.6 -60.8935 -75.8088 -51.65 -60.7799 -75.7816 -51.7 -60.6665 -75.7539 -51.75 -60.5533 -75.7257 -51.8 -60.4402 -75.697 -51.85 -60.3275 -75.6678 -51.9 -60.2149 -75.6381 -51.95 -60.1025 -75.6079 -52 -59.9904 -75.5772 -52.05 -59.8785 -75.546 -52.1 -59.7668 -75.5143 -52.15 -59.6554 -75.4821 -52.2 -59.5443 -75.4494 -52.25 -59.4333 -75.4162 -52.3 -59.3227 -75.3825 -52.35 -59.2122 -75.3482 -52.4 -59.1021 -75.3135 -52.45 -58.9922 -75.2782 -52.5 -58.8825 -75.2424 -52.55 -58.7731 -75.2061 -52.6 -58.664 -75.1693 -52.65 -58.5551 -75.132 -52.7 -58.4465 -75.0941 -52.75 -58.3382 -75.0558 -52.8 -58.2301 -75.0169 -52.85 -58.1222 -74.9776 -52.9 -58.0146 -74.9377 -52.95 -57.9073 -74.8973 -53 -57.8002 -74.8564 -53.05 -57.6934 -74.815 -53.1 -57.5868 -74.7731 -53.15 -57.4804 -74.7307 -53.2 -57.3743 -74.6878 -53.25 -57.2684 -74.6445 -53.3 -57.1627 -74.6006 -53.35 -57.0572 -74.5562 -53.4 -56.9519 -74.5114 -53.45 -56.8469 -74.466 -53.5 -56.742 -74.4202 -53.55 -56.6373 -74.374 -53.6 -56.5328 -74.3272 -53.65 -56.4285 -74.28 -53.7 -56.3243 -74.2324 -53.75 -56.2203 -74.1843 -53.8 -56.1164 -74.1358 -53.85 -56.0126 -74.0868 -53.9 -55.909 -74.0374 -53.95 -55.8054 -73.9875 -54 -55.702 -73.9372 -54.05 -55.5986 -73.8866 -54.1 -55.4953 -73.8355 -54.15 -55.3921 -73.784 -54.2 -55.2889 -73.7321 -54.25 -55.1857 -73.6798 -54.3 -55.0825 -73.6272 -54.35 -54.9793 -73.5741 -54.4 -54.8761 -73.5208 -54.45 -54.7729 -73.467 -54.5 -54.6695 -73.4129 -54.55 -54.5661 -73.3585 -54.6 -54.4626 -73.3037 -54.65 -54.359 -73.2486 -54.7 -54.2552 -73.1933 -54.75 -54.1512 -73.1376 -54.8 -54.0471 -73.0816 -54.85 -53.9427 -73.0253 -54.9 -53.8381 -72.9687 -54.95 -53.7332 -72.9119 -55 -53.628 -72.8548 -55.05 -53.5224 -72.7975 -55.1 -53.4165 -72.7399 -55.15 -53.3102 -72.6821 -55.2 -53.2034 -72.624 -55.25 -53.0962 -72.5658 -55.3 -52.9884 -72.5073 -55.35 -52.8801 -72.4486 -55.4 -52.7711 -72.3898 -55.45 -52.6615 -72.3308 -55.5 -52.5513 -72.2716 -55.55 -52.4402 -72.2123 -55.6 -52.3284 -72.1528 -55.65 -52.2156 -72.0932 -55.7 -52.1019 -72.0335 -55.75 -51.9873 -71.9736 -55.8 -51.8715 -71.9137 -55.85 -51.7546 -71.8536 -55.9 -51.6365 -71.7935 -55.95 -51.5171 -71.7333 -56 -51.3962 -71.673 -56.05 -51.2738 -71.6126 -56.1 -51.1498 -71.5522 -56.15 -51.0241 -71.4918 -56.2 -50.8964 -71.4313 -56.25 -50.7668 -71.3708 -56.3 -50.635 -71.3102 -56.35 -50.5009 -71.2497 -56.4 -50.3644 -71.1892 -56.45 -50.2251 -71.1287 -56.5 -50.083 -71.0682 -56.55 -49.9377 -71.0078 -56.6 -49.7891 -70.9474 -56.65 -49.6369 -70.887 -56.7 -49.4808 -70.8267 -56.75 -49.3204 -70.7665 -56.8 -49.1554 -70.7063 -56.85 -48.9855 -70.6462 -56.9 -48.8101 -70.5862 -56.95 -48.6288 -70.5262 -57 -48.441 -70.4664 -57.05 -48.2462 -70.4067 -57.1 -48.0436 -70.347 -57.15 -47.8325 -70.2876 -57.2 -47.6121 -70.2282 -57.25 -47.3813 -70.169 -57.3 -47.1392 -70.1099 -57.35 -46.8844 -70.051 -57.4 -46.6156 -69.9922 -57.45 -46.3312 -69.9336 -57.5 -46.0292 -69.8752 -57.55 -45.7077 -69.8169 -57.6 -45.364 -69.7588 -57.65 -44.9955 -69.7009 -57.7 -44.5988 -69.6432 -57.75 -44.1699 -69.5856 -57.8 -43.7044 -69.5282 -57.85 -43.1968 -69.4711 -57.9 -42.6409 -69.4141 -57.95 -42.0289 -69.3574 -58 -41.3519 -69.3009 -58.05 -40.599 -69.2446 -58.1 -39.7571 -69.1885 -58.15 -38.8105 -69.1326 -58.2 -37.7401 -69.077 -58.25 -36.5231 -69.0216 -58.3 -35.1319 -68.9665 -58.35 -33.5339 -68.9116 -58.4 -31.691 -68.8569 -58.45 -29.5596 -68.8025 -58.5 -27.0924 -68.7483 -58.55 -24.2422 -68.6943 -58.6 -20.9687 -68.6406 -58.65 -17.2511 -68.5871 -58.7 -13.1052 -68.5338 -58.75 -8.60488 -68.4808 -58.8 -3.89949 -68.428 -58.85 0.784278 -68.3755 -58.9 5.16768 -68.3231 -58.95 8.97186 -68.271 -59 11.9773 -68.2192 -59.05 14.0642 -68.1675 -59.1 15.2185 -68.1161 -59.15 15.51 -68.0649 -59.2 15.0581 -68.0138 -59.25 14.001 -67.9629 -59.3 12.4734 -67.9121 -59.35 10.5954 -67.8615 -59.4 8.46758 -67.8108 -59.45 6.17076 -67.7602 -59.5 3.76829 -67.7095 -59.55 1.30861 -67.6586 -59.6 -1.17187 -67.6075 -59.65 -3.64625 -67.556 -59.7 -6.09506 -67.5039 -59.75 -8.50453 -67.4511 -59.8 -10.8652 -67.3973 -59.85 -13.171 -67.3422 -59.9 -15.4183 -67.2854 -59.95 -17.6054 -67.2264 -60 -19.7322 -67.1646 -60.05 -21.7996 -67.0992 -60.1 -23.8097 -67.0294 -60.15 -25.7656 -66.954 -60.2 -27.6709 -66.8715 -60.25 -29.5303 -66.7802 -60.3 -31.3491 -66.6779 -60.35 -33.1331 -66.5621 -60.4 -34.889 -66.4293 -60.45 -36.6237 -66.2757 -60.5 -38.3444 -66.0963 -60.55 -40.0581 -65.885 -60.6 -41.7716 -65.6343 -60.65 -43.4906 -65.335 -60.7 -45.2196 -64.9757 -60.75 -46.9605 -64.5425 -60.8 -48.7124 -64.0181 -60.85 -50.4705 -63.3813 -60.9 -52.2251 -62.6057 -60.95 -53.9616 -61.6587 -61 -55.6605 -60.5 -61.05 -57.2987 -59.0788 -61.1 -58.851 -57.3315 -61.15 -60.2934 -55.177 -61.2 -61.6063 -52.5102 -61.25 -62.7764 -49.1923 -61.3 -63.7982 -45.0349 -61.35 -64.6743 -39.7761 -61.4 -65.4129 -33.0494 -61.45 -66.0269 -24.3704 -61.5 -66.531 -13.2458 -61.55 -66.9402 0.330747 -61.6 -67.2688 14.8919 -61.65 -67.5296 27.3958 -61.7 -67.7335 35.5654 -61.75 -67.89 39.619 -61.8 -68.0069 41.0303 -61.85 -68.0907 41.0289 -61.9 -68.1466 40.2825 -61.95 -68.1792 39.0967 -62 -68.1921 37.6081 -62.05 -68.1883 35.8852 -62.1 -68.1702 33.97 -62.15 -68.1401 31.8943 -62.2 -68.0996 29.6851 -62.25 -68.0503 27.3668 -62.3 -67.9933 24.9618 -62.35 -67.9298 22.4902 -62.4 -67.8605 19.97 -62.45 -67.7862 17.4173 -62.5 -67.7077 14.8458 -62.55 -67.6254 12.2674 -62.6 -67.5397 9.69193 -62.65 -67.4512 7.12744 -62.7 -67.3601 4.58042 -62.75 -67.2667 2.05582 -62.8 -67.1712 -0.442616 -62.85 -67.074 -2.91241 -62.9 -66.9752 -5.35196 -62.95 -66.8749 -7.76072 -63 -66.7733 -10.1388 -63.05 -66.6705 -12.4871 -63.1 -66.5666 -14.8075 -63.15 -66.4618 -17.1023 -63.2 -66.356 -19.3751 -63.25 -66.2494 -21.6306 -63.3 -66.1421 -23.8747 -63.35 -66.0341 -26.1154 -63.4 -65.9254 -28.3631 -63.45 -65.8162 -30.6307 -63.5 -65.7064 -32.9348 -63.55 -65.596 -35.2956 -63.6 -65.4852 -37.738 -63.65 -65.374 -40.2905 -63.7 -65.2623 -42.9846 -63.75 -65.1503 -45.8517 -63.8 -65.0379 -48.9169 -63.85 -64.9252 -52.188 -63.9 -64.8121 -55.6396 -63.95 -64.6988 -59.1947 -64 -64.5852 -62.712 -64.05 -64.4714 -65.9978 -64.1 -64.3573 -68.8543 -64.15 -64.2431 -71.1483 -64.2 -64.1286 -72.8561 -64.25 -64.014 -74.0495 -64.3 -63.8993 -74.8454 -64.35 -63.7844 -75.3601 -64.4 -63.6694 -75.6864 -64.45 -63.5543 -75.8902 -64.5 -63.4391 -76.0156 -64.55 -63.3238 -76.0908 -64.6 -63.2085 -76.1337 -64.65 -63.0932 -76.1556 -64.7 -62.9778 -76.1638 -64.75 -62.8624 -76.1629 -64.8 -62.747 -76.1557 -64.85 -62.6316 -76.1443 -64.9 -62.5162 -76.1298 -64.95 -62.4009 -76.1131 -65 -62.2856 -76.0948 -65.05 -62.1704 -76.0752 -65.1 -62.0553 -76.0545 -65.15 -61.9403 -76.033 -65.2 -61.8253 -76.0108 -65.25 -61.7105 -75.9879 -65.3 -61.5958 -75.9644 -65.35 -61.4812 -75.9403 -65.4 -61.3667 -75.9157 -65.45 -61.2524 -75.8905 -65.5 -61.1382 -75.8649 -65.55 -61.0243 -75.8387 -65.6 -60.9104 -75.812 -65.65 -60.7968 -75.7849 -65.7 -60.6834 -75.7572 -65.75 -60.5701 -75.7291 -65.8 -60.4571 -75.7005 -65.85 -60.3442 -75.6713 -65.9 -60.2316 -75.6417 -65.95 -60.1192 -75.6116 -66 -60.0071 -75.5809 -66.05 -59.8951 -75.5498 -66.1 -59.7834 -75.5181 -66.15 -59.672 -75.486 -66.2 -59.5608 -75.4533 -66.25 -59.4498 -75.4202 -66.3 -59.3391 -75.3865 -66.35 -59.2286 -75.3523 -66.4 -59.1184 -75.3176 -66.45 -59.0084 -75.2824 -66.5 -58.8987 -75.2467 -66.55 -58.7893 -75.2105 -66.6 -58.6801 -75.1737 -66.65 -58.5712 -75.1365 -66.7 -58.4626 -75.0987 -66.75 -58.3542 -75.0604 -66.8 -58.246 -75.0216 -66.85 -58.1381 -74.9823 -66.9 -58.0305 -74.9425 -66.95 -57.9231 -74.9022 -67 -57.816 -74.8613 -67.05 -57.7091 -74.82 -67.1 -57.6025 -74.7782 -67.15 -57.4961 -74.7358 -67.2 -57.3899 -74.693 -67.25 -57.2839 -74.6497 -67.3 -57.1782 -74.6058 -67.35 -57.0727 -74.5615 -67.4 -56.9674 -74.5167 -67.45 -56.8623 -74.4715 -67.5 -56.7574 -74.4257 -67.55 -56.6526 -74.3795 -67.6 -56.5481 -74.3328 -67.65 -56.4437 -74.2857 -67.7 -56.3395 -74.2381 -67.75 -56.2355 -74.1901 -67.8 -56.1315 -74.1416 -67.85 -56.0277 -74.0926 -67.9 -55.9241 -74.0433 -67.95 -55.8205 -73.9935 -68 -55.717 -73.9433 -68.05 -55.6137 -73.8926 -68.1 -55.5103 -73.8416 -68.15 -55.4071 -73.7902 -68.2 -55.3039 -73.7383 -68.25 -55.2007 -73.6861 -68.3 -55.0975 -73.6335 -68.35 -54.9943 -73.5805 -68.4 -54.891 -73.5272 -68.45 -54.7878 -73.4735 -68.5 -54.6845 -73.4194 -68.55 -54.5811 -73.365 -68.6 -54.4776 -73.3103 -68.65 -54.3739 -73.2552 -68.7 -54.2702 -73.1999 -68.75 -54.1662 -73.1442 -68.8 -54.0621 -73.0883 -68.85 -53.9577 -73.032 -68.9 -53.8531 -72.9755 -68.95 -53.7482 -72.9187 -69 -53.643 -72.8616 -69.05 -53.5375 -72.8043 -69.1 -53.4317 -72.7468 -69.15 -53.3254 -72.689 -69.2 -53.2186 -72.631 -69.25 -53.1114 -72.5727 -69.3 -53.0037 -72.5143 -69.35 -52.8955 -72.4557 -69.4 -52.7866 -72.3969 -69.45 -52.6771 -72.3379 -69.5 -52.5669 -72.2787 -69.55 -52.4559 -72.2194 -69.6 -52.3442 -72.1599 -69.65 -52.2316 -72.1003 -69.7 -52.118 -72.0406 -69.75 -52.0034 -71.9808 -69.8 -51.8878 -71.9209 -69.85 -51.7711 -71.8608 -69.9 -51.6531 -71.8007 -69.95 -51.5338 -71.7405 -70 -51.4131 -71.6802 -70.05 -51.2909 -71.6198 -70.1 -51.1671 -71.5594 -70.15 -51.0416 -71.499 -70.2 -50.9142 -71.4385 -70.25 -50.7848 -71.378 -70.3 -50.6533 -71.3175 -70.35 -50.5195 -71.257 -70.4 -50.3833 -71.1965 -70.45 -50.2444 -71.1359 -70.5 -50.1026 -71.0755 -70.55 -49.9578 -71.015 -70.6 -49.8096 -70.9546 -70.65 -49.6578 -70.8942 -70.7 -49.5022 -70.8339 -70.75 -49.3424 -70.7737 -70.8 -49.178 -70.7135 -70.85 -49.0087 -70.6534 -70.9 -48.834 -70.5933 -70.95 -48.6535 -70.5334 -71 -48.4666 -70.4735 -71.05 -48.2726 -70.4138 -71.1 -48.0711 -70.3542 -71.15 -47.8611 -70.2947 -71.2 -47.6419 -70.2353 -71.25 -47.4126 -70.1761 -71.3 -47.1719 -70.117 -71.35 -46.9188 -70.058 -71.4 -46.6519 -69.9992 -71.45 -46.3695 -69.9406 -71.5 -46.0699 -69.8822 -71.55 -45.7509 -69.8239 -71.6 -45.4103 -69.7658 -71.65 -45.0451 -69.7078 -71.7 -44.6521 -69.6501 -71.75 -44.2276 -69.5925 -71.8 -43.767 -69.5351 -71.85 -43.2651 -69.4779 -71.9 -42.7157 -69.421 -71.95 -42.1113 -69.3642 -72 -41.4431 -69.3076 -72.05 -40.7005 -69.2513 -72.1 -39.8707 -69.1952 -72.15 -38.9383 -69.1393 -72.2 -37.8848 -69.0837 -72.25 -36.6877 -69.0283 -72.3 -35.3203 -68.9731 -72.35 -33.7505 -68.9182 -72.4 -31.9409 -68.8635 -72.45 -29.8485 -68.809 -72.5 -27.4264 -68.7548 -72.55 -24.627 -68.7008 -72.6 -21.4085 -68.647 -72.65 -17.7468 -68.5935 -72.7 -13.652 -68.5402 -72.75 -9.18931 -68.4872 -72.8 -4.49808 -68.4343 -72.85 0.204015 -68.3818 -72.9 4.64229 -68.3294 -72.95 8.53442 -68.2773 -73 11.6505 -68.2254 -73.05 13.8569 -68.1737 -73.1 15.127 -68.1223 -73.15 15.5219 -68.071 -73.2 15.1566 -68.0199 -73.25 14.1684 -67.969 -73.3 12.6933 -67.9182 -73.35 10.8536 -67.8676 -73.4 8.75243 -67.8169 -73.45 6.4731 -67.7663 -73.5 4.08098 -67.7156 -73.55 1.62624 -67.6648 -73.6 -0.853328 -67.6137 -73.65 -3.32976 -67.5622 -73.7 -5.78274 -67.5102 -73.75 -8.19786 -67.4576 -73.8 -10.5652 -67.4039 -73.85 -12.8783 -67.349 -73.9 -15.1332 -67.2924 -73.95 -17.328 -67.2337 -74 -19.4625 -67.1723 -74.05 -21.5374 -67.1075 -74.1 -23.5547 -67.0383 -74.15 -25.5173 -66.9636 -74.2 -27.4288 -66.8821 -74.25 -29.2938 -66.792 -74.3 -31.1174 -66.6913 -74.35 -32.9056 -66.5773 -74.4 -34.6648 -66.447 -74.45 -36.4019 -66.2962 -74.5 -38.124 -66.1204 -74.55 -39.8382 -65.9135 -74.6 -41.5514 -65.6683 -74.65 -43.2695 -65.3757 -74.7 -44.9971 -65.0248 -74.75 -46.7365 -64.6018 -74.8 -48.4873 -64.09 -74.85 -50.245 -63.4688 -74.9 -52.0008 -62.7124 -74.95 -53.7408 -61.7892 -75 -55.4459 -60.6598 -75.05 -57.0933 -59.2751 -75.1 -58.6581 -57.5731 -75.15 -60.1159 -55.4753 -75.2 -61.4463 -52.8802 -75.25 -62.6352 -49.6538 -75.3 -63.6761 -45.6152 -75.35 -64.5704 -40.5133 -75.4 -65.3261 -33.9966 -75.45 -65.9552 -25.594 -75.5 -66.4725 -14.7972 -75.55 -66.8931 -1.48988 -75.6 -67.2312 13.096 -75.65 -67.5 26.0315 -75.7 -67.7106 34.7856 -75.75 -67.8727 39.2846 -75.8 -67.9943 40.9498 -75.85 -68.0819 41.0798 -75.9 -68.1412 40.4055 -75.95 -68.1765 39.2655 -76 -68.1917 37.8106 -76.05 -68.1899 36.1147 -76.1 -68.1735 34.2219 -76.15 -68.1448 32.165 -76.2 -68.1056 29.9712 -76.25 -68.0573 27.6655 -76.3 -68.0012 25.2703 -76.35 -67.9385 22.8061 -76.4 -67.8699 20.2912 -76.45 -67.7962 17.7418 -76.5 -67.7182 15.172 -76.55 -67.6363 12.5939 -76.6 -67.5511 10.0175 -76.65 -67.4629 7.45128 -76.7 -67.3721 4.90174 -76.75 -67.2789 2.37409 -76.8 -67.1838 -0.127837 -76.85 -67.0868 -2.60135 -76.9 -66.9881 -5.0448 -76.95 -66.888 -7.45742 -77 -66.7865 -9.83936 -77.05 -66.6839 -12.1914 -77.1 -66.5802 -14.5151 -77.15 -66.4754 -16.8131 -77.2 -66.3698 -19.0884 -77.25 -66.2633 -21.3457 -77.3 -66.1561 -23.5909 -77.35 -66.0481 -25.8316 -77.4 -65.9396 -28.0777 -77.45 -65.8304 -30.3419 -77.5 -65.7206 -32.6403 -77.55 -65.6104 -34.9928 -77.6 -65.4996 -37.4232 -77.65 -65.3884 -39.9601 -77.7 -65.2768 -42.6345 -77.75 -65.1648 -45.4781 -77.8 -65.0525 -48.5172 -77.85 -64.9398 -51.7626 -77.9 -64.8268 -55.1945 -77.95 -64.7135 -58.7429 -78 -64.6 -62.275 -78.05 -64.4862 -65.6017 -78.1 -64.3721 -68.5217 -78.15 -64.2579 -70.8906 -78.2 -64.1435 -72.6703 -78.25 -64.0289 -73.9228 -78.3 -63.9142 -74.7623 -78.35 -63.7993 -75.307 -78.4 -63.6843 -75.6529 -78.45 -63.5692 -75.8695 -78.5 -63.454 -76.003 -78.55 -63.3388 -76.0833 -78.6 -63.2235 -76.1296 -78.65 -63.1081 -76.1537 -78.7 -62.9927 -76.1634 -78.75 -62.8773 -76.1634 -78.8 -62.7619 -76.1569 -78.85 -62.6465 -76.1459 -78.9 -62.5312 -76.1318 -78.95 -62.4158 -76.1153 -79 -62.3006 -76.0972 -79.05 -62.1854 -76.0777 -79.1 -62.0702 -76.0572 -79.15 -61.9552 -76.0358 -79.2 -61.8402 -76.0136 -79.25 -61.7253 -75.9908 -79.3 -61.6106 -75.9674 -79.35 -61.496 -75.9434 -79.4 -61.3815 -75.9188 -79.45 -61.2672 -75.8937 -79.5 -61.153 -75.8681 -79.55 -61.039 -75.842 -79.6 -60.9252 -75.8154 -79.65 -60.8115 -75.7884 -79.7 -60.698 -75.7608 -79.75 -60.5848 -75.7327 -79.8 -60.4717 -75.7041 -79.85 -60.3588 -75.675 -79.9 -60.2462 -75.6455 -79.95 -60.1338 -75.6154 -80 -60.0216 -75.5848 -80.05 -59.9096 -75.5538 -80.1 -59.7979 -75.5222 -80.15 -59.6864 -75.4901 -80.2 -59.5751 -75.4575 -80.25 -59.4641 -75.4244 -80.3 -59.3534 -75.3908 -80.35 -59.2429 -75.3567 -80.4 -59.1326 -75.322 -80.45 -59.0227 -75.2869 -80.5 -58.9129 -75.2513 -80.55 -58.8035 -75.2151 -80.6 -58.6943 -75.1784 -80.65 -58.5853 -75.1412 -80.7 -58.4766 -75.1035 -80.75 -58.3682 -75.0653 -80.8 -58.26 -75.0265 -80.85 -58.1521 -74.9873 -80.9 -58.0444 -74.9476 -80.95 -57.937 -74.9073 -81 -57.8298 -74.8665 -81.05 -57.7229 -74.8253 -81.1 -57.6162 -74.7835 -81.15 -57.5098 -74.7412 -81.2 -57.4036 -74.6984 -81.25 -57.2976 -74.6552 -81.3 -57.1919 -74.6114 -81.35 -57.0863 -74.5672 -81.4 -56.981 -74.5224 -81.45 -56.8758 -74.4772 -81.5 -56.7709 -74.4316 -81.55 -56.6662 -74.3854 -81.6 -56.5616 -74.3388 -81.65 -56.4572 -74.2917 -81.7 -56.353 -74.2442 -81.75 -56.2489 -74.1962 -81.8 -56.1449 -74.1477 -81.85 -56.0411 -74.0989 -81.9 -55.9375 -74.0496 -81.95 -55.8339 -73.9998 -82 -55.7304 -73.9497 -82.05 -55.627 -73.8991 -82.1 -55.5237 -73.8481 -82.15 -55.4204 -73.7967 -82.2 -55.3172 -73.7449 -82.25 -55.214 -73.6927 -82.3 -55.1108 -73.6402 -82.35 -55.0076 -73.5872 -82.4 -54.9044 -73.5339 -82.45 -54.8011 -73.4803 -82.5 -54.6978 -73.4263 -82.55 -54.5944 -73.3719 -82.6 -54.4909 -73.3172 -82.65 -54.3873 -73.2622 -82.7 -54.2835 -73.2069 -82.75 -54.1796 -73.1513 -82.8 -54.0755 -73.0954 -82.85 -53.9712 -73.0392 -82.9 -53.8666 -72.9827 -82.95 -53.7618 -72.9259 -83 -53.6566 -72.8689 -83.05 -53.5512 -72.8116 -83.1 -53.4453 -72.7541 -83.15 -53.3391 -72.6963 -83.2 -53.2324 -72.6383 -83.25 -53.1253 -72.5801 -83.3 -53.0176 -72.5217 -83.35 -52.9095 -72.4631 -83.4 -52.8007 -72.4043 -83.45 -52.6913 -72.3454 -83.5 -52.5811 -72.2862 -83.55 -52.4703 -72.2269 -83.6 -52.3586 -72.1675 -83.65 -52.2461 -72.1079 -83.7 -52.1327 -72.0482 -83.75 -52.0182 -71.9884 -83.8 -51.9028 -71.9285 -83.85 -51.7862 -71.8684 -83.9 -51.6684 -71.8083 -83.95 -51.5492 -71.7481 -84 -51.4287 -71.6878 -84.05 -51.3067 -71.6275 -84.1 -51.1831 -71.5671 -84.15 -51.0578 -71.5067 -84.2 -50.9307 -71.4462 -84.25 -50.8016 -71.3857 -84.3 -50.6704 -71.3252 -84.35 -50.5369 -71.2646 -84.4 -50.4009 -71.2041 -84.45 -50.2624 -71.1436 -84.5 -50.121 -71.0831 -84.55 -49.9765 -71.0227 -84.6 -49.8288 -70.9623 -84.65 -49.6775 -70.9019 -84.7 -49.5224 -70.8416 -84.75 -49.3632 -70.7813 -84.8 -49.1994 -70.7211 -84.85 -49.0307 -70.661 -84.9 -48.8567 -70.6009 -84.95 -48.677 -70.541 -85 -48.4909 -70.4811 -85.05 -48.2979 -70.4214 -85.1 -48.0973 -70.3617 -85.15 -47.8885 -70.3022 -85.2 -47.6705 -70.2428 -85.25 -47.4425 -70.1836 -85.3 -47.2034 -70.1245 -85.35 -46.9519 -70.0655 -85.4 -46.6868 -70.0067 -85.45 -46.4065 -69.948 -85.5 -46.1092 -69.8896 -85.55 -45.7929 -69.8313 -85.6 -45.4551 -69.7731 -85.65 -45.0932 -69.7152 -85.7 -44.704 -69.6574 -85.75 -44.2837 -69.5998 -85.8 -43.8279 -69.5424 -85.85 -43.3316 -69.4852 -85.9 -42.7887 -69.4282 -85.95 -42.1917 -69.3714 -86 -41.5322 -69.3148 -86.05 -40.7998 -69.2584 -86.1 -39.9819 -69.2023 -86.15 -39.0635 -69.1464 -86.2 -38.0266 -69.0907 -86.25 -36.8492 -69.0353 -86.3 -35.5051 -68.9801 -86.35 -33.9631 -68.9251 -86.4 -32.1863 -68.8704 -86.45 -30.1324 -68.8159 -86.5 -27.755 -68.7616 -86.55 -25.0062 -68.7076 -86.6 -21.8429 -68.6538 -86.65 -18.238 -68.6003 -86.7 -14.196 -68.5469 -86.75 -9.77407 -68.4939 -86.8 -5.10133 -68.441 -86.85 -0.386083 -68.3884 -86.9 4.10199 -68.336 -86.95 8.07816 -68.2839 -87 11.3028 -68.232 -87.05 13.6287 -68.1803 -87.1 15.0163 -68.1288 -87.15 15.517 -68.0775 -87.2 15.2411 -68.0264 -87.25 14.3245 -67.9755 -87.3 12.9042 -67.9247 -87.35 11.1048 -67.874 -87.4 9.03195 -67.8233 -87.45 6.77132 -67.7727 -87.5 4.39049 -67.722 -87.55 1.94139 -67.6712 -87.6 -0.536757 -67.6202 -87.65 -3.01486 -67.5688 -87.7 -5.47174 -67.5169 -87.75 -7.89232 -67.4643 -87.8 -10.2662 -67.4108 -87.85 -12.5864 -67.356 -87.9 -14.8489 -67.2997 -87.95 -17.0514 -67.2413 -88 -19.1936 -67.1803 -88.05 -21.276 -67.1159 -88.1 -23.3005 -67.0473 -88.15 -25.2699 -66.9734 -88.2 -27.1878 -66.8929 -88.25 -29.0584 -66.804 -88.3 -30.8871 -66.7048 -88.35 -32.6794 -66.5927 -88.4 -34.4419 -66.4646 -88.45 -36.1814 -66.3167 -88.5 -37.905 -66.1444 -88.55 -39.6198 -65.9418 -88.6 -41.3328 -65.7019 -88.65 -43.05 -65.416 -88.7 -44.7762 -65.0731 -88.75 -46.514 -64.6602 -88.8 -48.2635 -64.1608 -88.85 -50.0207 -63.5548 -88.9 -51.7775 -62.8172 -88.95 -53.5204 -61.9173 -89 -55.2312 -60.8167 -89.05 -56.8874 -59.4676 -89.1 -58.464 -57.8101 -89.15 -59.9367 -55.7678 -89.2 -61.2843 -53.2427 -89.25 -62.4918 -50.1056 -89.3 -63.5516 -46.1827 -89.35 -64.4643 -41.2335 -89.4 -65.237 -34.9209 -89.45 -65.8816 -26.7882 -89.5 -66.4123 -16.3185 -89.55 -66.8443 -3.30161 -89.6 -67.1922 11.2583 -89.65 -67.4692 24.5843 -89.7 -67.6867 33.9283 -89.75 -67.8545 38.9017 -89.8 -67.9808 40.8443 -89.85 -68.0724 41.1183 -89.9 -68.135 40.5218 -89.95 -68.1732 39.4303 -90 -68.1908 38.0104 -90.05 -68.191 36.3424 -90.1 -68.1763 34.4728 -90.15 -68.1491 32.4351 -90.2 -68.1111 30.2574 -90.25 -68.0639 27.9647 -90.3 -68.0088 25.5797 -90.35 -67.9468 23.1232 -90.4 -67.8789 20.6138 -90.45 -67.8059 18.0679 -90.5 -67.7284 15.5 -90.55 -67.6469 12.9224 -90.6 -67.5621 10.3453 -90.65 -67.4743 7.77735 -90.7 -67.3838 5.22535 -90.75 -67.2909 2.69468 -90.8 -67.196 0.189299 -90.85 -67.0992 -2.28793 -90.9 -67.0008 -4.73528 -90.95 -66.9008 -7.15185 -91 -66.7996 -9.53765 -91.05 -66.6971 -11.8934 -91.1 -66.5934 -14.2206 -91.15 -66.4888 -16.5217 -91.2 -66.3833 -18.7997 -91.25 -66.2769 -21.059 -91.3 -66.1698 -23.3053 -91.35 -66.062 -25.5461 -91.4 -65.9535 -27.7909 -91.45 -65.8443 -30.052 -91.5 -65.7347 -32.345 -91.55 -65.6245 -34.6893 -91.6 -65.5138 -37.1084 -91.65 -65.4026 -39.63 -91.7 -65.2911 -42.2851 -91.75 -65.1791 -45.1055 -91.8 -65.0668 -48.1186 -91.85 -64.9542 -51.3381 -91.9 -64.8412 -54.7488 -91.95 -64.728 -58.2884 -92 -64.6145 -61.8321 -92.05 -64.5007 -65.1966 -92.1 -64.3867 -68.1783 -92.15 -64.2725 -70.622 -92.2 -64.1581 -72.4749 -92.25 -64.0435 -73.7887 -92.3 -63.9288 -74.674 -92.35 -63.814 -75.2503 -92.4 -63.699 -75.6172 -92.45 -63.5839 -75.8473 -92.5 -63.4687 -75.9894 -92.55 -63.3535 -76.0753 -92.6 -63.2382 -76.1251 -92.65 -63.1228 -76.1516 -92.7 -63.0074 -76.1627 -92.75 -62.8921 -76.1638 -92.8 -62.7767 -76.158 -92.85 -62.6613 -76.1475 -92.9 -62.5459 -76.1337 -92.95 -62.4306 -76.1175 -93 -62.3153 -76.0996 -93.05 -62.2001 -76.0803 -93.1 -62.0849 -76.0599 -93.15 -61.9698 -76.0386 -93.2 -61.8549 -76.0165 -93.25 -61.74 -75.9937 -93.3 -61.6252 -75.9704 -93.35 -61.5106 -75.9464 -93.4 -61.3961 -75.922 -93.45 -61.2818 -75.8969 -93.5 -61.1676 -75.8714 -93.55 -61.0535 -75.8454 -93.6 -60.9397 -75.8189 -93.65 -60.826 -75.7918 -93.7 -60.7125 -75.7643 -93.75 -60.5992 -75.7363 -93.8 -60.4861 -75.7078 -93.85 -60.3732 -75.6788 -93.9 -60.2606 -75.6493 -93.95 -60.1481 -75.6193 -94 -60.0359 -75.5887 -94.05 -59.9239 -75.5577 -94.1 -59.8121 -75.5262 -94.15 -59.7006 -75.4942 -94.2 -59.5893 -75.4617 -94.25 -59.4783 -75.4287 -94.3 -59.3675 -75.3951 -94.35 -59.257 -75.3611 -94.4 -59.1467 -75.3265 -94.45 -59.0367 -75.2914 -94.5 -58.9269 -75.2558 -94.55 -58.8174 -75.2197 -94.6 -58.7082 -75.1831 -94.65 -58.5992 -75.146 -94.7 -58.4905 -75.1083 -94.75 -58.382 -75.0702 -94.8 -58.2738 -75.0315 -94.85 -58.1658 -74.9923 -94.9 -58.0581 -74.9526 -94.95 -57.9507 -74.9124 -95 -57.8435 -74.8717 -95.05 -57.7366 -74.8305 -95.1 -57.6298 -74.7888 -95.15 -57.5234 -74.7466 -95.2 -57.4171 -74.7039 -95.25 -57.3111 -74.6607 -95.3 -57.2053 -74.617 -95.35 -57.0998 -74.5728 -95.4 -56.9944 -74.5282 -95.45 -56.8892 -74.483 -95.5 -56.7843 -74.4374 -95.55 -56.6795 -74.3913 -95.6 -56.5749 -74.3448 -95.65 -56.4705 -74.2977 -95.7 -56.3663 -74.2502 -95.75 -56.2622 -74.2023 -95.8 -56.1582 -74.1539 -95.85 -56.0544 -74.1051 -95.9 -55.9507 -74.0559 -95.95 -55.8471 -74.0062 -96 -55.7436 -73.9561 -96.05 -55.6402 -73.9055 -96.1 -55.5369 -73.8546 -96.15 -55.4336 -73.8033 -96.2 -55.3303 -73.7515 -96.25 -55.2271 -73.6994 -96.3 -55.1239 -73.6469 -96.35 -55.0208 -73.594 -96.4 -54.9175 -73.5407 -96.45 -54.8143 -73.4871 -96.5 -54.711 -73.4332 -96.55 -54.6076 -73.3789 -96.6 -54.5041 -73.3242 -96.65 -54.4005 -73.2693 -96.7 -54.2968 -73.214 -96.75 -54.1929 -73.1584 -96.8 -54.0888 -73.1025 -96.85 -53.9845 -73.0463 -96.9 -53.8799 -72.9899 -96.95 -53.7751 -72.9332 -97 -53.6701 -72.8762 -97.05 -53.5646 -72.8189 -97.1 -53.4588 -72.7614 -97.15 -53.3527 -72.7037 -97.2 -53.2461 -72.6457 -97.25 -53.139 -72.5876 -97.3 -53.0314 -72.5292 -97.35 -52.9233 -72.4706 -97.4 -52.8146 -72.4118 -97.45 -52.7052 -72.3529 -97.5 -52.5952 -72.2938 -97.55 -52.4845 -72.2345 -97.6 -52.3729 -72.1751 -97.65 -52.2605 -72.1155 -97.7 -52.1472 -72.0558 -97.75 -52.0329 -71.996 -97.8 -51.9176 -71.9361 -97.85 -51.8011 -71.8761 -97.9 -51.6834 -71.816 -97.95 -51.5645 -71.7558 -98 -51.4442 -71.6955 -98.05 -51.3224 -71.6352 -98.1 -51.199 -71.5748 -98.15 -51.0739 -71.5144 -98.2 -50.947 -71.4539 -98.25 -50.8181 -71.3934 -98.3 -50.6872 -71.3329 -98.35 -50.554 -71.2724 -98.4 -50.4184 -71.2118 -98.45 -50.2802 -71.1513 -98.5 -50.1391 -71.0908 -98.55 -49.9951 -71.0304 -98.6 -49.8478 -70.97 -98.65 -49.697 -70.9096 -98.7 -49.5424 -70.8493 -98.75 -49.3837 -70.789 -98.8 -49.2205 -70.7288 -98.85 -49.0525 -70.6686 -98.9 -48.8792 -70.6086 -98.95 -48.7002 -70.5486 -99 -48.515 -70.4887 -99.05 -48.3229 -70.429 -99.1 -48.1233 -70.3693 -99.15 -47.9156 -70.3098 -99.2 -47.6988 -70.2504 -99.25 -47.4721 -70.1911 -99.3 -47.2345 -70.132 -99.35 -46.9847 -70.073 -99.4 -46.7214 -70.0142 -99.45 -46.4431 -69.9555 -99.5 -46.1481 -69.897 -99.55 -45.8343 -69.8387 -99.6 -45.4994 -69.7805 -99.65 -45.1407 -69.7225 -99.7 -44.7552 -69.6647 -99.75 -44.3391 -69.6071 -99.8 -43.8881 -69.5497 -99.85 -43.3973 -69.4924 -99.9 -42.8607 -69.4354 -99.95 -42.2711 -69.3786 -100 -41.6201 -69.322 -100.05 -40.8976 -69.2656 -100.1 -40.0913 -69.2094 -100.15 -39.1867 -69.1535 -100.2 -38.166 -69.0978 -100.25 -37.0079 -69.0423 -100.3 -35.6867 -68.9871 -100.35 -34.1718 -68.9321 -100.4 -32.4271 -68.8773 -100.45 -30.4111 -68.8228 -100.5 -28.0776 -68.7685 -100.55 -25.3787 -68.7145 -100.6 -22.2702 -68.6607 -100.65 -18.7222 -68.6071 -100.7 -14.734 -68.5537 -100.75 -10.3549 -68.5006 -100.8 -5.70415 -68.4477 -100.85 -0.980246 -68.3951 -100.9 3.55289 -68.3427 -100.95 7.60912 -68.2905 -101 10.9399 -68.2386 -101.05 13.3848 -68.1868 -101.1 14.8906 -68.1353 -101.15 15.4991 -68.084 -101.2 15.3149 -68.0329 -101.25 14.4721 -67.9819 -101.3 13.1087 -67.9311 -101.35 11.3514 -67.8804 -101.4 9.30815 -67.8298 -101.45 7.06733 -67.7792 -101.5 4.69862 -67.7285 -101.55 2.2558 -67.6777 -101.6 -0.220455 -67.6267 -101.65 -2.69989 -67.5753 -101.7 -5.16043 -67.5235 -101.75 -7.5863 -67.471 -101.8 -9.96655 -67.4177 -101.85 -12.2939 -67.3631 -101.9 -14.5639 -67.307 -101.95 -16.7741 -67.2489 -102 -18.9239 -67.1882 -102.05 -21.0139 -67.1243 -102.1 -23.0457 -67.0563 -102.15 -25.022 -66.9832 -102.2 -26.9462 -66.9036 -102.25 -28.8226 -66.8159 -102.3 -30.6563 -66.7181 -102.35 -32.4529 -66.6078 -102.4 -34.2188 -66.4819 -102.45 -35.9608 -66.3368 -102.5 -37.686 -66.1679 -102.55 -39.4015 -65.9695 -102.6 -41.1144 -65.7349 -102.65 -42.8308 -65.4553 -102.7 -44.5556 -65.1204 -102.75 -46.2919 -64.7173 -102.8 -48.04 -64.2299 -102.85 -49.7966 -63.6387 -102.9 -51.5541 -62.9195 -102.95 -53.2998 -62.0422 -103 -55.0158 -60.9697 -103.05 -56.6802 -59.6553 -103.1 -58.2684 -58.0409 -103.15 -59.7556 -56.0526 -103.2 -61.1202 -53.5955 -103.25 -62.3461 -50.5449 -103.3 -63.4248 -46.7339 -103.35 -64.356 -41.9318 -103.4 -65.146 -35.8158 -103.45 -65.8061 -27.944 -103.5 -66.3504 -17.7968 -103.55 -66.7942 -5.0852 -103.6 -67.1521 9.4009 -103.65 -67.4374 23.0686 -103.7 -67.6619 32.9979 -103.75 -67.8355 38.47 -103.8 -67.9667 40.7126 -103.85 -68.0625 41.1433 -103.9 -68.1285 40.6305 -103.95 -68.1696 39.59 -104 -68.1896 38.2064 -104.05 -68.1918 36.567 -104.1 -68.1789 34.721 -104.15 -68.1532 32.7032 -104.2 -68.1165 30.5419 -104.25 -68.0704 28.2625 -104.3 -68.0162 25.8881 -104.35 -67.9551 23.4396 -104.4 -67.8879 20.936 -104.45 -67.8154 18.3939 -104.5 -67.7385 15.8281 -104.55 -67.6575 13.2511 -104.6 -67.5731 10.6735 -104.65 -67.4856 8.10393 -104.7 -67.3954 5.54959 -104.75 -67.3029 3.01594 -104.8 -67.2082 0.507179 -104.85 -67.1117 -1.97378 -104.9 -67.0134 -4.42497 -104.95 -66.9137 -6.84551 -105 -66.8125 -9.23519 -105.05 -66.7102 -11.5947 -105.1 -66.6067 -13.9255 -105.15 -66.5022 -16.2297 -105.2 -66.3968 -18.5104 -105.25 -66.2905 -20.7719 -105.3 -66.1835 -23.0195 -105.35 -66.0757 -25.2604 -105.4 -65.9673 -27.5041 -105.45 -65.8583 -29.7624 -105.5 -65.7487 -32.0503 -105.55 -65.6385 -34.3868 -105.6 -65.5279 -36.795 -105.65 -65.4168 -39.3018 -105.7 -65.3053 -41.9381 -105.75 -65.1934 -44.7358 -105.8 -65.0812 -47.7232 -105.85 -64.9686 -50.9165 -105.9 -64.8556 -54.3052 -105.95 -64.7424 -57.834 -106 -64.6289 -61.3864 -106.05 -64.5152 -64.7851 -106.1 -64.4012 -67.826 -106.15 -64.2871 -70.3436 -106.2 -64.1727 -72.2708 -106.25 -64.0581 -73.6478 -106.3 -63.9434 -74.5808 -106.35 -63.8286 -75.1904 -106.4 -63.7136 -75.5793 -106.45 -63.5986 -75.8237 -106.5 -63.4834 -75.975 -106.55 -63.3682 -76.0667 -106.6 -63.2529 -76.1203 -106.65 -63.1375 -76.1492 -106.7 -63.0222 -76.162 -106.75 -62.9068 -76.1641 -106.8 -62.7914 -76.159 -106.85 -62.676 -76.1491 -106.9 -62.5606 -76.1356 -106.95 -62.4453 -76.1197 -107 -62.33 -76.1019 -107.05 -62.2147 -76.0828 -107.1 -62.0996 -76.0625 -107.15 -61.9845 -76.0413 -107.2 -61.8695 -76.0193 -107.25 -61.7546 -75.9967 -107.3 -61.6398 -75.9734 -107.35 -61.5252 -75.9495 -107.4 -61.4107 -75.9251 -107.45 -61.2963 -75.9002 -107.5 -61.1821 -75.8747 -107.55 -61.0681 -75.8487 -107.6 -60.9542 -75.8223 -107.65 -60.8405 -75.7953 -107.7 -60.727 -75.7678 -107.75 -60.6136 -75.7399 -107.8 -60.5005 -75.7114 -107.85 -60.3876 -75.6825 -107.9 -60.2749 -75.653 -107.95 -60.1624 -75.6231 -108 -60.0502 -75.5927 -108.05 -59.9381 -75.5617 -108.1 -59.8263 -75.5303 -108.15 -59.7148 -75.4983 -108.2 -59.6035 -75.4659 -108.25 -59.4924 -75.4329 -108.3 -59.3816 -75.3994 -108.35 -59.271 -75.3654 -108.4 -59.1607 -75.3309 -108.45 -59.0507 -75.2959 -108.5 -58.9409 -75.2604 -108.55 -58.8313 -75.2243 -108.6 -58.7221 -75.1878 -108.65 -58.6131 -75.1507 -108.7 -58.5043 -75.1132 -108.75 -58.3958 -75.0751 -108.8 -58.2876 -75.0365 -108.85 -58.1796 -74.9974 -108.9 -58.0718 -74.9577 -108.95 -57.9644 -74.9176 -109 -57.8571 -74.877 -109.05 -57.7502 -74.8358 -109.1 -57.6434 -74.7942 -109.15 -57.5369 -74.752 -109.2 -57.4307 -74.7094 -109.25 -57.3246 -74.6662 -109.3 -57.2188 -74.6226 -109.35 -57.1132 -74.5785 -109.4 -57.0078 -74.5339 -109.45 -56.9026 -74.4888 -109.5 -56.7976 -74.4432 -109.55 -56.6929 -74.3972 -109.6 -56.5882 -74.3507 -109.65 -56.4838 -74.3037 -109.7 -56.3795 -74.2563 -109.75 -56.2754 -74.2085 -109.8 -56.1714 -74.1601 -109.85 -56.0676 -74.1114 -109.9 -55.9639 -74.0622 -109.95 -55.8603 -74.0125 -110 -55.7568 -73.9625 -110.05 -55.6534 -73.912 -110.1 -55.55 -73.8611 -110.15 -55.4467 -73.8098 -110.2 -55.3435 -73.7581 -110.25 -55.2403 -73.7061 -110.3 -55.1371 -73.6536 -110.35 -55.0339 -73.6008 -110.4 -54.9307 -73.5476 -110.45 -54.8274 -73.494 -110.5 -54.7242 -73.4401 -110.55 -54.6208 -73.3858 -110.6 -54.5173 -73.3312 -110.65 -54.4137 -73.2763 -110.7 -54.31 -73.2211 -110.75 -54.2061 -73.1655 -110.8 -54.1021 -73.1097 -110.85 -53.9978 -73.0535 -110.9 -53.8933 -72.9971 -110.95 -53.7885 -72.9404 -111 -53.6835 -72.8834 -111.05 -53.5781 -72.8262 -111.1 -53.4723 -72.7688 -111.15 -53.3662 -72.7111 -111.2 -53.2597 -72.6531 -111.25 -53.1526 -72.595 -111.3 -53.0451 -72.5366 -111.35 -52.9371 -72.4781 -111.4 -52.8285 -72.4193 -111.45 -52.7192 -72.3604 -111.5 -52.6093 -72.3013 -111.55 -52.4986 -72.242 -111.6 -52.3872 -72.1826 -111.65 -52.2749 -72.1231 -111.7 -52.1617 -72.0634 -111.75 -52.0475 -72.0036 -111.8 -51.9323 -71.9437 -111.85 -51.816 -71.8837 -111.9 -51.6985 -71.8236 -111.95 -51.5797 -71.7635 -112 -51.4596 -71.7032 -112.05 -51.338 -71.6429 -112.1 -51.2148 -71.5825 -112.15 -51.0899 -71.5221 -112.2 -50.9633 -71.4616 -112.25 -50.8347 -71.4011 -112.3 -50.704 -71.3406 -112.35 -50.5711 -71.2801 -112.4 -50.4358 -71.2195 -112.45 -50.2979 -71.159 -112.5 -50.1573 -71.0985 -112.55 -50.0136 -71.0381 -112.6 -49.8668 -70.9777 -112.65 -49.7164 -70.9173 -112.7 -49.5623 -70.8569 -112.75 -49.4041 -70.7967 -112.8 -49.2415 -70.7364 -112.85 -49.0742 -70.6763 -112.9 -48.9016 -70.6162 -112.95 -48.7233 -70.5563 -113 -48.5389 -70.4964 -113.05 -48.3477 -70.4366 -113.1 -48.1492 -70.3769 -113.15 -47.9425 -70.3174 -113.2 -47.727 -70.2579 -113.25 -47.5016 -70.1987 -113.3 -47.2654 -70.1395 -113.35 -47.0172 -70.0805 -113.4 -46.7557 -70.0217 -113.45 -46.4795 -69.963 -113.5 -46.1867 -69.9045 -113.55 -45.8754 -69.8461 -113.6 -45.5433 -69.7879 -113.65 -45.1878 -69.7299 -113.7 -44.8059 -69.6721 -113.75 -44.3939 -69.6144 -113.8 -43.9477 -69.557 -113.85 -43.4622 -69.4997 -113.9 -42.9318 -69.4427 -113.95 -42.3494 -69.3858 -114 -41.7067 -69.3292 -114.05 -40.9939 -69.2728 -114.1 -40.1991 -69.2166 -114.15 -39.3079 -69.1606 -114.2 -38.3031 -69.1049 -114.25 -37.1638 -69.0494 -114.3 -35.865 -68.9941 -114.35 -34.3766 -68.9391 -114.4 -32.6634 -68.8843 -114.45 -30.6844 -68.8298 -114.5 -28.394 -68.7754 -114.55 -25.7441 -68.7214 -114.6 -22.6899 -68.6675 -114.65 -19.1986 -68.6139 -114.7 -15.265 -68.5605 -114.75 -10.9307 -68.5074 -114.8 -6.30512 -68.4545 -114.85 -1.57693 -68.4018 -114.9 2.99648 -68.3494 -114.95 7.1286 -68.2972 -115 10.5629 -68.2452 -115.05 13.1257 -68.1934 -115.1 14.7504 -68.1419 -115.15 15.4683 -68.0905 -115.2 15.3779 -68.0394 -115.25 14.6111 -67.9884 -115.3 13.3067 -67.9376 -115.35 11.593 -67.8869 -115.4 9.58087 -67.8362 -115.45 7.36096 -67.7856 -115.5 5.00523 -67.735 -115.55 2.56933 -67.6842 -115.6 0.0954577 -67.6332 -115.65 -2.38495 -67.5819 -115.7 -4.84889 -67.5302 -115.75 -7.27987 -67.4778 -115.8 -9.66641 -67.4245 -115.85 -12.0008 -67.3701 -115.9 -14.2783 -67.3142 -115.95 -16.4962 -67.2564 -116 -18.6537 -67.1961 -116.05 -20.7511 -67.1327 -116.1 -22.7902 -67.0653 -116.15 -24.7733 -66.9928 -116.2 -26.7039 -66.9141 -116.25 -28.5862 -66.8276 -116.3 -30.425 -66.7312 -116.35 -32.2259 -66.6226 -116.4 -33.9954 -66.4989 -116.45 -35.7401 -66.3565 -116.5 -37.467 -66.1909 -116.55 -39.1834 -65.9967 -116.6 -40.8963 -65.7671 -116.65 -42.6119 -65.4938 -116.7 -44.3354 -65.1666 -116.75 -46.0702 -64.7729 -116.8 -47.8169 -64.2973 -116.85 -49.5728 -63.7206 -116.9 -51.3308 -63.0192 -116.95 -53.0787 -62.1639 -117 -54.7997 -61.1186 -117.05 -56.472 -59.838 -117.1 -58.0713 -58.2655 -117.15 -59.5727 -56.3296 -117.2 -60.9539 -53.9383 -117.25 -62.1981 -50.9716 -117.3 -63.2958 -47.2686 -117.35 -64.2455 -42.6085 -117.4 -65.0529 -36.6817 -117.45 -65.7288 -29.0621 -117.5 -66.2871 -19.2312 -117.55 -66.7428 -6.83598 -117.6 -67.1108 7.53214 -117.65 -67.4047 21.4894 -117.7 -67.6363 31.9927 -117.75 -67.816 37.9861 -117.8 -67.9522 40.5525 -117.85 -68.0521 41.1535 -117.9 -68.1216 40.7307 -117.95 -68.1656 39.744 -118 -68.1881 38.3981 -118.05 -68.1924 36.788 -118.1 -68.1814 34.9663 -118.15 -68.1572 32.9686 -118.2 -68.1218 30.8241 -118.25 -68.0768 28.5584 -118.3 -68.0235 26.1949 -118.35 -67.9632 23.7547 -118.4 -67.8967 21.2572 -118.45 -67.8249 18.7192 -118.5 -67.7485 16.1556 -118.55 -67.668 13.5794 -118.6 -67.584 11.0013 -118.65 -67.4969 8.43033 -118.7 -67.4071 5.87371 -118.75 -67.3148 3.33716 -118.8 -67.2204 0.825031 -118.85 -67.1241 -1.65959 -118.9 -67.026 -4.11466 -118.95 -66.9264 -6.53911 -119 -66.8255 -8.93273 -119.05 -66.7233 -11.296 -119.1 -66.6199 -13.6303 -119.15 -66.5156 -15.9378 -119.2 -66.4103 -18.2212 -119.25 -66.3041 -20.4849 -119.3 -66.1972 -22.7339 -119.35 -66.0895 -24.9753 -119.4 -65.9812 -27.2179 -119.45 -65.8722 -29.4735 -119.5 -65.7627 -31.7568 -119.55 -65.6526 -34.0859 -119.6 -65.542 -36.4835 -119.65 -65.431 -38.9762 -119.7 -65.3195 -41.5942 -119.75 -65.2077 -44.3696 -119.8 -65.0955 -47.3316 -119.85 -64.9829 -50.4984 -119.9 -64.87 -53.8641 -119.95 -64.7569 -57.3802 -120 -64.6434 -60.9383 -120.05 -64.5297 -64.368 -120.1 -64.4158 -67.4651 -120.15 -64.3016 -70.0554 -120.2 -64.1873 -72.0576 -120.25 -64.0727 -73.4997 -120.3 -63.9581 -74.4824 -120.35 -63.8432 -75.1269 -120.4 -63.7283 -75.5392 -120.45 -63.6132 -75.7986 -120.5 -63.4981 -75.9596 -120.55 -63.3829 -76.0575 -120.6 -63.2676 -76.115 -120.65 -63.1522 -76.1465 -120.7 -63.0368 -76.161 -120.75 -62.9215 -76.1643 -120.8 -62.8061 -76.16 -120.85 -62.6907 -76.1505 -120.9 -62.5753 -76.1375 -120.95 -62.4599 -76.1218 -121 -62.3446 -76.1043 -121.05 -62.2294 -76.0853 -121.1 -62.1142 -76.0651 -121.15 -61.9991 -76.0441 -121.2 -61.8841 -76.0222 -121.25 -61.7692 -75.9996 -121.3 -61.6545 -75.9764 -121.35 -61.5398 -75.9526 -121.4 -61.4253 -75.9282 -121.45 -61.3109 -75.9034 -121.5 -61.1967 -75.878 -121.55 -61.0826 -75.8521 -121.6 -60.9687 -75.8257 -121.65 -60.8549 -75.7988 -121.7 -60.7414 -75.7714 -121.75 -60.6281 -75.7435 -121.8 -60.5149 -75.7151 -121.85 -60.402 -75.6862 -121.9 -60.2892 -75.6568 -121.95 -60.1767 -75.6269 -122 -60.0644 -75.5966 -122.05 -59.9524 -75.5657 -122.1 -59.8406 -75.5343 -122.15 -59.729 -75.5024 -122.2 -59.6176 -75.47 -122.25 -59.5065 -75.4371 -122.3 -59.3957 -75.4037 -122.35 -59.2851 -75.3698 -122.4 -59.1748 -75.3353 -122.45 -59.0647 -75.3004 -122.5 -58.9548 -75.2649 -122.55 -58.8453 -75.229 -122.6 -58.736 -75.1925 -122.65 -58.6269 -75.1555 -122.7 -58.5181 -75.118 -122.75 -58.4096 -75.0799 -122.8 -58.3013 -75.0414 -122.85 -58.1933 -75.0024 -122.9 -58.0856 -74.9628 -122.95 -57.978 -74.9227 -123 -57.8708 -74.8822 -123.05 -57.7638 -74.8411 -123.1 -57.657 -74.7995 -123.15 -57.5505 -74.7574 -123.2 -57.4442 -74.7148 -123.25 -57.3381 -74.6718 -123.3 -57.2323 -74.6282 -123.35 -57.1266 -74.5841 -123.4 -57.0212 -74.5396 -123.45 -56.916 -74.4946 -123.5 -56.811 -74.4491 -123.55 -56.7062 -74.4031 -123.6 -56.6016 -74.3567 -123.65 -56.4971 -74.3098 -123.7 -56.3928 -74.2624 -123.75 -56.2887 -74.2146 -123.8 -56.1847 -74.1663 -123.85 -56.0808 -74.1176 -123.9 -55.9771 -74.0684 -123.95 -55.8735 -74.0189 -124 -55.77 -73.9689 -124.05 -55.6665 -73.9185 -124.1 -55.5632 -73.8676 -124.15 -55.4599 -73.8164 -124.2 -55.3566 -73.7647 -124.25 -55.2534 -73.7127 -124.3 -55.1502 -73.6603 -124.35 -55.047 -73.6075 -124.4 -54.9438 -73.5543 -124.45 -54.8406 -73.5008 -124.5 -54.7373 -73.447 -124.55 -54.634 -73.3927 -124.6 -54.5305 -73.3382 -124.65 -54.4269 -73.2833 -124.7 -54.3232 -73.2281 -124.75 -54.2194 -73.1726 -124.8 -54.1153 -73.1168 -124.85 -54.0111 -73.0607 -124.9 -53.9066 -73.0043 -124.95 -53.8019 -72.9476 -125 -53.6969 -72.8907 -125.05 -53.5915 -72.8335 -125.1 -53.4858 -72.7761 -125.15 -53.3798 -72.7184 -125.2 -53.2733 -72.6605 -125.25 -53.1663 -72.6024 -125.3 -53.0589 -72.5441 -125.35 -52.9509 -72.4855 -125.4 -52.8423 -72.4268 -125.45 -52.7332 -72.3679 -125.5 -52.6233 -72.3088 -125.55 -52.5127 -72.2496 -125.6 -52.4014 -72.1902 -125.65 -52.2892 -72.1307 -125.7 -52.1761 -72.071 -125.75 -52.0621 -72.0113 -125.8 -51.947 -71.9514 -125.85 -51.8309 -71.8914 -125.9 -51.7135 -71.8313 -125.95 -51.5949 -71.7711 -126 -51.475 -71.7109 -126.05 -51.3535 -71.6506 -126.1 -51.2306 -71.5902 -126.15 -51.1059 -71.5298 -126.2 -50.9795 -71.4693 -126.25 -50.8512 -71.4088 -126.3 -50.7208 -71.3483 -126.35 -50.5881 -71.2878 -126.4 -50.4532 -71.2273 -126.45 -50.3156 -71.1667 -126.5 -50.1753 -71.1062 -126.55 -50.0321 -71.0458 -126.6 -49.8856 -70.9853 -126.65 -49.7358 -70.925 -126.7 -49.5821 -70.8646 -126.75 -49.4245 -70.8043 -126.8 -49.2625 -70.7441 -126.85 -49.0957 -70.684 -126.9 -48.9238 -70.6239 -126.95 -48.7464 -70.5639 -127 -48.5628 -70.504 -127.05 -48.3725 -70.4442 -127.1 -48.1749 -70.3845 -127.15 -47.9693 -70.3249 -127.2 -47.7549 -70.2655 -127.25 -47.5309 -70.2062 -127.3 -47.2961 -70.147 -127.35 -47.0495 -70.088 -127.4 -46.7898 -70.0291 -127.45 -46.5155 -69.9704 -127.5 -46.2249 -69.9119 -127.55 -45.9161 -69.8535 -127.6 -45.5868 -69.7953 -127.65 -45.2345 -69.7373 -127.7 -44.8561 -69.6794 -127.75 -44.4482 -69.6218 -127.8 -44.0065 -69.5643 -127.85 -43.5264 -69.507 -127.9 -43.002 -69.4499 -127.95 -42.4267 -69.3931 -128 -41.7922 -69.3364 -128.05 -41.0889 -69.2799 -128.1 -40.3053 -69.2237 -128.15 -39.4273 -69.1677 -128.2 -38.438 -69.112 -128.25 -37.3171 -69.0564 -128.3 -36.0401 -69.0011 -128.35 -34.5778 -68.9461 -128.4 -32.8953 -68.8913 -128.45 -30.9526 -68.8367 -128.5 -28.7045 -68.7823 -128.55 -26.103 -68.7282 -128.6 -23.1025 -68.6744 -128.65 -19.6679 -68.6207 -128.7 -15.7894 -68.5673 -128.75 -11.5016 -68.5141 -128.8 -6.90431 -68.4612 -128.85 -2.17605 -68.4085 -128.9 2.4329 -68.356 -128.95 6.63666 -68.3038 -129 10.1715 -68.2518 -129.05 12.8512 -68.2 -129.1 14.5954 -68.1484 -129.15 15.4243 -68.0971 -129.2 15.4298 -68.0459 -129.25 14.7414 -67.9949 -129.3 13.498 -67.9441 -129.35 11.8298 -67.8933 -129.4 9.85025 -67.8427 -129.45 7.65243 -67.7921 -129.5 5.3106 -67.7414 -129.55 2.88232 -67.6907 -129.6 0.411332 -67.6397 -129.65 -2.06967 -67.5885 -129.7 -4.53674 -67.5368 -129.75 -6.97264 -67.4845 -129.8 -9.36533 -67.4314 -129.85 -11.7067 -67.3771 -129.9 -13.9916 -67.3214 -129.95 -16.2172 -67.2639 -130 -18.3824 -67.2039 -130.05 -20.4874 -67.141 -130.1 -22.5338 -67.0741 -130.15 -24.5238 -67.0024 -130.2 -26.4609 -66.9246 -130.25 -28.349 -66.8391 -130.3 -30.193 -66.7441 -130.35 -31.9985 -66.6372 -130.4 -33.7716 -66.5156 -130.45 -35.5191 -66.3758 -130.5 -37.2479 -66.2134 -130.55 -38.9652 -66.0232 -130.6 -40.6782 -65.7985 -130.65 -42.3931 -65.5313 -130.7 -44.1154 -65.2116 -130.75 -45.8487 -64.8272 -130.8 -47.594 -64.363 -130.85 -49.349 -63.8004 -130.9 -51.1072 -63.1163 -130.95 -52.8573 -62.2825 -131 -54.5828 -61.2637 -131.05 -56.2627 -60.0159 -131.1 -57.8727 -58.4842 -131.15 -59.3879 -56.5992 -131.2 -60.7854 -54.2718 -131.25 -62.0477 -51.3862 -131.3 -63.1643 -47.7877 -131.35 -64.1327 -43.2644 -131.4 -64.9577 -37.5199 -131.45 -65.6496 -30.1435 -131.5 -66.222 -20.6221 -131.55 -66.69 -8.55112 -131.6 -67.0684 5.6591 -131.65 -67.371 19.8518 -131.7 -67.6099 30.9119 -131.75 -67.7957 37.4469 -131.8 -67.937 40.3615 -131.85 -68.0412 41.1478 -131.9 -68.1143 40.8221 -131.95 -68.1613 39.8924 -132 -68.1863 38.5855 -132.05 -68.1928 37.0056 -132.1 -68.1835 35.2086 -132.15 -68.1609 33.2316 -132.2 -68.1268 31.1043 -132.25 -68.083 28.8527 -132.3 -68.0307 26.5004 -132.35 -67.9712 24.0689 -132.4 -67.9055 21.5777 -132.45 -67.8343 19.0439 -132.5 -67.7585 16.4829 -132.55 -67.6785 13.9076 -132.6 -67.5949 11.3293 -132.65 -67.5082 8.75692 -132.7 -67.4187 6.19812 -132.75 -67.3267 3.65876 -132.8 -67.2325 1.14332 -132.85 -67.1364 -1.34491 -132.9 -67.0386 -3.80384 -132.95 -66.9392 -6.2322 -133 -66.8384 -8.62973 -133.05 -66.7364 -10.9968 -133.1 -66.6332 -13.3347 -133.15 -66.5289 -15.6454 -133.2 -66.4237 -17.9318 -133.25 -66.3177 -20.1976 -133.3 -66.2108 -22.4482 -133.35 -66.1032 -24.6901 -133.4 -65.995 -26.9321 -133.45 -65.8861 -29.1852 -133.5 -65.7766 -31.464 -133.55 -65.6666 -33.7862 -133.6 -65.5561 -36.1736 -133.65 -65.4452 -38.6526 -133.7 -65.3338 -41.2529 -133.75 -65.222 -44.0065 -133.8 -65.1098 -46.9434 -133.85 -64.9973 -50.0839 -133.9 -64.8844 -53.426 -133.95 -64.7713 -56.9275 -134 -64.6579 -60.4887 -134.05 -64.5442 -63.9457 -134.1 -64.4303 -67.0963 -134.15 -64.3162 -69.758 -134.2 -64.2018 -71.8356 -134.25 -64.0873 -73.3442 -134.3 -63.9727 -74.3787 -134.35 -63.8579 -75.0598 -134.4 -63.7429 -75.4966 -134.45 -63.6279 -75.772 -134.5 -63.5127 -75.9432 -134.55 -63.3975 -76.0477 -134.6 -63.2822 -76.1094 -134.65 -63.1669 -76.1436 -134.7 -63.0515 -76.1599 -134.75 -62.9361 -76.1644 -134.8 -62.8207 -76.1609 -134.85 -62.7053 -76.152 -134.9 -62.59 -76.1393 -134.95 -62.4746 -76.124 -135 -62.3593 -76.1066 -135.05 -62.2441 -76.0878 -135.1 -62.1289 -76.0678 -135.15 -62.0138 -76.0468 -135.2 -61.8988 -76.025 -135.25 -61.7839 -76.0025 -135.3 -61.6691 -75.9794 -135.35 -61.5544 -75.9557 -135.4 -61.4398 -75.9314 -135.45 -61.3254 -75.9066 -135.5 -61.2112 -75.8812 -135.55 -61.0971 -75.8554 -135.6 -60.9832 -75.8291 -135.65 -60.8694 -75.8022 -135.7 -60.7559 -75.7749 -135.75 -60.6425 -75.7471 -135.8 -60.5293 -75.7187 -135.85 -60.4163 -75.6899 -135.9 -60.3036 -75.6606 -135.95 -60.191 -75.6308 -136 -60.0787 -75.6005 -136.05 -59.9666 -75.5696 -136.1 -59.8548 -75.5383 -136.15 -59.7432 -75.5065 -136.2 -59.6318 -75.4742 -136.25 -59.5207 -75.4413 -136.3 -59.4098 -75.408 -136.35 -59.2992 -75.3741 -136.4 -59.1888 -75.3398 -136.45 -59.0787 -75.3049 -136.5 -58.9688 -75.2695 -136.55 -58.8592 -75.2336 -136.6 -58.7499 -75.1972 -136.65 -58.6408 -75.1602 -136.7 -58.532 -75.1228 -136.75 -58.4234 -75.0848 -136.8 -58.3151 -75.0463 -136.85 -58.2071 -75.0074 -136.9 -58.0993 -74.9679 -136.95 -57.9917 -74.9279 -137 -57.8844 -74.8874 -137.05 -57.7774 -74.8463 -137.1 -57.6706 -74.8048 -137.15 -57.564 -74.7628 -137.2 -57.4577 -74.7203 -137.25 -57.3516 -74.6773 -137.3 -57.2457 -74.6338 -137.35 -57.1401 -74.5898 -137.4 -57.0346 -74.5453 -137.45 -56.9294 -74.5003 -137.5 -56.8244 -74.4549 -137.55 -56.7195 -74.409 -137.6 -56.6149 -74.3626 -137.65 -56.5104 -74.3157 -137.7 -56.4061 -74.2684 -137.75 -56.3019 -74.2207 -137.8 -56.1979 -74.1725 -137.85 -56.094 -74.1238 -137.9 -55.9903 -74.0747 -137.95 -55.8866 -74.0252 -138 -55.7831 -73.9753 -138.05 -55.6797 -73.9249 -138.1 -55.5763 -73.8741 -138.15 -55.473 -73.8229 -138.2 -55.3698 -73.7713 -138.25 -55.2666 -73.7194 -138.3 -55.1634 -73.667 -138.35 -55.0602 -73.6142 -138.4 -54.957 -73.5611 -138.45 -54.8537 -73.5077 -138.5 -54.7505 -73.4538 -138.55 -54.6471 -73.3997 -138.6 -54.5437 -73.3451 -138.65 -54.4401 -73.2903 -138.7 -54.3364 -73.2351 -138.75 -54.2326 -73.1797 -138.8 -54.1286 -73.1239 -138.85 -54.0244 -73.0678 -138.9 -53.9199 -73.0115 -138.95 -53.8152 -72.9549 -139 -53.7102 -72.898 -139.05 -53.6049 -72.8408 -139.1 -53.4993 -72.7834 -139.15 -53.3933 -72.7258 -139.2 -53.2868 -72.6679 -139.25 -53.1799 -72.6098 -139.3 -53.0726 -72.5515 -139.35 -52.9647 -72.493 -139.4 -52.8562 -72.4343 -139.45 -52.7471 -72.3754 -139.5 -52.6373 -72.3164 -139.55 -52.5269 -72.2571 -139.6 -52.4156 -72.1978 -139.65 -52.3035 -72.1383 -139.7 -52.1906 -72.0786 -139.75 -52.0767 -72.0189 -139.8 -51.9617 -71.959 -139.85 -51.8457 -71.899 -139.9 -51.7285 -71.839 -139.95 -51.6101 -71.7788 -140 -51.4903 -71.7186 -140.05 -51.3691 -71.6582 -140.1 -51.2463 -71.5979 -140.15 -51.1219 -71.5375 -140.2 -50.9957 -71.477 -140.25 -50.8676 -71.4165 -140.3 -50.7375 -71.356 -140.35 -50.6052 -71.2955 -140.4 -50.4705 -71.235 -140.45 -50.3333 -71.1744 -140.5 -50.1934 -71.1139 -140.55 -50.0505 -71.0535 -140.6 -49.9045 -70.993 -140.65 -49.755 -70.9326 -140.7 -49.6019 -70.8723 -140.75 -49.4448 -70.812 -140.8 -49.2834 -70.7518 -140.85 -49.1173 -70.6916 -140.9 -48.946 -70.6315 -140.95 -48.7693 -70.5715 -141 -48.5865 -70.5116 -141.05 -48.3971 -70.4518 -141.1 -48.2005 -70.3921 -141.15 -47.996 -70.3325 -141.2 -47.7828 -70.2731 -141.25 -47.56 -70.2137 -141.3 -47.3266 -70.1545 -141.35 -47.0816 -70.0955 -141.4 -46.8237 -70.0366 -141.45 -46.5513 -69.9779 -141.5 -46.2629 -69.9193 -141.55 -45.9565 -69.8609 -141.6 -45.63 -69.8027 -141.65 -45.2807 -69.7447 -141.7 -44.9059 -69.6868 -141.75 -44.5019 -69.6291 -141.8 -44.0648 -69.5716 -141.85 -43.5899 -69.5143 -141.9 -43.0715 -69.4572 -141.95 -42.503 -69.4003 -142 -41.8766 -69.3436 -142.05 -41.1827 -69.2871 -142.1 -40.41 -69.2309 -142.15 -39.5449 -69.1748 -142.2 -38.5708 -69.119 -142.25 -37.468 -69.0635 -142.3 -36.2124 -69.0082 -142.35 -34.7755 -68.9531 -142.4 -33.1232 -68.8982 -142.45 -31.216 -68.8436 -142.5 -29.0094 -68.7892 -142.55 -26.4556 -68.7351 -142.6 -23.5082 -68.6812 -142.65 -20.1301 -68.6275 -142.7 -16.3074 -68.5741 -142.75 -12.0677 -68.5209 -142.8 -7.50161 -68.4679 -142.85 -2.77739 -68.4152 -142.9 1.86242 -68.3627 -142.95 6.13352 -68.3104 -143 9.76596 -68.2584 -143.05 12.5613 -68.2066 -143.1 14.4254 -68.155 -143.15 15.367 -68.1036 -143.2 15.4706 -68.0524 -143.25 14.8628 -68.0014 -143.3 13.6825 -67.9505 -143.35 12.0618 -67.8998 -143.4 10.1163 -67.8491 -143.45 7.94175 -67.7985 -143.5 5.61474 -67.7479 -143.55 3.19477 -67.6971 -143.6 0.727207 -67.6462 -143.65 -1.75402 -67.595 -143.7 -4.22394 -67.5434 -143.75 -6.66458 -67.4912 -143.8 -9.06329 -67.4382 -143.85 -11.4115 -67.3841 -143.9 -13.7038 -67.3286 -143.95 -15.937 -67.2713 -144 -18.1099 -67.2117 -144.05 -20.2226 -67.1492 -144.1 -22.2763 -67.0829 -144.15 -24.2734 -67.0118 -144.2 -26.217 -66.9349 -144.25 -28.1111 -66.8505 -144.3 -29.9605 -66.7568 -144.35 -31.7706 -66.6516 -144.4 -33.5474 -66.532 -144.45 -35.2978 -66.3948 -144.5 -37.0285 -66.2356 -144.55 -38.7469 -66.0492 -144.6 -40.4601 -65.8293 -144.65 -42.1744 -65.568 -144.7 -43.8955 -65.2556 -144.75 -45.6273 -64.8802 -144.8 -47.371 -64.4271 -144.85 -49.125 -63.8782 -144.9 -50.8834 -63.2111 -144.95 -52.6354 -62.3982 -145 -54.3651 -61.4051 -145.05 -56.0521 -60.1893 -145.1 -57.6724 -58.6973 -145.15 -59.201 -56.8617 -145.2 -60.6146 -54.5964 -145.25 -61.8949 -51.7895 -145.3 -63.0304 -48.2922 -145.35 -64.0175 -43.901 -145.4 -64.8603 -38.3321 -145.45 -65.5684 -31.1907 -145.5 -66.1552 -21.9714 -145.55 -66.6357 -10.2296 -145.6 -67.0247 3.78708 -145.65 -67.3362 18.1601 -145.7 -67.5827 29.7538 -145.75 -67.7746 36.8482 -145.8 -67.9212 40.1368 -145.85 -68.0297 41.1248 -145.9 -68.1065 40.9041 -145.95 -68.1566 40.0348 -146 -68.1842 38.7685 -146.05 -68.1929 37.2197 -146.1 -68.1855 35.448 -146.15 -68.1644 33.4922 -146.2 -68.1317 31.3825 -146.25 -68.089 29.1454 -146.3 -68.0378 26.8047 -146.35 -67.9792 24.3821 -146.4 -67.9142 21.8975 -146.45 -67.8437 19.3683 -146.5 -67.7684 16.8099 -146.55 -67.6889 14.2358 -146.6 -67.6057 11.6573 -146.65 -67.5194 9.08374 -146.7 -67.4302 6.52287 -146.75 -67.3385 3.98075 -146.8 -67.2446 1.46207 -146.85 -67.1487 -1.02979 -146.9 -67.0511 -3.4925 -146.95 -66.9519 -5.92482 -147 -66.8513 -8.32622 -147.05 -66.7494 -10.6972 -147.1 -66.6464 -13.0387 -147.15 -66.5422 -15.3527 -147.2 -66.4372 -17.642 -147.25 -66.3312 -19.9103 -147.3 -66.2245 -22.1623 -147.35 -66.117 -24.4049 -147.4 -66.0088 -26.6463 -147.45 -65.9 -28.8974 -147.5 -65.7906 -31.1719 -147.55 -65.6807 -33.4874 -147.6 -65.5702 -35.8652 -147.65 -65.4593 -38.3309 -147.7 -65.348 -40.914 -147.75 -65.2362 -43.6463 -147.8 -65.1241 -46.5584 -147.85 -65.0116 -49.6725 -147.9 -64.8988 -52.9902 -147.95 -64.7857 -56.4757 -148 -64.6723 -60.037 -148.05 -64.5587 -63.5183 -148.1 -64.4448 -66.719 -148.15 -64.3307 -69.4506 -148.2 -64.2164 -71.6038 -148.25 -64.1019 -73.1808 -148.3 -63.9873 -74.269 -148.35 -63.8725 -74.9886 -148.4 -63.7576 -75.4514 -148.45 -63.6425 -75.7437 -148.5 -63.5274 -75.9257 -148.55 -63.4122 -76.0371 -148.6 -63.2969 -76.1033 -148.65 -63.1816 -76.1404 -148.7 -63.0662 -76.1586 -148.75 -62.9508 -76.1643 -148.8 -62.8354 -76.1617 -148.85 -62.72 -76.1533 -148.9 -62.6047 -76.1411 -148.95 -62.4893 -76.126 -149 -62.374 -76.1089 -149.05 -62.2587 -76.0902 -149.1 -62.1435 -76.0704 -149.15 -62.0284 -76.0495 -149.2 -61.9134 -76.0278 -149.25 -61.7985 -76.0054 -149.3 -61.6837 -75.9824 -149.35 -61.569 -75.9587 -149.4 -61.4544 -75.9345 -149.45 -61.34 -75.9098 -149.5 -61.2257 -75.8845 -149.55 -61.1116 -75.8587 -149.6 -60.9977 -75.8324 -149.65 -60.8839 -75.8057 -149.7 -60.7703 -75.7784 -149.75 -60.6569 -75.7506 -149.8 -60.5437 -75.7224 -149.85 -60.4307 -75.6936 -149.9 -60.3179 -75.6644 -149.95 -60.2054 -75.6346 -150 -60.093 -75.6044 -150.05 -59.9809 -75.5736 -150.1 -59.869 -75.5423 -150.15 -59.7574 -75.5106 -150.2 -59.646 -75.4783 -150.25 -59.5348 -75.4455 -150.3 -59.4239 -75.4123 -150.35 -59.3132 -75.3785 -150.4 -59.2028 -75.3442 -150.45 -59.0927 -75.3093 -150.5 -58.9828 -75.274 -150.55 -58.8732 -75.2382 -150.6 -58.7638 -75.2018 -150.65 -58.6547 -75.1649 -150.7 -58.5458 -75.1276 -150.75 -58.4372 -75.0897 -150.8 -58.3289 -75.0513 -150.85 -58.2208 -75.0123 -150.9 -58.113 -74.9729 -150.95 -58.0054 -74.933 -151 -57.8981 -74.8925 -151.05 -57.791 -74.8516 -151.1 -57.6842 -74.8101 -151.15 -57.5776 -74.7682 -151.2 -57.4712 -74.7257 -151.25 -57.3651 -74.6828 -151.3 -57.2592 -74.6393 -151.35 -57.1535 -74.5954 -151.4 -57.048 -74.551 -151.45 -56.9428 -74.5061 -151.5 -56.8377 -74.4607 -151.55 -56.7329 -74.4149 -151.6 -56.6282 -74.3685 -151.65 -56.5237 -74.3217 -151.7 -56.4193 -74.2745 -151.75 -56.3152 -74.2268 -151.8 -56.2111 -74.1786 -151.85 -56.1072 -74.13 -151.9 -56.0035 -74.081 -151.95 -55.8998 -74.0315 -152 -55.7963 -73.9816 -152.05 -55.6929 -73.9313 -152.1 -55.5895 -73.8806 -152.15 -55.4862 -73.8295 -152.2 -55.3829 -73.7779 -152.25 -55.2797 -73.726 -152.3 -55.1765 -73.6737 -152.35 -55.0733 -73.621 -152.4 -54.9701 -73.5679 -152.45 -54.8669 -73.5145 -152.5 -54.7636 -73.4607 -152.55 -54.6603 -73.4066 -152.6 -54.5569 -73.3521 -152.65 -54.4533 -73.2973 -152.7 -54.3497 -73.2422 -152.75 -54.2458 -73.1868 -152.8 -54.1418 -73.131 -152.85 -54.0377 -73.075 -152.9 -53.9332 -73.0187 -152.95 -53.8286 -72.9621 -153 -53.7236 -72.9052 -153.05 -53.6184 -72.8481 -153.1 -53.5128 -72.7907 -153.15 -53.4068 -72.7331 -153.2 -53.3004 -72.6753 -153.25 -53.1936 -72.6172 -153.3 -53.0863 -72.5589 -153.35 -52.9784 -72.5005 -153.4 -52.87 -72.4418 -153.45 -52.761 -72.3829 -153.5 -52.6513 -72.3239 -153.55 -52.541 -72.2647 -153.6 -52.4298 -72.2053 -153.65 -52.3179 -72.1459 -153.7 -52.205 -72.0862 -153.75 -52.0912 -72.0265 -153.8 -51.9764 -71.9666 -153.85 -51.8606 -71.9067 -153.9 -51.7435 -71.8466 -153.95 -51.6253 -71.7865 -154 -51.5057 -71.7262 -154.05 -51.3846 -71.6659 -154.1 -51.262 -71.6056 -154.15 -51.1378 -71.5452 -154.2 -51.0119 -71.4847 -154.25 -50.884 -71.4242 -154.3 -50.7542 -71.3637 -154.35 -50.6222 -71.3032 -154.4 -50.4878 -71.2427 -154.45 -50.3509 -71.1821 -154.5 -50.2114 -71.1216 -154.55 -50.0689 -71.0612 -154.6 -49.9233 -71.0007 -154.65 -49.7743 -70.9403 -154.7 -49.6217 -70.88 -154.75 -49.4651 -70.8197 -154.8 -49.3042 -70.7594 -154.85 -49.1387 -70.6993 -154.9 -48.9682 -70.6392 -154.95 -48.7921 -70.5792 -155 -48.6101 -70.5192 -155.05 -48.4216 -70.4594 -155.1 -48.226 -70.3997 -155.15 -48.0225 -70.3401 -155.2 -47.8104 -70.2806 -155.25 -47.5889 -70.2213 -155.3 -47.357 -70.1621 -155.35 -47.1136 -70.103 -155.4 -46.8573 -70.0441 -155.45 -46.5869 -69.9854 -155.5 -46.3006 -69.9268 -155.55 -45.9966 -69.8684 -155.6 -45.6728 -69.8101 -155.65 -45.3266 -69.752 -155.7 -44.9552 -69.6941 -155.75 -44.5551 -69.6364 -155.8 -44.1225 -69.5789 -155.85 -43.6527 -69.5216 -155.9 -43.1402 -69.4644 -155.95 -42.5785 -69.4075 -156 -41.96 -69.3508 -156.05 -41.2753 -69.2943 -156.1 -40.5133 -69.238 -156.15 -39.6608 -69.182 -156.2 -38.7017 -69.1261 -156.25 -37.6165 -69.0705 -156.3 -36.3819 -69.0152 -156.35 -34.9698 -68.9601 -156.4 -33.3471 -68.9052 -156.45 -31.4748 -68.8506 -156.5 -29.309 -68.7962 -156.55 -26.8021 -68.742 -156.6 -23.9072 -68.688 -156.65 -20.5854 -68.6343 -156.7 -16.8189 -68.5809 -156.75 -12.6289 -68.5276 -156.8 -8.09674 -68.4746 -156.85 -3.38055 -68.4219 -156.9 1.28541 -68.3694 -156.95 5.61943 -68.3171 -157 9.34627 -68.265 -157.05 12.2558 -68.2132 -157.1 14.2402 -68.1615 -157.15 15.2958 -68.1101 -157.2 15.4998 -68.0589 -157.25 14.975 -68.0079 -157.3 13.86 -67.957 -157.35 12.2886 -67.9062 -157.4 10.3788 -67.8556 -157.45 8.22879 -67.805 -157.5 5.91757 -67.7543 -157.55 3.50666 -67.7036 -157.6 1.04306 -67.6527 -157.65 -1.43798 -67.6015 -157.7 -3.91047 -67.55 -157.75 -6.35565 -67.4979 -157.8 -8.76026 -67.445 -157.85 -11.1153 -67.3911 -157.9 -13.4149 -67.3358 -157.95 -15.6558 -67.2788 -158 -17.8364 -67.2195 -158.05 -19.9566 -67.1573 -158.1 -22.0178 -67.0915 -158.15 -24.022 -67.0212 -158.2 -25.9722 -66.945 -158.25 -27.8724 -66.8617 -158.3 -29.7272 -66.7693 -158.35 -31.5419 -66.6657 -158.4 -33.3226 -66.5482 -158.45 -35.0759 -66.4134 -158.5 -36.8088 -66.2572 -158.55 -38.5284 -66.0747 -158.6 -40.2418 -65.8595 -158.65 -41.9557 -65.6039 -158.7 -43.6757 -65.2987 -158.75 -45.4059 -64.9321 -158.8 -47.1481 -64.4898 -158.85 -48.9011 -63.9542 -158.9 -50.6594 -63.3036 -158.95 -52.413 -62.511 -159 -54.1466 -61.5431 -159.05 -55.8402 -60.3583 -159.1 -57.4704 -58.9049 -159.15 -59.0121 -57.1175 -159.2 -60.4415 -54.9126 -159.25 -61.7396 -52.1822 -159.3 -62.8939 -48.7828 -159.35 -63.8999 -44.5194 -159.4 -64.7606 -39.1201 -159.45 -65.4852 -32.2054 -159.5 -66.0867 -23.2806 -159.55 -66.5798 -11.8709 -159.6 -66.9797 1.92044 -159.65 -67.3004 16.4184 -159.7 -67.5545 28.5171 -159.75 -67.7529 36.1859 -159.8 -67.9047 39.8751 -159.85 -68.0178 41.0828 -159.9 -68.0983 40.976 -159.95 -68.1515 40.1711 -160 -68.1818 38.9473 -160.05 -68.1927 37.4304 -160.1 -68.1872 35.6848 -160.15 -68.1678 33.7506 -160.2 -68.1365 31.6591 -160.25 -68.095 29.4368 -160.3 -68.0448 27.108 -160.35 -67.987 24.6948 -160.4 -67.9228 22.217 -160.45 -67.8529 19.6926 -160.5 -67.7782 17.1372 -160.55 -67.6992 14.5644 -160.6 -67.6165 11.9859 -160.65 -67.5305 9.41126 -160.7 -67.4417 6.84839 -160.75 -67.3503 4.30359 -160.8 -67.2567 1.78171 -160.85 -67.1611 -0.713725 -160.9 -67.0637 -3.18026 -160.95 -66.9646 -5.61648 -161 -66.8642 -8.02185 -161.05 -66.7625 -10.3966 -161.1 -66.6596 -12.7418 -161.15 -66.5556 -15.0592 -161.2 -66.4506 -17.3514 -161.25 -66.3448 -19.6221 -161.3 -66.2381 -21.876 -161.35 -66.1307 -24.1193 -161.4 -66.0226 -26.3602 -161.45 -65.9139 -28.6094 -161.5 -65.8046 -30.8802 -161.55 -65.6947 -33.1893 -161.6 -65.5843 -35.5578 -161.65 -65.4735 -38.0107 -161.7 -65.3622 -40.5771 -161.75 -65.2505 -43.2886 -161.8 -65.1384 -46.1763 -161.85 -65.026 -49.2639 -161.9 -64.9132 -52.5566 -161.95 -64.8001 -56.0244 -162 -64.6868 -59.5835 -162.05 -64.5732 -63.0856 -162.1 -64.4593 -66.3336 -162.15 -64.3452 -69.1332 -162.2 -64.231 -71.3624 -162.25 -64.1165 -73.0093 -162.3 -64.0019 -74.1533 -162.35 -63.8871 -74.9133 -162.4 -63.7722 -75.4034 -162.45 -63.6572 -75.7136 -162.5 -63.5421 -75.9071 -162.55 -63.4269 -76.0259 -162.6 -63.3116 -76.0968 -162.65 -63.1963 -76.1369 -162.7 -63.0809 -76.1571 -162.75 -62.9655 -76.1641 -162.8 -62.8501 -76.1624 -162.85 -62.7347 -76.1547 -162.9 -62.6194 -76.1428 -162.95 -62.504 -76.1281 -163 -62.3887 -76.1112 -163.05 -62.2734 -76.0927 -163.1 -62.1582 -76.073 -163.15 -62.0431 -76.0522 -163.2 -61.9281 -76.0306 -163.25 -61.8131 -76.0083 -163.3 -61.6983 -75.9853 -163.35 -61.5836 -75.9618 -163.4 -61.469 -75.9376 -163.45 -61.3546 -75.9129 -163.5 -61.2403 -75.8877 -163.55 -61.1261 -75.862 -163.6 -61.0122 -75.8358 -163.65 -60.8984 -75.8091 -163.7 -60.7848 -75.7819 -163.75 -60.6713 -75.7542 -163.8 -60.5581 -75.726 -163.85 -60.4451 -75.6973 -163.9 -60.3323 -75.6681 -163.95 -60.2197 -75.6384 -164 -60.1073 -75.6082 -164.05 -59.9952 -75.5775 -164.1 -59.8833 -75.5464 -164.15 -59.7716 -75.5147 -164.2 -59.6602 -75.4825 -164.25 -59.549 -75.4497 -164.3 -59.438 -75.4165 -164.35 -59.3273 -75.3828 -164.4 -59.2169 -75.3486 -164.45 -59.1067 -75.3138 -164.5 -58.9968 -75.2785 -164.55 -58.8871 -75.2428 -164.6 -58.7777 -75.2065 -164.65 -58.6686 -75.1697 -164.7 -58.5597 -75.1324 -164.75 -58.451 -75.0945 -164.8 -58.3427 -75.0562 -164.85 -58.2346 -75.0173 -164.9 -58.1267 -74.978 -164.95 -58.0191 -74.9381 -165 -57.9117 -74.8977 -165.05 -57.8046 -74.8568 -165.1 -57.6978 -74.8154 -165.15 -57.5912 -74.7736 -165.2 -57.4848 -74.7312 -165.25 -57.3786 -74.6883 -165.3 -57.2727 -74.6449 -165.35 -57.167 -74.601 -165.4 -57.0615 -74.5567 -165.45 -56.9562 -74.5118 -165.5 -56.8511 -74.4665 -165.55 -56.7462 -74.4207 -165.6 -56.6415 -74.3745 -165.65 -56.537 -74.3277 -165.7 -56.4326 -74.2805 -165.75 -56.3284 -74.2329 -165.8 -56.2244 -74.1848 -165.85 -56.1205 -74.1363 -165.9 -56.0167 -74.0873 -165.95 -55.913 -74.0379 -166 -55.8095 -73.988 -166.05 -55.706 -73.9378 -166.1 -55.6027 -73.8871 -166.15 -55.4993 -73.836 -166.2 -55.3961 -73.7845 -166.25 -55.2929 -73.7326 -166.3 -55.1897 -73.6804 -166.35 -55.0865 -73.6277 -166.4 -54.9833 -73.5747 -166.45 -54.88 -73.5213 -166.5 -54.7768 -73.4676 -166.55 -54.6735 -73.4135 -166.6 -54.57 -73.3591 -166.65 -54.4665 -73.3043 -166.7 -54.3629 -73.2492 -166.75 -54.2591 -73.1938 -166.8 -54.1551 -73.1381 -166.85 -54.0509 -73.0821 -166.9 -53.9466 -73.0259 -166.95 -53.8419 -72.9693 -167 -53.737 -72.9125 -167.05 -53.6318 -72.8554 -167.1 -53.5263 -72.7981 -167.15 -53.4203 -72.7405 -167.2 -53.314 -72.6827 -167.25 -53.2072 -72.6246 -167.3 -53.1 -72.5664 -167.35 -52.9922 -72.5079 -167.4 -52.8839 -72.4493 -167.45 -52.7749 -72.3904 -167.5 -52.6654 -72.3314 -167.55 -52.5551 -72.2722 -167.6 -52.444 -72.2129 -167.65 -52.3322 -72.1535 -167.7 -52.2195 -72.0938 -167.75 -52.1058 -72.0341 -167.8 -51.9911 -71.9743 -167.85 -51.8754 -71.9143 -167.9 -51.7585 -71.8543 -167.95 -51.6404 -71.7941 -168 -51.521 -71.7339 -168.05 -51.4001 -71.6736 -168.1 -51.2778 -71.6133 -168.15 -51.1538 -71.5529 -168.2 -51.028 -71.4924 -168.25 -50.9005 -71.4319 -168.3 -50.7709 -71.3714 -168.35 -50.6391 -71.3109 -168.4 -50.5051 -71.2504 -168.45 -50.3685 -71.1899 -168.5 -50.2293 -71.1294 -168.55 -50.0872 -71.0689 -168.6 -49.942 -71.0084 -168.65 -49.7935 -70.948 -168.7 -49.6413 -70.8877 -168.75 -49.4853 -70.8274 -168.8 -49.325 -70.7671 -168.85 -49.1601 -70.7069 -168.9 -48.9902 -70.6468 -168.95 -48.8149 -70.5868 -169 -48.6337 -70.5269 -169.05 -48.4461 -70.467 -169.1 -48.2513 -70.4073 -169.15 -48.0489 -70.3477 -169.2 -47.838 -70.2882 -169.25 -47.6177 -70.2288 -169.3 -47.3872 -70.1696 -169.35 -47.1453 -70.1105 -169.4 -46.8908 -70.0516 -169.45 -46.6222 -69.9928 -169.5 -46.3381 -69.9342 -169.55 -46.0365 -69.8758 -169.6 -45.7153 -69.8175 -169.65 -45.3721 -69.7594 -169.7 -45.0041 -69.7015 -169.75 -44.6079 -69.6438 -169.8 -44.1797 -69.5862 -169.85 -43.7149 -69.5289 -169.9 -43.2082 -69.4717 -169.95 -42.6532 -69.4148 -170 -42.0424 -69.358 -170.05 -41.3667 -69.3015 -170.1 -40.6153 -69.2452 -170.15 -39.7752 -69.1891 -170.2 -38.8307 -69.1332 -170.25 -37.7628 -69.0776 -170.3 -36.5487 -69.0222 -170.35 -35.161 -68.9671 -170.4 -33.5672 -68.9122 -170.45 -31.7291 -68.8575 -170.5 -29.6033 -68.8031 -170.55 -27.1427 -68.7489 -170.6 -24.2997 -68.6949 -170.65 -21.034 -68.6412 -170.7 -17.3242 -68.5877 -170.75 -13.1851 -68.5344 -170.8 -8.68952 -68.4814 -170.85 -3.98522 -68.4286 -170.9 0.702302 -68.376 -170.95 5.09475 -68.3237 -171 8.91263 -68.2716 -171.05 11.9348 -68.2198 -171.1 14.0394 -68.1681 -171.15 15.2107 -68.1167 -171.2 15.5171 -68.0654 -171.25 15.0777 -68.0144 -171.3 14.0304 -67.9635 -171.35 12.5103 -67.9127 -171.4 10.6377 -67.862 -171.45 8.51358 -67.8114 -171.5 6.21919 -67.7608 -171.55 3.81811 -67.7101 -171.6 1.35905 -67.6592 -171.65 -1.12138 -67.6081 -171.7 -3.59615 -67.5566 -171.75 -6.04564 -67.5046 -171.8 -8.45601 -67.4518 -171.85 -10.8177 -67.398 -171.9 -13.1247 -67.3429 -171.95 -15.3732 -67.2861 -172 -17.5615 -67.2272 -172.05 -19.6894 -67.1654 -172.1 -21.758 -67.1002 -172.15 -23.7692 -67.0304 -172.2 -25.7262 -66.9551 -172.25 -27.6325 -66.8728 -172.3 -29.4928 -66.7817 -172.35 -31.3123 -66.6796 -172.4 -33.097 -66.5641 -172.45 -34.8534 -66.4317 -172.5 -36.5885 -66.2785 -172.55 -38.3094 -66.0996 -172.6 -40.0232 -65.889 -172.65 -41.7367 -65.6391 -172.7 -43.4556 -65.3408 -172.75 -45.1844 -64.9827 -172.8 -46.9251 -64.551 -172.85 -48.677 -64.0285 -172.9 -50.4351 -63.3939 -172.95 -52.1899 -62.6212 -173 -53.9271 -61.6777 -173.05 -55.6271 -60.5233 -173.1 -57.2668 -59.1075 -173.15 -58.8211 -57.3669 -173.2 -60.2661 -55.2207 -173.25 -61.5818 -52.5644 -173.3 -62.7548 -49.2599 -173.35 -63.7797 -45.12 -173.4 -64.6586 -39.8842 -173.45 -65.3999 -33.1883 -173.5 -66.0163 -24.5498 -173.55 -66.5224 -13.4727 -173.6 -66.9334 0.0662499 -173.65 -67.2634 14.6343 -173.7 -67.5254 27.2032 -173.75 -67.7303 35.4571 -173.8 -67.8877 39.5735 -173.85 -68.0053 41.0203 -173.9 -68.0896 41.0371 -173.95 -68.1461 40.3009 -174 -68.1791 39.1216 -174.05 -68.1923 37.6378 -174.1 -68.1888 35.9188 -174.15 -68.171 34.0068 -174.2 -68.1411 31.9338 -174.25 -68.1008 29.7268 -174.3 -68.0516 27.4104 -174.35 -67.9948 25.0067 -174.4 -67.9313 22.5362 -174.45 -67.8621 20.0168 -174.5 -67.788 17.4645 -174.55 -67.7095 14.8933 -174.6 -67.6273 12.3149 -174.65 -67.5417 9.7393 -174.7 -67.4532 7.17455 -174.75 -67.3621 4.62716 -174.8 -67.2688 2.10211 -174.85 -67.1734 -0.396826 -174.9 -67.0762 -2.86716 -174.95 -66.9774 -5.30728 -175 -66.8771 -7.7166 -175.05 -66.7755 -10.0952 -175.1 -66.6727 -12.4441 -175.15 -66.5689 -14.765 -175.2 -66.4641 -17.0602 -175.25 -66.3583 -19.3333 -175.3 -66.2518 -21.5891 -175.35 -66.1445 -23.8334 -175.4 -66.0365 -26.0741 -175.45 -65.9278 -28.3214 -175.5 -65.8186 -30.5886 -175.55 -65.7088 -32.8918 -175.6 -65.5984 -35.2514 -175.65 -65.4876 -37.692 -175.7 -65.3764 -40.2422 -175.75 -65.2648 -42.9334 -175.8 -65.1527 -45.7971 -175.85 -65.0403 -48.8584 -175.9 -64.9276 -52.1258 -175.95 -64.8146 -55.5747 -176 -64.7013 -59.1289 -176.05 -64.5877 -62.6486 -176.1 -64.4739 -65.9406 -176.15 -64.3598 -68.8064 -176.2 -64.2456 -71.1114 -176.25 -64.1311 -72.8296 -176.3 -64.0165 -74.0314 -176.35 -63.9018 -74.8336 -176.4 -63.7869 -75.3526 -176.45 -63.6719 -75.6816 -176.5 -63.5568 -75.8873 -176.55 -63.4416 -76.0138 -176.6 -63.3263 -76.0897 -176.65 -63.211 -76.1331 -176.7 -63.0957 -76.1554 -176.75 -62.9803 -76.1638 -176.8 -62.8649 -76.163 -176.85 -62.7495 -76.1559 -176.9 -62.6341 -76.1445 -176.95 -62.5187 -76.1301 -177 -62.4034 -76.1134 -177.05 -62.2881 -76.0951 -177.1 -62.1729 -76.0755 -177.15 -62.0578 -76.0549 -177.2 -61.9427 -76.0334 -177.25 -61.8278 -76.0112 -177.3 -61.713 -75.9883 -177.35 -61.5982 -75.9648 -177.4 -61.4836 -75.9407 -177.45 -61.3692 -75.9161 -177.5 -61.2549 -75.891 -177.55 -61.1407 -75.8653 -177.6 -61.0267 -75.8392 -177.65 -60.9129 -75.8125 -177.7 -60.7993 -75.7854 -177.75 -60.6858 -75.7578 -177.8 -60.5726 -75.7296 -177.85 -60.4595 -75.701 -177.9 -60.3467 -75.6719 -177.95 -60.2341 -75.6422 -178 -60.1216 -75.6121 -178.05 -60.0095 -75.5815 -178.1 -59.8975 -75.5504 -178.15 -59.7858 -75.5187 -178.2 -59.6744 -75.4866 -178.25 -59.5631 -75.4539 -178.3 -59.4522 -75.4208 -178.35 -59.3414 -75.3871 -178.4 -59.231 -75.353 -178.45 -59.1208 -75.3183 -178.5 -59.0108 -75.2831 -178.55 -58.9011 -75.2474 -178.6 -58.7917 -75.2111 -178.65 -58.6825 -75.1744 -178.7 -58.5736 -75.1372 -178.75 -58.4649 -75.0994 -178.8 -58.3565 -75.0611 -178.85 -58.2483 -75.0223 -178.9 -58.1405 -74.983 -178.95 -58.0328 -74.9432 -179 -57.9254 -74.9029 -179.05 -57.8183 -74.8621 -179.1 -57.7114 -74.8208 -179.15 -57.6047 -74.7789 -179.2 -57.4983 -74.7366 -179.25 -57.3921 -74.6938 -179.3 -57.2862 -74.6505 -179.35 -57.1805 -74.6067 -179.4 -57.0749 -74.5624 -179.45 -56.9696 -74.5176 -179.5 -56.8645 -74.4723 -179.55 -56.7596 -74.4266 -179.6 -56.6549 -74.3804 -179.65 -56.5503 -74.3337 -179.7 -56.4459 -74.2866 -179.75 -56.3417 -74.239 -179.8 -56.2377 -74.191 -179.85 -56.1337 -74.1425 -179.9 -56.0299 -74.0936 -179.95 -55.9263 -74.0442 -180 -55.8227 -73.9944 -180.05 -55.7192 -73.9442 -180.1 -55.6158 -73.8936 -180.15 -55.5125 -73.8425 -180.2 -55.4093 -73.7911 -180.25 -55.306 -73.7393 -180.3 -55.2028 -73.6871 -180.35 -55.0996 -73.6345 -180.4 -54.9964 -73.5815 -180.45 -54.8932 -73.5282 -180.5 -54.79 -73.4745 -180.55 -54.6866 -73.4204 -180.6 -54.5832 -73.366 -180.65 -54.4797 -73.3113 -180.7 -54.3761 -73.2563 -180.75 -54.2723 -73.2009 -180.8 -54.1684 -73.1453 -180.85 -54.0643 -73.0893 -180.9 -53.9599 -73.0331 -180.95 -53.8553 -72.9765 -181 -53.7504 -72.9198 -181.05 -53.6453 -72.8627 -181.1 -53.5398 -72.8054 -181.15 -53.4339 -72.7478 -181.2 -53.3276 -72.6901 -181.25 -53.2209 -72.632 -181.3 -53.1137 -72.5738 -181.35 -53.006 -72.5154 -181.4 -52.8977 -72.4568 -181.45 -52.7889 -72.398 -181.5 -52.6794 -72.339 -181.55 -52.5692 -72.2798 -181.6 -52.4583 -72.2205 -181.65 -52.3465 -72.161 -181.7 -52.2339 -72.1015 -181.75 -52.1204 -72.0417 -181.8 -52.0058 -71.9819 -181.85 -51.8902 -71.922 -181.9 -51.7735 -71.8619 -181.95 -51.6556 -71.8018 -182 -51.5363 -71.7416 -182.05 -51.4156 -71.6813 -182.1 -51.2935 -71.621 -182.15 -51.1697 -71.5606 -182.2 -51.0442 -71.5001 -182.25 -50.9168 -71.4396 -182.3 -50.7875 -71.3791 -182.35 -50.6561 -71.3186 -182.4 -50.5223 -71.2581 -182.45 -50.3861 -71.1976 -182.5 -50.2472 -71.1371 -182.55 -50.1055 -71.0766 -182.6 -49.9607 -71.0161 -182.65 -49.8126 -70.9557 -182.7 -49.661 -70.8954 -182.75 -49.5054 -70.8351 -182.8 -49.3457 -70.7748 -182.85 -49.1814 -70.7146 -182.9 -49.0122 -70.6545 -182.95 -48.8376 -70.5945 -183 -48.6572 -70.5345 -183.05 -48.4704 -70.4747 -183.1 -48.2766 -70.4149 -183.15 -48.0752 -70.3553 -183.2 -47.8654 -70.2958 -183.25 -47.6464 -70.2364 -183.3 -47.4172 -70.1772 -183.35 -47.1768 -70.1181 -183.4 -46.924 -70.0591 -183.45 -46.6573 -70.0003 -183.5 -46.3753 -69.9417 -183.55 -46.076 -69.8833 -183.6 -45.7575 -69.825 -183.65 -45.4172 -69.7668 -183.7 -45.0525 -69.7089 -183.75 -44.6601 -69.6511 -183.8 -44.2362 -69.5936 -183.85 -43.7764 -69.5362 -183.9 -43.2754 -69.479 -183.95 -42.7269 -69.422 -184 -42.1237 -69.3652 -184.05 -41.4569 -69.3087 -184.1 -40.7158 -69.2524 -184.15 -39.8878 -69.1962 -184.2 -38.9576 -69.1404 -184.25 -37.9066 -69.0847 -184.3 -36.7126 -69.0293 -184.35 -35.3488 -68.9741 -184.4 -33.7833 -68.9192 -184.45 -31.9787 -68.8645 -184.5 -29.8922 -68.81 -184.55 -27.477 -68.7558 -184.6 -24.6853 -68.7018 -184.65 -21.4752 -68.648 -184.7 -17.8222 -68.5945 -184.75 -13.7352 -68.5412 -184.8 -9.27857 -68.4881 -184.85 -4.58987 -68.4353 -184.9 0.114587 -68.3827 -184.95 4.56082 -68.3304 -185 8.46605 -68.2783 -185.05 11.5988 -68.2264 -185.1 13.8235 -68.1747 -185.15 15.1115 -68.1232 -185.2 15.5223 -68.072 -185.25 15.1705 -68.0209 -185.3 14.193 -67.97 -185.35 12.7261 -67.9192 -185.4 10.8925 -67.8685 -185.45 8.79554 -67.8179 -185.5 6.51898 -67.7672 -185.55 4.12853 -67.7165 -185.6 1.6746 -67.6657 -185.65 -0.804785 -67.6146 -185.7 -3.28149 -67.5632 -185.75 -5.73509 -67.5112 -185.8 -8.15105 -67.4586 -185.85 -10.5194 -67.4049 -185.9 -12.8336 -67.35 -185.95 -15.0896 -67.2935 -186 -17.2857 -67.2348 -186.05 -19.4213 -67.1735 -186.1 -21.4973 -67.1087 -186.15 -23.5157 -67.0396 -186.2 -25.4794 -66.9651 -186.25 -27.3919 -66.8837 -186.3 -29.2577 -66.7938 -186.35 -31.0821 -66.6933 -186.4 -32.8709 -66.5797 -186.45 -34.6306 -66.4496 -186.5 -36.3681 -66.2994 -186.55 -38.0904 -66.1241 -186.6 -39.8047 -65.9179 -186.65 -41.5179 -65.6735 -186.7 -43.2359 -65.3819 -186.75 -44.9632 -65.0322 -186.8 -46.7024 -64.6108 -186.85 -48.453 -64.1009 -186.9 -50.2107 -63.482 -186.95 -51.9666 -62.7285 -187 -53.707 -61.8089 -187.05 -55.4131 -60.6839 -187.1 -57.0619 -59.3047 -187.15 -58.6285 -57.6096 -187.2 -60.0886 -55.5204 -187.25 -61.4217 -52.936 -187.3 -62.6134 -49.7234 -187.35 -63.6572 -45.7027 -187.4 -64.5544 -40.6244 -187.45 -65.3126 -34.1393 -187.5 -65.9441 -25.7783 -187.55 -66.4634 -15.0314 -187.6 -66.8857 -1.7671 -187.65 -67.2254 12.8181 -187.7 -67.4953 25.816 -187.75 -67.707 34.66 -187.8 -67.87 39.2294 -187.85 -67.9923 40.9354 -187.9 -68.0805 41.0865 -187.95 -68.1403 40.4237 -188 -68.1761 39.2909 -188.05 -68.1916 37.8412 -188.1 -68.1901 36.1495 -188.15 -68.174 34.2603 -188.2 -68.1455 32.2062 -188.25 -68.1065 30.0149 -188.3 -68.0583 27.7111 -188.35 -68.0024 25.3175 -188.4 -67.9398 22.8544 -188.45 -67.8713 20.3403 -188.5 -67.7977 17.7914 -188.55 -67.7198 15.2219 -188.6 -67.638 12.6439 -188.65 -67.5528 10.0674 -188.7 -67.4646 7.50089 -188.75 -67.3739 4.95096 -188.8 -67.2808 2.42285 -188.85 -67.1857 -0.0796008 -188.9 -67.0887 -2.55367 -188.95 -66.9901 -4.99772 -189 -66.89 -7.41093 -189.05 -66.7886 -9.79347 -189.1 -66.6859 -12.146 -189.15 -66.5822 -14.4703 -189.2 -66.4775 -16.7687 -189.25 -66.3719 -19.0445 -189.3 -66.2654 -21.302 -189.35 -66.1582 -23.5474 -189.4 -66.0503 -25.7882 -189.45 -65.9417 -28.034 -189.5 -65.8325 -30.2977 -189.55 -65.7228 -32.5953 -189.6 -65.6125 -34.9465 -189.65 -65.5018 -37.3752 -189.7 -65.3906 -39.9097 -189.75 -65.279 -42.5811 -189.8 -65.167 -45.4211 -189.85 -65.0547 -48.4563 -189.9 -64.942 -51.6978 -189.95 -64.829 -55.1264 -190 -64.7157 -58.6737 -190.05 -64.6022 -62.2078 -190.1 -64.4884 -65.5404 -190.15 -64.3744 -68.4699 -190.2 -64.2602 -70.8503 -190.25 -64.1457 -72.6411 -190.3 -64.0312 -73.9028 -190.35 -63.9164 -74.7492 -190.4 -63.8016 -75.2985 -190.45 -63.6866 -75.6476 -190.5 -63.5715 -75.8662 -190.55 -63.4563 -76.001 -190.6 -63.341 -76.0821 -190.65 -63.2257 -76.1289 -190.7 -63.1104 -76.1534 -190.75 -62.995 -76.1633 -190.8 -62.8796 -76.1635 -190.85 -62.7642 -76.1571 -190.9 -62.6488 -76.1462 -190.95 -62.5334 -76.1321 -191 -62.4181 -76.1157 -191.05 -62.3028 -76.0976 -191.1 -62.1876 -76.0781 -191.15 -62.0725 -76.0576 -191.2 -61.9574 -76.0362 -191.25 -61.8425 -76.0141 -191.3 -61.7276 -75.9913 -191.35 -61.6129 -75.9678 -191.4 -61.4982 -75.9438 -191.45 -61.3838 -75.9193 -191.5 -61.2694 -75.8942 -191.55 -61.1553 -75.8686 -191.6 -61.0412 -75.8425 -191.65 -60.9274 -75.816 -191.7 -60.8137 -75.7889 -191.75 -60.7003 -75.7613 -191.8 -60.587 -75.7332 -191.85 -60.4739 -75.7047 -191.9 -60.3611 -75.6756 -191.95 -60.2484 -75.646 -192 -60.136 -75.616 -192.05 -60.0238 -75.5854 -192.1 -59.9118 -75.5544 -192.15 -59.8001 -75.5228 -192.2 -59.6886 -75.4907 -192.25 -59.5773 -75.4581 -192.3 -59.4663 -75.4251 -192.35 -59.3556 -75.3915 -192.4 -59.2451 -75.3573 -192.45 -59.1348 -75.3227 -192.5 -59.0248 -75.2876 -192.55 -58.9151 -75.2519 -192.6 -58.8056 -75.2158 -192.65 -58.6964 -75.1791 -192.7 -58.5874 -75.1419 -192.75 -58.4787 -75.1042 -192.8 -58.3703 -75.066 -192.85 -58.2621 -75.0273 -192.9 -58.1542 -74.9881 -192.95 -58.0465 -74.9483 -193 -57.9391 -74.9081 -193.05 -57.8319 -74.8673 -193.1 -57.725 -74.8261 -193.15 -57.6183 -74.7843 -193.2 -57.5119 -74.742 -193.25 -57.4057 -74.6993 -193.3 -57.2997 -74.656 -193.35 -57.1939 -74.6123 -193.4 -57.0884 -74.568 -193.45 -56.983 -74.5233 -193.5 -56.8779 -74.4781 -193.55 -56.773 -74.4325 -193.6 -56.6682 -74.3863 -193.65 -56.5637 -74.3397 -193.7 -56.4593 -74.2926 -193.75 -56.355 -74.2451 -193.8 -56.2509 -74.1971 -193.85 -56.147 -74.1487 -193.9 -56.0432 -74.0998 -193.95 -55.9395 -74.0505 -194 -55.8359 -74.0008 -194.05 -55.7324 -73.9506 -194.1 -55.629 -73.9001 -194.15 -55.5257 -73.8491 -194.2 -55.4224 -73.7977 -194.25 -55.3192 -73.7459 -194.3 -55.216 -73.6937 -194.35 -55.1128 -73.6412 -194.4 -55.0096 -73.5883 -194.45 -54.9064 -73.535 -194.5 -54.8031 -73.4813 -194.55 -54.6998 -73.4273 -194.6 -54.5964 -73.373 -194.65 -54.493 -73.3183 -194.7 -54.3893 -73.2633 -194.75 -54.2856 -73.208 -194.8 -54.1817 -73.1524 -194.85 -54.0775 -73.0965 -194.9 -53.9732 -73.0403 -194.95 -53.8687 -72.9838 -195 -53.7638 -72.927 -195.05 -53.6587 -72.87 -195.1 -53.5532 -72.8127 -195.15 -53.4474 -72.7552 -195.2 -53.3412 -72.6974 -195.25 -53.2345 -72.6395 -195.3 -53.1274 -72.5813 -195.35 -53.0198 -72.5229 -195.4 -52.9116 -72.4643 -195.45 -52.8028 -72.4055 -195.5 -52.6934 -72.3465 -195.55 -52.5833 -72.2874 -195.6 -52.4725 -72.2281 -195.65 -52.3608 -72.1686 -195.7 -52.2483 -72.1091 -195.75 -52.1349 -72.0494 -195.8 -52.0205 -71.9896 -195.85 -51.905 -71.9296 -195.9 -51.7885 -71.8696 -195.95 -51.6707 -71.8095 -196 -51.5516 -71.7493 -196.05 -51.4311 -71.689 -196.1 -51.3091 -71.6287 -196.15 -51.1856 -71.5683 -196.2 -51.0603 -71.5078 -196.25 -50.9332 -71.4474 -196.3 -50.8041 -71.3869 -196.35 -50.6729 -71.3263 -196.4 -50.5395 -71.2658 -196.45 -50.4036 -71.2053 -196.5 -50.2651 -71.1448 -196.55 -50.1238 -71.0843 -196.6 -49.9794 -71.0239 -196.65 -49.8317 -70.9634 -196.7 -49.6805 -70.9031 -196.75 -49.5255 -70.8427 -196.8 -49.3663 -70.7825 -196.85 -49.2026 -70.7223 -196.9 -49.0341 -70.6622 -196.95 -48.8602 -70.6021 -197 -48.6805 -70.5422 -197.05 -48.4946 -70.4823 -197.1 -48.3017 -70.4225 -197.15 -48.1013 -70.3629 -197.2 -47.8927 -70.3034 -197.25 -47.6749 -70.244 -197.3 -47.4471 -70.1847 -197.35 -47.2082 -70.1256 -197.4 -46.957 -70.0666 -197.45 -46.6921 -70.0078 -197.5 -46.4121 -69.9492 -197.55 -46.1152 -69.8907 -197.6 -45.7992 -69.8324 -197.65 -45.4619 -69.7742 -197.7 -45.1005 -69.7163 -197.75 -44.7118 -69.6585 -197.8 -44.2922 -69.6009 -197.85 -43.8372 -69.5435 -197.9 -43.3417 -69.4863 -197.95 -42.7997 -69.4293 -198 -42.2039 -69.3725 -198.05 -41.5457 -69.3159 -198.1 -40.8148 -69.2595 -198.15 -39.9987 -69.2034 -198.2 -39.0825 -69.1475 -198.25 -38.048 -69.0918 -198.3 -36.8736 -69.0363 -198.35 -35.5331 -68.9811 -198.4 -33.9952 -68.9262 -198.45 -32.2234 -68.8714 -198.5 -30.1754 -68.817 -198.55 -27.8047 -68.7627 -198.6 -25.0635 -68.7087 -198.65 -21.9087 -68.6549 -198.7 -18.3124 -68.6013 -198.75 -14.2786 -68.548 -198.8 -9.86309 -68.4949 -198.85 -5.19348 -68.442 -198.9 -0.476626 -68.3894 -198.95 4.01865 -68.337 -199 8.00732 -68.2849 -199.05 11.2484 -68.233 -199.1 13.5925 -68.1813 -199.15 14.9981 -68.1298 -199.2 15.5151 -68.0785 -199.25 15.2531 -68.0274 -199.3 14.3476 -67.9765 -199.35 12.9359 -67.9257 -199.4 11.1428 -67.875 -199.45 9.07439 -67.8243 -199.5 6.81672 -67.7737 -199.55 4.43768 -67.723 -199.6 1.9895 -67.6722 -199.65 -0.48839 -67.6212 -199.7 -2.96672 -67.5698 -199.75 -5.42418 -67.5179 -199.8 -7.84558 -67.4653 -199.85 -10.2204 -67.4118 -199.9 -12.5418 -67.3571 -199.95 -14.8054 -67.3008 -200 -17.0091 -67.2425 -200.05 -19.1524 -67.1815 -200.1 -21.236 -67.1172 -200.15 -23.2616 -67.0487 -200.2 -25.2321 -66.9749 -200.25 -27.1509 -66.8945 -200.3 -29.0224 -66.8058 -200.35 -30.8518 -66.7068 -200.4 -32.6448 -66.595 -200.45 -34.4078 -66.4672 -200.5 -36.1477 -66.3198 -200.55 -37.8715 -66.148 -200.6 -39.5864 -65.9461 -200.65 -41.2994 -65.707 -200.7 -43.0165 -65.422 -200.75 -44.7424 -65.0804 -200.8 -46.4801 -64.669 -200.85 -48.2293 -64.1715 -200.9 -49.9865 -63.5678 -200.95 -51.7434 -62.833 -201 -53.4867 -61.9366 -201.05 -55.1984 -60.8403 -201.1 -56.8558 -59.4966 -201.15 -58.4342 -57.8458 -201.2 -59.9092 -55.8118 -201.25 -61.2594 -53.2972 -201.3 -62.4697 -50.1735 -201.35 -63.5324 -46.268 -201.4 -64.4479 -41.3416 -201.45 -65.2233 -35.0595 -201.5 -65.8701 -26.9672 -201.55 -66.4029 -16.5471 -201.6 -66.8368 -3.57598 -201.65 -67.1862 10.9756 -201.7 -67.4644 24.3571 -201.75 -67.6829 33.791 -201.8 -67.8516 38.839 -201.85 -67.9787 40.8259 -201.9 -68.071 41.123 -201.95 -68.1341 40.5389 -202 -68.1727 39.455 -202.05 -68.1906 38.0406 -202.1 -68.1911 36.3769 -202.15 -68.1768 34.5109 -202.2 -68.1498 32.4762 -202.25 -68.112 30.301 -202.3 -68.0649 28.0103 -202.35 -68.0099 25.6269 -202.4 -67.9481 23.1716 -202.45 -67.8803 20.663 -202.5 -67.8073 18.1177 -202.55 -67.7299 15.5501 -202.6 -67.6486 12.9726 -202.65 -67.5638 10.3954 -202.7 -67.476 7.82721 -202.75 -67.3856 5.27485 -202.8 -67.2928 2.74371 -202.85 -67.1979 0.23781 -202.9 -67.1011 -2.23999 -202.95 -67.0027 -4.68793 -203 -66.9028 -7.10511 -203.05 -66.8015 -9.4915 -203.1 -66.6991 -11.8479 -203.15 -66.5955 -14.1756 -203.2 -66.4909 -16.4771 -203.25 -66.3854 -18.7556 -203.3 -66.279 -21.0152 -203.35 -66.1719 -23.2616 -203.4 -66.0641 -25.5024 -203.45 -65.9556 -27.7471 -203.5 -65.8465 -30.0077 -203.55 -65.7368 -32.2999 -203.6 -65.6266 -34.643 -203.65 -65.5159 -37.0604 -203.7 -65.4048 -39.5797 -203.75 -65.2933 -42.2319 -203.8 -65.1813 -45.0488 -203.85 -65.069 -48.058 -203.9 -64.9564 -51.2735 -203.95 -64.8434 -54.6809 -204 -64.7302 -58.219 -204.05 -64.6167 -61.7642 -204.1 -64.5029 -65.1341 -204.15 -64.3889 -68.125 -204.2 -64.2747 -70.5801 -204.25 -64.1603 -72.4443 -204.3 -64.0458 -73.7677 -204.35 -63.9311 -74.6601 -204.4 -63.8162 -75.2414 -204.45 -63.7012 -75.6116 -204.5 -63.5861 -75.8438 -204.55 -63.471 -75.9873 -204.6 -63.3557 -76.074 -204.65 -63.2404 -76.1244 -204.7 -63.1251 -76.1512 -204.75 -63.0097 -76.1626 -204.8 -62.8943 -76.1638 -204.85 -62.7789 -76.1582 -204.9 -62.6635 -76.1478 -204.95 -62.5481 -76.134 -205 -62.4328 -76.1179 -205.05 -62.3175 -76.0999 -205.1 -62.2023 -76.0806 -205.15 -62.0871 -76.0603 -205.2 -61.9721 -76.039 -205.25 -61.8571 -76.0169 -205.3 -61.7422 -75.9942 -205.35 -61.6275 -75.9708 -205.4 -61.5128 -75.9469 -205.45 -61.3983 -75.9224 -205.5 -61.284 -75.8974 -205.55 -61.1698 -75.8719 -205.6 -61.0558 -75.8459 -205.65 -60.9419 -75.8194 -205.7 -60.8282 -75.7924 -205.75 -60.7147 -75.7648 -205.8 -60.6014 -75.7368 -205.85 -60.4883 -75.7083 -205.9 -60.3754 -75.6793 -205.95 -60.2627 -75.6498 -206 -60.1503 -75.6198 -206.05 -60.0381 -75.5893 -206.1 -59.9261 -75.5583 -206.15 -59.8143 -75.5268 -206.2 -59.7028 -75.4948 -206.25 -59.5915 -75.4623 -206.3 -59.4804 -75.4293 -206.35 -59.3697 -75.3958 -206.4 -59.2591 -75.3617 -206.45 -59.1488 -75.3272 -206.5 -59.0388 -75.2921 -206.55 -58.929 -75.2565 -206.6 -58.8195 -75.2204 -206.65 -58.7103 -75.1838 -206.7 -58.6013 -75.1467 -206.75 -58.4926 -75.1091 -206.8 -58.3841 -75.0709 -206.85 -58.2759 -75.0323 -206.9 -58.1679 -74.9931 -206.95 -58.0602 -74.9534 -207 -57.9528 -74.9132 -207.05 -57.8456 -74.8725 -207.1 -57.7386 -74.8313 -207.15 -57.6319 -74.7896 -207.2 -57.5254 -74.7474 -207.25 -57.4192 -74.7047 -207.3 -57.3132 -74.6616 -207.35 -57.2074 -74.6179 -207.4 -57.1018 -74.5737 -207.45 -56.9964 -74.529 -207.5 -56.8913 -74.4839 -207.55 -56.7863 -74.4383 -207.6 -56.6816 -74.3922 -207.65 -56.577 -74.3457 -207.7 -56.4725 -74.2986 -207.75 -56.3683 -74.2512 -207.8 -56.2642 -74.2033 -207.85 -56.1602 -74.1549 -207.9 -56.0564 -74.1061 -207.95 -55.9527 -74.0568 -208 -55.8491 -74.0071 -208.05 -55.7456 -73.957 -208.1 -55.6422 -73.9065 -208.15 -55.5389 -73.8556 -208.2 -55.4356 -73.8043 -208.25 -55.3324 -73.7525 -208.3 -55.2292 -73.7004 -208.35 -55.126 -73.6479 -208.4 -55.0228 -73.595 -208.45 -54.9195 -73.5418 -208.5 -54.8163 -73.4882 -208.55 -54.713 -73.4342 -208.6 -54.6096 -73.3799 -208.65 -54.5061 -73.3253 -208.7 -54.4025 -73.2703 -208.75 -54.2988 -73.2151 -208.8 -54.1949 -73.1595 -208.85 -54.0908 -73.1036 -208.9 -53.9865 -73.0474 -208.95 -53.882 -72.991 -209 -53.7772 -72.9343 -209.05 -53.6721 -72.8773 -209.1 -53.5667 -72.82 -209.15 -53.4609 -72.7625 -209.2 -53.3547 -72.7048 -209.25 -53.2481 -72.6469 -209.3 -53.1411 -72.5887 -209.35 -53.0335 -72.5303 -209.4 -52.9254 -72.4717 -209.45 -52.8167 -72.413 -209.5 -52.7074 -72.354 -209.55 -52.5974 -72.2949 -209.6 -52.4866 -72.2356 -209.65 -52.3751 -72.1762 -209.7 -52.2627 -72.1167 -209.75 -52.1494 -72.057 -209.8 -52.0351 -71.9972 -209.85 -51.9198 -71.9373 -209.9 -51.8034 -71.8773 -209.95 -51.6857 -71.8172 -210 -51.5668 -71.757 -210.05 -51.4465 -71.6967 -210.1 -51.3248 -71.6364 -210.15 -51.2014 -71.576 -210.2 -51.0764 -71.5155 -210.25 -50.9495 -71.4551 -210.3 -50.8207 -71.3946 -210.35 -50.6898 -71.3341 -210.4 -50.5566 -71.2735 -210.45 -50.4211 -71.213 -210.5 -50.2829 -71.1525 -210.55 -50.1419 -71.092 -210.6 -49.9979 -71.0316 -210.65 -49.8507 -70.9711 -210.7 -49.7 -70.9108 -210.75 -49.5455 -70.8504 -210.8 -49.3868 -70.7902 -210.85 -49.2237 -70.73 -210.9 -49.0558 -70.6698 -210.95 -48.8826 -70.6098 -211 -48.7037 -70.5498 -211.05 -48.5186 -70.4899 -211.1 -48.3267 -70.4301 -211.15 -48.1273 -70.3705 -211.2 -47.9197 -70.3109 -211.25 -47.7031 -70.2515 -211.3 -47.4767 -70.1923 -211.35 -47.2392 -70.1331 -211.4 -46.9897 -70.0741 -211.45 -46.7267 -70.0153 -211.5 -46.4487 -69.9566 -211.55 -46.154 -69.8981 -211.6 -45.8406 -69.8398 -211.65 -45.5061 -69.7816 -211.7 -45.148 -69.7237 -211.75 -44.763 -69.6659 -211.8 -44.3475 -69.6082 -211.85 -43.8973 -69.5508 -211.9 -43.4073 -69.4936 -211.95 -42.8716 -69.4365 -212 -42.2831 -69.3797 -212.05 -41.6334 -69.3231 -212.1 -40.9124 -69.2667 -212.15 -40.1079 -69.2105 -212.2 -39.2054 -69.1546 -212.25 -38.1871 -69.0989 -212.3 -37.0319 -69.0434 -212.35 -35.7141 -68.9882 -212.4 -34.2034 -68.9332 -212.45 -32.4635 -68.8784 -212.5 -30.4532 -68.8239 -212.55 -28.1264 -68.7696 -212.6 -25.435 -68.7155 -212.65 -22.3348 -68.6617 -212.7 -18.7955 -68.6081 -212.75 -14.8156 -68.5548 -212.8 -10.4432 -68.5016 -212.85 -5.7961 -68.4488 -212.9 -1.07126 -68.3961 -212.95 3.46833 -68.3437 -213 7.53644 -68.2915 -213.05 10.8832 -68.2396 -213.1 13.3462 -68.1878 -213.15 14.8701 -68.1363 -213.2 15.4952 -68.085 -213.25 15.3252 -68.0339 -213.3 14.4939 -67.9829 -213.35 13.1394 -67.9321 -213.4 11.3886 -67.8814 -213.45 9.35005 -67.8308 -213.5 7.11235 -67.7801 -213.55 4.74557 -67.7295 -213.6 2.30376 -67.6787 -213.65 -0.172163 -67.6277 -213.7 -2.65177 -67.5763 -213.75 -5.11284 -67.5245 -213.8 -7.53951 -67.4721 -213.85 -9.92073 -67.4187 -213.9 -12.2492 -67.3642 -213.95 -14.5203 -67.3081 -214 -16.7317 -67.25 -214.05 -18.8827 -67.1894 -214.1 -20.9738 -67.1256 -214.15 -23.0067 -67.0577 -214.2 -24.984 -66.9847 -214.25 -26.9092 -66.9052 -214.3 -28.7865 -66.8177 -214.35 -30.621 -66.7201 -214.4 -32.4182 -66.6101 -214.45 -34.1847 -66.4845 -214.5 -35.9271 -66.3398 -214.55 -37.6525 -66.1714 -214.6 -39.3682 -65.9737 -214.65 -41.0811 -65.7398 -214.7 -42.7973 -65.4613 -214.75 -44.5219 -65.1275 -214.8 -46.258 -64.7258 -214.85 -48.0059 -64.2403 -214.9 -49.7624 -63.6514 -214.95 -51.52 -62.9349 -215 -53.266 -62.061 -215.05 -54.9828 -60.9927 -215.1 -56.6484 -59.6836 -215.15 -58.2384 -58.0756 -215.2 -59.7278 -56.0955 -215.25 -61.0949 -53.6485 -215.3 -62.3236 -50.6109 -215.35 -63.4053 -46.8167 -215.4 -64.3393 -42.0366 -215.45 -65.1319 -35.95 -215.5 -65.7944 -28.1174 -215.55 -66.3409 -18.019 -215.6 -66.7865 -5.35503 -215.65 -67.1459 9.11575 -215.7 -67.4325 22.8312 -215.75 -67.658 32.8491 -215.8 -67.8326 38.3995 -215.85 -67.9646 40.69 -215.9 -68.0609 41.1458 -215.95 -68.1275 40.6463 -216 -68.169 39.6138 -216.05 -68.1894 38.2359 -216.1 -68.1919 36.6009 -216.15 -68.1793 34.7587 -216.2 -68.1538 32.7438 -216.25 -68.1173 30.5851 -216.3 -68.0714 28.3078 -216.35 -68.0173 25.935 -216.4 -67.9563 23.4878 -216.45 -67.8892 20.985 -216.5 -67.8169 18.4436 -216.55 -67.74 15.8781 -216.6 -67.6591 13.3012 -216.65 -67.5748 10.7235 -216.7 -67.4874 8.15371 -216.75 -67.3972 5.59901 -216.8 -67.3047 3.06491 -216.85 -67.2101 0.555634 -216.9 -67.1136 -1.92589 -216.95 -67.0153 -4.37767 -217 -66.9156 -6.79881 -217.05 -66.8145 -9.18909 -217.1 -66.7122 -11.5492 -217.15 -66.6087 -13.8805 -217.2 -66.5043 -16.1852 -217.25 -66.3989 -18.4663 -217.3 -66.2926 -20.7281 -217.35 -66.1856 -22.976 -217.4 -66.0778 -25.2169 -217.45 -65.9694 -27.4604 -217.5 -65.8604 -29.7183 -217.55 -65.7508 -32.0055 -217.6 -65.6407 -34.3408 -217.65 -65.5301 -36.7473 -217.7 -65.419 -39.252 -217.75 -65.3075 -41.8854 -217.8 -65.1956 -44.6797 -217.85 -65.0833 -47.6632 -217.9 -64.9707 -50.8524 -217.95 -64.8578 -54.2377 -218 -64.7446 -57.7646 -218.05 -64.6311 -61.3181 -218.1 -64.5174 -64.7217 -218.15 -64.4035 -67.7714 -218.2 -64.2893 -70.3002 -218.25 -64.1749 -72.2388 -218.3 -64.0604 -73.6256 -218.35 -63.9457 -74.5661 -218.4 -63.8308 -75.1809 -218.45 -63.7159 -75.5734 -218.5 -63.6008 -75.82 -218.55 -63.4857 -75.9727 -218.6 -63.3704 -76.0653 -218.65 -63.2551 -76.1195 -218.7 -63.1398 -76.1488 -218.75 -63.0244 -76.1618 -218.8 -62.909 -76.1641 -218.85 -62.7936 -76.1592 -218.9 -62.6782 -76.1493 -218.95 -62.5628 -76.1359 -219 -62.4475 -76.12 -219.05 -62.3322 -76.1023 -219.1 -62.217 -76.0832 -219.15 -62.1018 -76.0629 -219.2 -61.9867 -76.0417 -219.25 -61.8717 -76.0198 -219.3 -61.7569 -75.9971 -219.35 -61.6421 -75.9738 -219.4 -61.5274 -75.95 -219.45 -61.4129 -75.9256 -219.5 -61.2986 -75.9007 -219.55 -61.1843 -75.8752 -219.6 -61.0703 -75.8492 -219.65 -60.9564 -75.8228 -219.7 -60.8427 -75.7958 -219.75 -60.7292 -75.7684 -219.8 -60.6158 -75.7404 -219.85 -60.5027 -75.712 -219.9 -60.3898 -75.6831 -219.95 -60.2771 -75.6536 -220 -60.1646 -75.6237 -220.05 -60.0523 -75.5933 -220.1 -59.9403 -75.5623 -220.15 -59.8285 -75.5309 -220.2 -59.717 -75.4989 -220.25 -59.6056 -75.4665 -220.3 -59.4946 -75.4335 -220.35 -59.3838 -75.4001 -220.4 -59.2732 -75.3661 -220.45 -59.1629 -75.3316 -220.5 -59.0528 -75.2966 -220.55 -58.943 -75.2611 -220.6 -58.8335 -75.2251 -220.65 -58.7242 -75.1885 -220.7 -58.6152 -75.1515 -220.75 -58.5064 -75.1139 -220.8 -58.3979 -75.0758 -220.85 -58.2897 -75.0372 -220.9 -58.1817 -74.9981 -220.95 -58.0739 -74.9585 -221 -57.9665 -74.9184 -221.05 -57.8592 -74.8778 -221.1 -57.7522 -74.8366 -221.15 -57.6455 -74.795 -221.2 -57.539 -74.7529 -221.25 -57.4327 -74.7102 -221.3 -57.3267 -74.6671 -221.35 -57.2209 -74.6235 -221.4 -57.1153 -74.5794 -221.45 -57.0099 -74.5348 -221.5 -56.9047 -74.4897 -221.55 -56.7997 -74.4441 -221.6 -56.6949 -74.3981 -221.65 -56.5903 -74.3516 -221.7 -56.4858 -74.3047 -221.75 -56.3816 -74.2573 -221.8 -56.2774 -74.2094 -221.85 -56.1735 -74.1611 -221.9 -56.0696 -74.1123 -221.95 -55.9659 -74.0631 -222 -55.8623 -74.0135 -222.05 -55.7588 -73.9635 -222.1 -55.6554 -73.913 -222.15 -55.552 -73.8621 -222.2 -55.4487 -73.8108 -222.25 -55.3455 -73.7591 -222.3 -55.2423 -73.7071 -222.35 -55.1391 -73.6546 -222.4 -55.0359 -73.6018 -222.45 -54.9327 -73.5486 -222.5 -54.8295 -73.495 -222.55 -54.7262 -73.4411 -222.6 -54.6228 -73.3869 -222.65 -54.5193 -73.3323 -222.7 -54.4158 -73.2774 -222.75 -54.312 -73.2221 -222.8 -54.2082 -73.1666 -222.85 -54.1041 -73.1107 -222.9 -53.9998 -73.0546 -222.95 -53.8953 -72.9982 -223 -53.7906 -72.9415 -223.05 -53.6855 -72.8846 -223.1 -53.5801 -72.8273 -223.15 -53.4744 -72.7699 -223.2 -53.3683 -72.7122 -223.25 -53.2617 -72.6543 -223.3 -53.1547 -72.5961 -223.35 -53.0472 -72.5378 -223.4 -52.9392 -72.4792 -223.45 -52.8306 -72.4205 -223.5 -52.7213 -72.3615 -223.55 -52.6114 -72.3025 -223.6 -52.5008 -72.2432 -223.65 -52.3893 -72.1838 -223.7 -52.2771 -72.1243 -223.75 -52.1639 -72.0646 -223.8 -52.0497 -72.0048 -223.85 -51.9346 -71.9449 -223.9 -51.8183 -71.8849 -223.95 -51.7008 -71.8248 -224 -51.5821 -71.7646 -224.05 -51.4619 -71.7044 -224.1 -51.3404 -71.6441 -224.15 -51.2172 -71.5837 -224.2 -51.0924 -71.5232 -224.25 -50.9657 -71.4628 -224.3 -50.8372 -71.4023 -224.35 -50.7066 -71.3418 -224.4 -50.5737 -71.2812 -224.45 -50.4385 -71.2207 -224.5 -50.3006 -71.1602 -224.55 -50.16 -71.0997 -224.6 -50.0164 -71.0393 -224.65 -49.8696 -70.9788 -224.7 -49.7194 -70.9184 -224.75 -49.5653 -70.8581 -224.8 -49.4073 -70.7978 -224.85 -49.2448 -70.7376 -224.9 -49.0775 -70.6775 -224.95 -48.905 -70.6174 -225 -48.7269 -70.5574 -225.05 -48.5426 -70.4975 -225.1 -48.3515 -70.4378 -225.15 -48.1531 -70.3781 -225.2 -47.9466 -70.3185 -225.25 -47.7312 -70.2591 -225.3 -47.5061 -70.1998 -225.35 -47.2701 -70.1407 -225.4 -47.0222 -70.0816 -225.45 -46.761 -70.0228 -225.5 -46.485 -69.9641 -225.55 -46.1925 -69.9056 -225.6 -45.8816 -69.8472 -225.65 -45.55 -69.7891 -225.7 -45.195 -69.731 -225.75 -44.8136 -69.6732 -225.8 -44.4022 -69.6156 -225.85 -43.9567 -69.5581 -225.9 -43.4721 -69.5008 -225.95 -42.9426 -69.4438 -226 -42.3612 -69.3869 -226.05 -41.7198 -69.3303 -226.1 -41.0085 -69.2739 -226.15 -40.2154 -69.2177 -226.2 -39.3263 -69.1617 -226.25 -38.3239 -69.106 -226.3 -37.1874 -69.0505 -226.35 -35.8919 -68.9952 -226.4 -34.4076 -68.9402 -226.45 -32.6991 -68.8854 -226.5 -30.7257 -68.8308 -226.55 -28.4418 -68.7765 -226.6 -25.7994 -68.7224 -226.65 -22.7534 -68.6686 -226.7 -19.2708 -68.6149 -226.75 -15.3456 -68.5615 -226.8 -11.0183 -68.5084 -226.85 -6.39683 -68.4555 -226.9 -1.66837 -68.4028 -226.95 2.91078 -68.3504 -227 7.05413 -68.2982 -227.05 10.504 -68.2462 -227.1 13.0847 -68.1944 -227.15 14.7277 -68.1429 -227.2 15.4625 -68.0915 -227.25 15.3866 -68.0404 -227.3 14.6316 -67.9894 -227.35 13.3363 -67.9386 -227.4 11.6295 -67.8879 -227.45 9.62225 -67.8372 -227.5 7.40564 -67.7866 -227.55 5.05198 -67.7359 -227.6 2.6172 -67.6852 -227.65 0.143733 -67.6342 -227.7 -2.33679 -67.5829 -227.75 -4.80123 -67.5312 -227.8 -7.23297 -67.4788 -227.85 -9.62046 -67.4256 -227.9 -11.9559 -67.3712 -227.95 -14.2345 -67.3153 -228 -16.4536 -67.2576 -228.05 -18.6123 -67.1973 -228.1 -20.7109 -67.1339 -228.15 -22.7511 -67.0666 -228.2 -24.7352 -66.9943 -228.25 -26.6668 -66.9157 -228.3 -28.55 -66.8293 -228.35 -30.3895 -66.7332 -228.4 -32.1912 -66.6249 -228.45 -33.9612 -66.5015 -228.5 -35.7063 -66.3595 -228.55 -37.4335 -66.1944 -228.6 -39.1501 -66.0008 -228.65 -40.863 -65.7719 -228.7 -42.5785 -65.4995 -228.75 -44.3018 -65.1735 -228.8 -46.0363 -64.7813 -228.85 -47.7828 -64.3074 -228.9 -49.5386 -63.7329 -228.95 -51.2966 -63.0342 -229 -53.0449 -62.1823 -229.05 -54.7666 -61.141 -229.1 -56.4401 -59.8655 -229.15 -58.0411 -58.2993 -229.2 -59.5446 -56.3713 -229.25 -60.9283 -53.9899 -229.3 -62.1753 -51.0357 -229.35 -63.2759 -47.349 -229.4 -64.2285 -42.7101 -229.45 -65.0385 -36.8116 -229.5 -65.7168 -29.2297 -229.55 -66.2772 -19.4467 -229.6 -66.7348 -7.10066 -229.65 -67.1044 7.24585 -229.7 -67.3996 21.2427 -229.75 -67.6324 31.8324 -229.8 -67.8129 37.9074 -229.85 -67.9499 40.5253 -229.9 -68.0504 41.1537 -229.95 -68.1205 40.7453 -230 -68.165 39.7671 -230.05 -68.1878 38.427 -230.1 -68.1925 36.8215 -230.15 -68.1817 35.0035 -230.2 -68.1577 33.009 -230.25 -68.1225 30.8671 -230.3 -68.0777 28.6035 -230.35 -68.0246 26.2417 -230.4 -67.9644 23.8028 -230.45 -67.8981 21.3062 -230.5 -67.8264 18.7688 -230.55 -67.75 16.2057 -230.6 -67.6696 13.6296 -230.65 -67.5857 11.0515 -230.7 -67.4986 8.48026 -230.75 -67.4088 5.9233 -230.8 -67.3166 3.38632 -230.85 -67.2222 0.873677 -230.9 -67.1259 -1.6115 -230.95 -67.0279 -4.06716 -231 -66.9284 -6.4922 -231.05 -66.8275 -8.88642 -231.1 -66.7253 -11.2503 -231.15 -66.622 -13.5852 -231.2 -66.5176 -15.8931 -231.25 -66.4123 -18.177 -231.3 -66.3062 -20.441 -231.35 -66.1993 -22.6902 -231.4 -66.0916 -24.9317 -231.45 -65.9833 -27.1742 -231.5 -65.8743 -29.4294 -231.55 -65.7648 -31.712 -231.6 -65.6547 -34.0401 -231.65 -65.5442 -36.436 -231.7 -65.4332 -38.9266 -231.75 -65.3217 -41.5418 -231.8 -65.2099 -44.3138 -231.85 -65.0977 -47.272 -231.9 -64.9851 -50.4348 -231.95 -64.8722 -53.7969 -232 -64.7591 -57.3109 -232.05 -64.6456 -60.8696 -232.1 -64.5319 -64.3037 -232.15 -64.418 -67.4092 -232.2 -64.3038 -70.0105 -232.25 -64.1895 -72.0242 -232.3 -64.075 -73.4764 -232.35 -63.9603 -74.4669 -232.4 -63.8455 -75.1169 -232.45 -63.7305 -75.5328 -232.5 -63.6155 -75.7947 -232.55 -63.5003 -75.9571 -232.6 -63.3851 -76.056 -232.65 -63.2698 -76.1142 -232.7 -63.1545 -76.1461 -232.75 -63.0391 -76.1609 -232.8 -62.9237 -76.1643 -232.85 -62.8083 -76.1601 -232.9 -62.6929 -76.1508 -232.95 -62.5775 -76.1378 -233 -62.4622 -76.1222 -233.05 -62.3469 -76.1047 -233.1 -62.2316 -76.0857 -233.15 -62.1165 -76.0655 -233.2 -62.0014 -76.0445 -233.25 -61.8864 -76.0226 -233.3 -61.7715 -76 -233.35 -61.6567 -75.9768 -233.4 -61.542 -75.9531 -233.45 -61.4275 -75.9287 -233.5 -61.3131 -75.9039 -233.55 -61.1989 -75.8785 -233.6 -61.0848 -75.8526 -233.65 -60.9709 -75.8262 -233.7 -60.8572 -75.7993 -233.75 -60.7436 -75.7719 -233.8 -60.6303 -75.744 -233.85 -60.5171 -75.7156 -233.9 -60.4042 -75.6868 -233.95 -60.2914 -75.6574 -234 -60.1789 -75.6275 -234.05 -60.0666 -75.5972 -234.1 -59.9546 -75.5663 -234.15 -59.8427 -75.5349 -234.2 -59.7312 -75.503 -234.25 -59.6198 -75.4707 -234.3 -59.5087 -75.4378 -234.35 -59.3979 -75.4044 -234.4 -59.2873 -75.3704 -234.45 -59.1769 -75.336 -234.5 -59.0668 -75.3011 -234.55 -58.957 -75.2656 -234.6 -58.8474 -75.2297 -234.65 -58.7381 -75.1932 -234.7 -58.629 -75.1562 -234.75 -58.5203 -75.1187 -234.8 -58.4117 -75.0807 -234.85 -58.3034 -75.0422 -234.9 -58.1954 -75.0031 -234.95 -58.0876 -74.9636 -235 -57.9801 -74.9235 -235.05 -57.8729 -74.883 -235.1 -57.7659 -74.8419 -235.15 -57.6591 -74.8003 -235.2 -57.5525 -74.7582 -235.25 -57.4462 -74.7157 -235.3 -57.3402 -74.6726 -235.35 -57.2343 -74.629 -235.4 -57.1287 -74.585 -235.45 -57.0233 -74.5405 -235.5 -56.9181 -74.4955 -235.55 -56.813 -74.45 -235.6 -56.7082 -74.404 -235.65 -56.6036 -74.3576 -235.7 -56.4991 -74.3107 -235.75 -56.3948 -74.2633 -235.8 -56.2907 -74.2155 -235.85 -56.1867 -74.1672 -235.9 -56.0828 -74.1185 -235.95 -55.9791 -74.0694 -236 -55.8755 -74.0198 -236.05 -55.772 -73.9698 -236.1 -55.6685 -73.9194 -236.15 -55.5652 -73.8686 -236.2 -55.4619 -73.8174 -236.25 -55.3587 -73.7658 -236.3 -55.2554 -73.7137 -236.35 -55.1522 -73.6613 -236.4 -55.0491 -73.6085 -236.45 -54.9458 -73.5554 -236.5 -54.8426 -73.5019 -236.55 -54.7393 -73.448 -236.6 -54.636 -73.3938 -236.65 -54.5325 -73.3392 -236.7 -54.429 -73.2844 -236.75 -54.3253 -73.2292 -236.8 -54.2214 -73.1737 -236.85 -54.1174 -73.1179 -236.9 -54.0131 -73.0618 -236.95 -53.9086 -73.0054 -237 -53.8039 -72.9487 -237.05 -53.6989 -72.8918 -237.1 -53.5936 -72.8346 -237.15 -53.4879 -72.7772 -237.2 -53.3818 -72.7195 -237.25 -53.2753 -72.6616 -237.3 -53.1684 -72.6035 -237.35 -53.061 -72.5452 -237.4 -52.953 -72.4867 -237.45 -52.8444 -72.428 -237.5 -52.7353 -72.3691 -237.55 -52.6255 -72.31 -237.6 -52.5149 -72.2508 -237.65 -52.4036 -72.1914 -237.7 -52.2914 -72.1319 -237.75 -52.1783 -72.0722 -237.8 -52.0643 -72.0124 -237.85 -51.9493 -71.9525 -237.9 -51.8331 -71.8926 -237.95 -51.7158 -71.8325 -238 -51.5972 -71.7723 -238.05 -51.4773 -71.7121 -238.1 -51.3559 -71.6517 -238.15 -51.233 -71.5914 -238.2 -51.1084 -71.5309 -238.25 -50.982 -71.4705 -238.3 -50.8537 -71.41 -238.35 -50.7233 -71.3495 -238.4 -50.5908 -71.289 -238.45 -50.4558 -71.2284 -238.5 -50.3183 -71.1679 -238.55 -50.1781 -71.1074 -238.6 -50.0349 -71.047 -238.65 -49.8885 -70.9865 -238.7 -49.7387 -70.9261 -238.75 -49.5852 -70.8658 -238.8 -49.4276 -70.8055 -238.85 -49.2657 -70.7453 -238.9 -49.099 -70.6851 -238.95 -48.9272 -70.625 -239 -48.7499 -70.5651 -239.05 -48.5664 -70.5052 -239.1 -48.3762 -70.4454 -239.15 -48.1788 -70.3857 -239.2 -47.9734 -70.3261 -239.25 -47.7592 -70.2667 -239.3 -47.5353 -70.2073 -239.35 -47.3008 -70.1482 -239.4 -47.0544 -70.0892 -239.45 -46.795 -70.0303 -239.5 -46.521 -69.9716 -239.55 -46.2307 -69.913 -239.6 -45.9223 -69.8547 -239.65 -45.5934 -69.7964 -239.7 -45.2416 -69.7384 -239.75 -44.8637 -69.6806 -239.8 -44.4564 -69.6229 -239.85 -44.0155 -69.5654 -239.9 -43.5361 -69.5081 -239.95 -43.0127 -69.451 -240 -42.4384 -69.3942 -240.05 -41.8052 -69.3375 -240.1 -41.1034 -69.281 -240.15 -40.3214 -69.2248 -240.2 -39.4454 -69.1688 -240.25 -38.4584 -69.113 -240.3 -37.3403 -69.0575 -240.35 -36.0667 -69.0022 -240.4 -34.6082 -68.9472 -240.45 -32.9304 -68.8923 -240.5 -30.9932 -68.8378 -240.55 -28.7514 -68.7834 -240.6 -26.1573 -68.7293 -240.65 -23.1649 -68.6754 -240.7 -19.739 -68.6217 -240.75 -15.869 -68.5683 -240.8 -11.5884 -68.5152 -240.85 -6.99572 -68.4622 -240.9 -2.26781 -68.4095 -240.95 2.34615 -68.357 -241 6.56049 -68.3048 -241.05 10.1104 -68.2528 -241.1 12.8079 -68.201 -241.15 14.5704 -68.1494 -241.2 15.4164 -68.0981 -241.25 15.4368 -68.0469 -241.3 14.7606 -67.9959 -241.35 13.5266 -67.9451 -241.4 11.8656 -67.8943 -241.45 9.89113 -67.8437 -241.5 7.69679 -67.793 -241.55 5.35716 -67.7424 -241.6 2.9301 -67.6916 -241.65 0.459607 -67.6407 -241.7 -2.02145 -67.5895 -241.75 -4.48898 -67.5378 -241.8 -6.92561 -67.4855 -241.85 -9.31923 -67.4324 -241.9 -11.6616 -67.3782 -241.95 -13.9477 -67.3225 -242 -16.1744 -67.265 -242.05 -18.3408 -67.2051 -242.1 -20.447 -67.1422 -242.15 -22.4945 -67.0754 -242.2 -24.4856 -67.0038 -242.25 -26.4237 -66.9261 -242.3 -28.3127 -66.8408 -242.35 -30.1575 -66.746 -242.4 -31.9637 -66.6394 -242.45 -33.7374 -66.5182 -242.5 -35.4853 -66.3787 -242.55 -37.2144 -66.2169 -242.6 -38.9319 -66.0272 -242.65 -40.6448 -65.8033 -242.7 -42.3597 -65.537 -242.75 -44.0818 -65.2184 -242.8 -45.8148 -64.8354 -242.85 -47.5599 -64.3729 -242.9 -49.3147 -63.8124 -242.95 -51.073 -63.131 -243 -52.8234 -62.3004 -243.05 -54.5496 -61.2855 -243.1 -56.2306 -60.0427 -243.15 -57.8422 -58.5171 -243.2 -59.3594 -56.6397 -243.25 -60.7595 -54.322 -243.3 -62.0245 -51.4486 -243.35 -63.144 -47.8658 -243.4 -64.1153 -43.3629 -243.45 -64.943 -37.6457 -243.5 -65.6373 -30.3057 -243.55 -66.2119 -20.831 -243.6 -66.6818 -8.81003 -243.65 -67.0618 5.37285 -243.7 -67.3657 19.5967 -243.75 -67.6058 30.7399 -243.8 -67.7925 37.3593 -243.85 -67.9346 40.3294 -243.9 -68.0394 41.1455 -243.95 -68.1131 40.8353 -244 -68.1606 39.9146 -244.05 -68.186 38.6138 -244.1 -68.1928 37.0386 -244.15 -68.1839 35.2454 -244.2 -68.1615 33.2716 -244.25 -68.1276 31.147 -244.3 -68.0839 28.8976 -244.35 -68.0318 26.547 -244.4 -67.9725 24.1169 -244.45 -67.9068 21.6266 -244.5 -67.8358 19.0936 -244.55 -67.76 16.5329 -244.6 -67.6801 13.9579 -244.65 -67.5966 11.3794 -244.7 -67.5099 8.80691 -244.75 -67.4204 6.24778 -244.8 -67.3285 3.708 -244.85 -67.2344 1.19206 -244.9 -67.1383 -1.29673 -244.95 -67.0405 -3.75624 -245 -66.9411 -6.18521 -245.05 -66.8404 -8.58333 -245.1 -66.7384 -10.951 -245.15 -66.6352 -13.2894 -245.2 -66.531 -15.6007 -245.25 -66.4258 -17.8875 -245.3 -66.3198 -20.1537 -245.35 -66.2129 -22.4044 -245.4 -66.1053 -24.6465 -245.45 -65.9971 -26.8883 -245.5 -65.8882 -29.1412 -245.55 -65.7788 -31.4192 -245.6 -65.6688 -33.7404 -245.65 -65.5583 -36.1264 -245.7 -65.4473 -38.6032 -245.75 -65.3359 -41.2009 -245.8 -65.2241 -43.9512 -245.85 -65.112 -46.8843 -245.9 -64.9995 -50.0208 -245.95 -64.8866 -53.3592 -246 -64.7735 -56.8584 -246.05 -64.6601 -60.4197 -246.1 -64.5464 -63.8807 -246.15 -64.4325 -67.0391 -246.2 -64.3184 -69.7117 -246.25 -64.2041 -71.8008 -246.3 -64.0896 -73.3198 -246.35 -63.9749 -74.3623 -246.4 -63.8601 -75.0492 -246.45 -63.7452 -75.4899 -246.5 -63.6301 -75.7678 -246.55 -63.515 -75.9406 -246.6 -63.3998 -76.0461 -246.65 -63.2845 -76.1085 -246.7 -63.1692 -76.1432 -246.75 -63.0538 -76.1597 -246.8 -62.9384 -76.1644 -246.85 -62.823 -76.161 -246.9 -62.7076 -76.1522 -246.95 -62.5922 -76.1396 -247 -62.4769 -76.1243 -247.05 -62.3616 -76.107 -247.1 -62.2463 -76.0882 -247.15 -62.1311 -76.0682 -247.2 -62.016 -76.0472 -247.25 -61.901 -76.0254 -247.3 -61.7861 -76.003 -247.35 -61.6713 -75.9798 -247.4 -61.5566 -75.9561 -247.45 -61.4421 -75.9319 -247.5 -61.3277 -75.9071 -247.55 -61.2134 -75.8817 -247.6 -61.0993 -75.8559 -247.65 -60.9854 -75.8296 -247.7 -60.8716 -75.8027 -247.75 -60.7581 -75.7754 -247.8 -60.6447 -75.7476 -247.85 -60.5315 -75.7193 -247.9 -60.4185 -75.6905 -247.95 -60.3058 -75.6612 -248 -60.1932 -75.6314 -248.05 -60.0809 -75.6011 -248.1 -59.9688 -75.5703 -248.15 -59.857 -75.5389 -248.2 -59.7453 -75.5071 -248.25 -59.634 -75.4748 -248.3 -59.5228 -75.442 -248.35 -59.412 -75.4086 -248.4 -59.3013 -75.3748 -248.45 -59.1909 -75.3404 -248.5 -59.0808 -75.3056 -248.55 -58.971 -75.2702 -248.6 -58.8613 -75.2343 -248.65 -58.752 -75.1979 -248.7 -58.6429 -75.1609 -248.75 -58.5341 -75.1235 -248.8 -58.4255 -75.0856 -248.85 -58.3172 -75.0471 -248.9 -58.2092 -75.0081 -248.95 -58.1014 -74.9686 -249 -57.9938 -74.9286 -249.05 -57.8865 -74.8881 -249.1 -57.7795 -74.8471 -249.15 -57.6727 -74.8056 -249.2 -57.5661 -74.7636 -249.25 -57.4598 -74.7211 -249.3 -57.3537 -74.6781 -249.35 -57.2478 -74.6346 -249.4 -57.1421 -74.5906 -249.45 -57.0367 -74.5462 -249.5 -56.9314 -74.5012 -249.55 -56.8264 -74.4558 -249.6 -56.7216 -74.4099 -249.65 -56.6169 -74.3635 -249.7 -56.5124 -74.3167 -249.75 -56.4081 -74.2694 -249.8 -56.3039 -74.2216 -249.85 -56.1999 -74.1734 -249.9 -56.096 -74.1248 -249.95 -55.9923 -74.0757 -250 -55.8887 -74.0262 diff --git a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/data/compare_neuron0.png b/tests/python/Rallpacks/moose_vs_neuron/rallpack3/data/compare_neuron0.png deleted file mode 100644 index b10ab7b39048ce68d8ab9ad77a8963888459c1d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 76567 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
    $ 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 KH!m~2bo;+#K8wNt diff --git a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/data/compare_neuron1.png b/tests/python/Rallpacks/moose_vs_neuron/rallpack3/data/compare_neuron1.png deleted file mode 100644 index c464e1ac8e48337828650bd9c75546f67f9a6f97..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 78880 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 diff --git a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/data/moose.dat b/tests/python/Rallpacks/moose_vs_neuron/rallpack3/data/moose.dat deleted file mode 100644 index 92868c37..00000000 --- a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/data/moose.dat +++ /dev/null @@ -1,5001 +0,0 @@ -0.0 -0.06 -0.06 -5e-05 -0.065 -0.065 -0.0001 -0.0651573982953 -0.0651573982953 -0.00015 -0.0591036424217 -0.0653121196769 -0.0002 -0.0591822194374 -0.0654646787991 -0.00025 -0.0563278891296 -0.0656154571713 -0.0003 -0.0564020853705 -0.0657647265834 -0.00035 -0.0543239207478 -0.0659126704885 -0.0004 -0.0543666828076 -0.0660594026542 -0.00045 -0.0526408309359 -0.0662049829289 -0.0005 -0.0526255431122 -0.0663494302985 -0.00055 -0.051074964079 -0.0664927334942 -0.0006 -0.0509711862006 -0.0666348594917 -0.00065 -0.0494875544992 -0.0667757602443 -0.0007 -0.049256372403 -0.066915377962 -0.00075 -0.0477504279954 -0.067053649171 -0.0008 -0.0473361389888 -0.0671905078005 -0.00085 -0.0457107665285 -0.0673258874742 -0.0009 -0.0450251256872 -0.0674597231382 -0.00095 -0.0431465334028 -0.0675919521986 -0.001 -0.042037548584 -0.0677225152247 -0.00105 -0.0396871645011 -0.0678513563734 -0.0011 -0.037874494303 -0.0679784235619 -0.00115 -0.0346536868784 -0.0681036685078 -0.0012 -0.0315954296151 -0.0682270466542 -0.00125 -0.0267426444001 -0.0683485170344 -0.0013 -0.0214149617158 -0.0684680421148 -0.00135 -0.0136234046287 -0.0685855876177 -0.0014 -0.00464302916227 -0.0687011223374 -0.00145 0.00686694262419 -0.0688146179656 -0.0015 0.0182604857943 -0.068926048914 -0.00155 0.0289210834088 -0.0690353921308 -0.0016 0.035762336258 -0.0691426269066 -0.00165 0.040024674026 -0.0692477346577 -0.0017 0.0412493105396 -0.0693506986768 -0.00175 0.0416985139673 -0.069451503832 -0.0018 0.0406519936586 -0.0695501361922 -0.00185 0.039698721961 -0.069646582548 -0.0019 0.0377610445579 -0.0697408297831 -0.00195 0.0361709789292 -0.0698328640318 -0.002 0.0337834093539 -0.069922669551 -0.00205 0.0318321782489 -0.0700102271848 -0.0021 0.0291848138249 -0.0700955122886 -0.00215 0.027018553543 -0.0701784919637 -0.0022 0.024228186541 -0.0702591214285 -0.00225 0.0219458831725 -0.0703373393262 -0.0023 0.0190954356876 -0.0704130618006 -0.00235 0.0167689029044 -0.0704861750935 -0.0024 0.0139182412842 -0.0705565264471 -0.00245 0.0115987714138 -0.0706239129837 -0.0025 0.00878947118745 -0.0706880681828 -0.00255 0.00651182530842 -0.0707486454594 -0.0026 0.00377080520548 -0.0708051981847 -0.00265 0.00155669053545 -0.0708571553388 -0.0027 -0.00110046622333 -0.0709037917609 -0.00275 -0.00323922833141 -0.070944191714 -0.0028 -0.00580533148831 -0.0709772041726 -0.00285 -0.00786411705272 -0.0710013878686 -0.0029 -0.0103380088604 -0.0710149436723 -0.00295 -0.0123173919891 -0.0710156313335 -0.003 -0.0147023809745 -0.0710006668947 -0.00305 -0.0166070380364 -0.070966596264 -0.0031 -0.0189103388592 -0.0709091393554 -0.00315 -0.0207490508594 -0.0708229979162 -0.0032 -0.0229823817638 -0.070701618527 -0.00325 -0.0247692043642 -0.0705369002411 -0.0033 -0.0269504831874 -0.0703188337978 -0.00335 -0.0287068503117 -0.0700350561112 -0.0034 -0.030862541673 -0.0696702996104 -0.00345 -0.0326196124376 -0.0692057105205 -0.0035 -0.0347867681623 -0.0686180026913 -0.00355 -0.0365867352173 -0.0678784027528 -0.0036 -0.038812995704 -0.0669513257234 -0.00365 -0.0407069210879 -0.06579269252 -0.0037 -0.0430449248854 -0.0643477513545 -0.00375 -0.0450818499873 -0.0625481705299 -0.0038 -0.0475705078166 -0.0603079802575 -0.00385 -0.0497678254975 -0.0575175451192 -0.0039 -0.0523891213806 -0.0540339073639 -0.00395 -0.0546755657356 -0.0496640673696 -0.004 -0.0572897385072 -0.044134277283 -0.00405 -0.0594494988938 -0.0370332164499 -0.0041 -0.0617775135413 -0.0277189692028 -0.00415 -0.0635057211943 -0.0152470901678 -0.0042 -0.0652765939586 0.00126419291625 -0.00425 -0.0663951448434 0.0206125044677 -0.0043 -0.0675580472995 0.036690861629 -0.00435 -0.0681363573481 0.0438018186689 -0.0044 -0.0688430931172 0.0449617354689 -0.00445 -0.0690666506643 0.0446182642931 -0.0045 -0.0694984336858 0.0438661256791 -0.00455 -0.0695224334429 0.0428521204893 -0.0046 -0.0698022758855 0.041598240057 -0.00465 -0.0697191932418 0.0401269884479 -0.0047 -0.0699149767617 0.0384496499752 -0.00475 -0.0697736956061 0.0366078990803 -0.0048 -0.0699207943195 0.0346165154838 -0.00485 -0.0697467451962 0.032496368128 -0.0049 -0.069863854269 0.030266321406 -0.00495 -0.0696706696752 0.0279452878307 -0.005 -0.0697680992038 0.0255511277641 -0.00505 -0.0695634194131 0.0231002727771 -0.0051 -0.0696471404296 0.0206078821515 -0.00515 -0.0694354394478 0.0180872570807 -0.0052 -0.0695090728485 0.015550275006 -0.00525 -0.069293071359 0.0130069598369 -0.0053 -0.0693589039405 0.010465942874 -0.00535 -0.0691403079343 0.00793420306424 -0.0054 -0.0691998365428 0.00541748113028 -0.00545 -0.0689797421478 0.00292013813106 -0.0055 -0.0690339788578 0.000445501371589 -0.00555 -0.0688131040897 -0.00200421206454 -0.0056 -0.0688627545081 -0.00442762589985 -0.00565 -0.068641577027 -0.00682426261539 -0.0057 -0.0686871481679 -0.00919436223288 -0.00575 -0.0684659897852 -0.0115389687928 -0.0058 -0.0685078572671 -0.013859863884 -0.00585 -0.0682869371558 -0.0161597378686 -0.0059 -0.0683253880879 -0.0184422846073 -0.00595 -0.0681048570191 -0.0207125270677 -0.006 -0.0681401179389 -0.0229771349524 -0.00605 -0.0679200807085 -0.0252449767342 -0.0061 -0.0679523361102 -0.0275277172715 -0.00615 -0.0677328664525 -0.029840642352 -0.0062 -0.067762271247 -0.0322035353552 -0.00625 -0.0675434218759 -0.0346416886105 -0.0063 -0.0675701098968 -0.0371867661237 -0.00635 -0.0673519193368 -0.0398772744974 -0.0064 -0.0673760092003 -0.0427577881413 -0.00645 -0.0671585064737 -0.0458755748162 -0.0065 -0.0671801056711 -0.0492720508268 -0.00655 -0.0669633135275 -0.052965610545 -0.0066 -0.0669825212915 -0.0569228011003 -0.00665 -0.0667664584492 -0.0610212064633 -0.0067 -0.0667833677925 -0.0650248675279 -0.00675 -0.0665680504873 -0.068615790602 -0.0068 -0.0665827496479 -0.0715102806702 -0.00685 -0.0663681926987 -0.0735958948838 -0.0069 -0.0663807661706 -0.0749597487563 -0.00695 -0.0661669837101 -0.075792394812 -0.007 -0.0661775129835 -0.0762810981783 -0.00705 -0.065964518947 -0.0765632636745 -0.0071 -0.0659730830307 -0.0767259690664 -0.00715 -0.0657608914667 -0.0768204775849 -0.0072 -0.065767567254 -0.0768759915196 -0.00725 -0.0655561925105 -0.0769089869429 -0.0073 -0.0655610550285 -0.076928792807 -0.00735 -0.0653505118442 -0.0769407457773 -0.0074 -0.0653536344149 -0.0769479431568 -0.00745 -0.0651439379405 -0.0769522088213 -0.0075 -0.0651453922729 -0.0769546359574 -0.00755 -0.0649365580367 -0.0769558879428 -0.0076 -0.0649364142678 -0.0769563759239 -0.00765 -0.0647284581086 -0.0769563558941 -0.0077 -0.064726784815 -0.0769559922008 -0.00775 -0.0645197227989 -0.0769553888835 -0.0078 -0.0645165869952 -0.0769546155715 -0.00785 -0.0643104353284 -0.076953716296 -0.0079 -0.0643059024576 -0.0769527222857 -0.00795 -0.0641006773963 -0.0769516525884 -0.008 -0.0640948113107 -0.0769505220511 -0.00805 -0.0638905290621 -0.0769493388037 -0.0081 -0.0638833919881 -0.0769481103634 -0.00815 -0.063680068599 -0.0769468398739 -0.0082 -0.0636717210852 -0.0769455314184 -0.00825 -0.0634693723172 -0.0769441857714 -0.0083 -0.0634598731672 -0.0769428053297 -0.00835 -0.0632585143625 -0.0769413897026 -0.0084 -0.063247920556 -0.0769399404141 -0.00845 -0.0630475664973 -0.0769384564829 -0.0085 -0.0630359331047 -0.0769369389516 -0.00855 -0.062836597873 -0.0769353865326 -0.0086 -0.0628239779671 -0.0769337999803 -0.00865 -0.0626256748016 -0.0769321778449 -0.0087 -0.0626121193696 -0.0769305206909 -0.00875 -0.0624148605314 -0.0769288269815 -0.0088 -0.0624004183885 -0.0769270971409 -0.00885 -0.0622042150298 -0.0769253295848 -0.0089 -0.0621889327356 -0.0769235246231 -0.00895 -0.0619937947735 -0.0769216806445 -0.009 -0.061977716553 -0.0769197978578 -0.00905 -0.0617836525498 -0.076917874635 -0.0091 -0.0617668202166 -0.0769159110901 -0.00915 -0.061573837266 -0.0769139055828 -0.0092 -0.0615562901497 -0.0769118581353 -0.00925 -0.0613643937685 -0.0769097670959 -0.0093 -0.0613461686468 -0.0769076323959 -0.00935 -0.0611553626719 -0.0769054523716 -0.0094 -0.0611364937049 -0.0769032268632 -0.00945 -0.0609467801959 -0.0769009541928 -0.0095 -0.0609272988646 -0.0768986341094 -0.00955 -0.0607386780115 -0.0768962649179 -0.0096 -0.0607186130597 -0.0768938462754 -0.00965 -0.0605310830948 -0.076891376467 -0.0097 -0.0605104604737 -0.0768888550571 -0.00975 -0.060324017588 -0.0768862803083 -0.0098 -0.0603028604024 -0.0768836516919 -0.00985 -0.0601174986649 -0.0768809674446 -0.0099 -0.0600958271219 -0.0768782269447 -0.00995 -0.0599115384012 -0.0768754284004 -0.01 -0.0598893697594 -0.0768725710967 -0.01005 -0.059706143648 -0.0768696532113 -0.0101 -0.0596834921669 -0.0768666739365 -0.01015 -0.0595013159057 -0.076863631417 -0.0102 -0.0594781927944 -0.0768605247535 -0.01025 -0.0592970511968 -0.0768573520564 -0.0103 -0.0592734645604 -0.076854112336 -0.01035 -0.0590933399353 -0.0768508036672 -0.0104 -0.0590692947186 -0.0768474249715 -0.01045 -0.0588901667902 -0.0768439742879 -0.0105 -0.058865664716 -0.0768404504515 -0.01055 -0.0586875105376 -0.076836851465 -0.0106 -0.0586625500366 -0.07683317608 -0.01065 -0.0584853438974 -0.076829422264 -0.0107 -0.05845992003 -0.0768255886881 -0.01075 -0.0582836333515 -0.0768216732854 -0.0108 -0.0582577377176 -0.0768176746501 -0.01085 -0.0580823389409 -0.0768135906826 -0.0109 -0.0580559595782 -0.0768094199046 -0.01095 -0.0578814140357 -0.0768051601856 -0.011 -0.0578545352986 -0.0768008099794 -0.01105 -0.0576808050665 -0.0767963671277 -0.0111 -0.0576534074841 -0.0767918300209 -0.01115 -0.0574804512112 -0.076787196476 -0.0112 -0.05745251132 -0.0767824648256 -0.01125 -0.0572802840343 -0.0767776328658 -0.0113 -0.0572517741857 -0.0767726988773 -0.01135 -0.0570802270699 -0.0767676606394 -0.0114 -0.057051115201 -0.076762516387 -0.01145 -0.056880195329 -0.0767572638869 -0.0115 -0.0568504446911 -0.0767519013341 -0.01155 -0.0566800947191 -0.0767464264881 -0.0116 -0.0566496635602 -0.0767408375105 -0.01165 -0.0564798213737 -0.076735132158 -0.0117 -0.0564486625685 -0.0767293085657 -0.01175 -0.0562792608653 -0.0767233644928 -0.0118 -0.0562473214762 -0.0767172980551 -0.01185 -0.0560782872781 -0.0767111070202 -0.0119 -0.0560455080369 -0.0767047894911 -0.01195 -0.0558767621181 -0.076698343249 -0.012 -0.0558430768223 -0.0766917663911 -0.01205 -0.0556745330439 -0.0766850567178 -0.0121 -0.0556398678447 -0.076678212327 -0.01215 -0.0554714323702 -0.0766712310438 -0.0122 -0.0554357049312 -0.0766641109737 -0.01225 -0.0552672753016 -0.0766568499728 -0.0123 -0.0552303938052 -0.0766494461608 -0.01235 -0.0550618578513 -0.0766418974297 -0.0124 -0.055023719829 -0.0766342019199 -0.01245 -0.0548549543899 -0.0766263575643 -0.0125 -0.0548154453354 -0.0766183625294 -0.01255 -0.054646314737 -0.0766102147944 -0.0126 -0.0546053064575 -0.0766019125587 -0.01265 -0.0544356607064 -0.0765934538525 -0.0127 -0.05439300936 -0.0765848369135 -0.01275 -0.0542226819896 -0.0765760598269 -0.0128 -0.0541782257395 -0.076567120873 -0.01285 -0.054007031235 -0.0765580181963 -0.0129 -0.0539605874366 -0.0765487501251 -0.01295 -0.0537883181421 -0.0765393148673 -0.013 -0.0537396799543 -0.0765297108033 -0.01305 -0.0535661023402 -0.0765199362071 -0.0131 -0.053515034626 -0.0765099895142 -0.01315 -0.0533398847635 -0.0764998690673 -0.0132 -0.0532861191027 -0.0764895733615 -0.01325 -0.0531090971468 -0.0764791008108 -0.0133 -0.0530523257388 -0.0764684499717 -0.01335 -0.0528730891669 -0.0764576193307 -0.0134 -0.0528129573362 -0.0764466075073 -0.01345 -0.0526311126052 -0.0764354130625 -0.0135 -0.0525672095116 -0.076424034681 -0.01355 -0.052382301701 -0.0764124709981 -0.0136 -0.0523141487849 -0.0764007207635 -0.01365 -0.0521256486434 -0.0763887826865 -0.0137 -0.0520526850939 -0.076376655583 -0.01375 -0.0518599727181 -0.076364338236 -0.0138 -0.0517815371024 -0.0763518295258 -0.01385 -0.051583881192 -0.0763391283066 -0.0139 -0.0514991879997 -0.0763262335224 -0.01395 -0.0512957192687 -0.0763131440972 -0.014 -0.0512038286988 -0.076299859036 -0.01405 -0.0509935054525 -0.0762863773282 -0.0141 -0.0508932841156 -0.0762726980364 -0.01415 -0.0506748472412 -0.0762588202129 -0.0142 -0.0505649164624 -0.0762447429737 -0.01425 -0.0503368298931 -0.0762304654271 -0.0143 -0.0502154969461 -0.0762159867374 -0.01435 -0.0499758679776 -0.0762013060644 -0.0144 -0.0498410334528 -0.0761864226133 -0.01445 -0.0495875046641 -0.0761713355865 -0.0145 -0.0494365359301 -0.0761560442235 -0.01455 -0.0491661365088 -0.0761405477613 -0.0146 -0.04899569235 -0.0761248454628 -0.01465 -0.0487046303964 -0.0761089365884 -0.0147 -0.0485104139866 -0.076092820415 -0.01475 -0.0481937814428 -0.0760764962134 -0.0148 -0.0479701862817 -0.0760599632597 -0.01485 -0.0476215320785 -0.0760432208217 -0.0149 -0.0473611248516 -0.0760262681593 -0.01495 -0.0469718251807 -0.0760091045178 -0.015 -0.0466645748743 -0.0759917291227 -0.01505 -0.0462228844053 -0.0759741411771 -0.0151 -0.0458549880374 -0.0759563398476 -0.01515 -0.0453445782779 -0.07593832427 -0.0152 -0.0448966310813 -0.075920093526 -0.01525 -0.0442942865221 -0.075901646652 -0.0153 -0.0437383648876 -0.0758829826111 -0.01535 -0.0430102698865 -0.0758641003046 -0.0154 -0.0423051822122 -0.0758449985342 -0.01545 -0.0414008228586 -0.0758256760197 -0.0155 -0.0404842596218 -0.0758061313513 -0.01555 -0.0393263159368 -0.075786363008 -0.0156 -0.0381018765636 -0.0757663693039 -0.01565 -0.036569718653 -0.0757461484039 -0.0157 -0.0348862950217 -0.0757256982614 -0.01575 -0.032791106951 -0.0757050166333 -0.0158 -0.0304148135637 -0.0756841010026 -0.01585 -0.0274721872751 -0.075662948592 -0.0159 -0.0240692284809 -0.0756415562708 -0.01595 -0.0199126482646 -0.0756199205574 -0.016 -0.0151314604854 -0.0755980375101 -0.01605 -0.00952443058137 -0.0755759027103 -0.0161 -0.00341386409508 -0.0755535111289 -0.01615 0.00308615255853 -0.0755308570813 -0.0162 0.00928215740455 -0.0755079340522 -0.01625 0.0147924060618 -0.0754847346079 -0.0163 0.0189525916842 -0.0754612501537 -0.01635 0.0217417528642 -0.0754374707708 -0.0164 0.0230190976793 -0.0754133848634 -0.01645 0.0231999004172 -0.0753889788589 -0.0165 0.0223685339488 -0.0753642366643 -0.01655 0.020970820326 -0.0753391391134 -0.0166 0.0190196006653 -0.075313663078 -0.01665 0.0168564625658 -0.0752877804486 -0.0167 0.0144010824961 -0.0752614566131 -0.01675 0.0119198527682 -0.0752346485905 -0.0168 0.00927976681523 -0.0752073023861 -0.01685 0.00670765225375 -0.0751793496576 -0.0169 0.00404466916042 -0.0751507031817 -0.01695 0.00149710181316 -0.0751212511348 -0.017 -0.00110657796119 -0.0750908495873 -0.01705 -0.0035715081144 -0.0750593131335 -0.0171 -0.006075531256 -0.0750264029352 -0.01715 -0.00843064404989 -0.0749918119664 -0.0172 -0.0108177174422 -0.0749551465424 -0.01725 -0.0130531862104 -0.0749159036816 -0.0173 -0.0153192023212 -0.074873443069 -0.01735 -0.017435369033 -0.0748269527661 -0.0174 -0.0195842645126 -0.0747754069341 -0.01745 -0.0215881012428 -0.0747175140909 -0.0175 -0.023629594926 -0.0746516533908 -0.01755 -0.0255334485035 -0.0745757965002 -0.0176 -0.0274825443629 -0.07448741139 -0.01765 -0.029304151597 -0.074383344177 -0.0177 -0.0311814174379 -0.0742596735635 -0.01775 -0.0329441993914 -0.0741115318204 -0.0178 -0.034775833643 -0.0739328841483 -0.01785 -0.0365084973725 -0.0737162569917 -0.0179 -0.0383252238594 -0.0734524029337 -0.01795 -0.0400596812811 -0.0731298874609 -0.018 -0.0418933684152 -0.0727345785318 -0.01805 -0.0436596514474 -0.0722490156314 -0.0181 -0.0455360325309 -0.0716516279458 -0.01815 -0.0473522861713 -0.070915762998 -0.0182 -0.0492777975347 -0.0700084735192 -0.01825 -0.0511339236083 -0.0688889906557 -0.0183 -0.0530769585272 -0.0675067766234 -0.01835 -0.0549157106318 -0.0657989872352 -0.0184 -0.0567917143734 -0.0636870489514 -0.01845 -0.0585038253883 -0.0610717933165 -0.0185 -0.0601871411557 -0.0578260174649 -0.01855 -0.0616444958053 -0.0537820560709 -0.0186 -0.0630217973541 -0.0487090939611 -0.01865 -0.0641419782334 -0.0422690787462 -0.0187 -0.0651720517615 -0.0339315912752 -0.01875 -0.0659566296934 -0.0228386090574 -0.0188 -0.0666772314424 -0.00777905747478 -0.01885 -0.0671885465205 0.0117739479452 -0.0189 -0.0676741217799 0.0319127292868 -0.01895 -0.067988387603 0.0438696165674 -0.019 -0.0683100819595 0.0465538656178 -0.01905 -0.0684898515372 0.0464319676521 -0.0191 -0.0687005821071 0.045908442843 -0.01915 -0.0687895498785 0.0451601014871 -0.0192 -0.0689249209701 0.044206490896 -0.01925 -0.0689519177194 0.0430567126776 -0.0193 -0.0690352618329 0.0417141359729 -0.01935 -0.0690192069769 0.040182772823 -0.0194 -0.0690659375521 0.038470865124 -0.01945 -0.0690194449409 0.0366131335136 -0.0195 -0.0690399476582 0.0346231151434 -0.01955 -0.0689716052906 0.0325168956116 -0.0196 -0.068973023362 0.0303118374349 -0.01965 -0.0688887909566 0.0280234202881 -0.0197 -0.0688761232412 0.0256679965115 -0.01975 -0.0687802003423 0.0232595691766 -0.0198 -0.0687569926953 0.0208120680354 -0.01985 -0.068652373568 0.0183371721779 -0.0199 -0.0686211676599 0.0158459015608 -0.01995 -0.0685100069526 0.0133472861944 -0.02 -0.0684726401613 0.0108494486451 -0.02005 -0.0683565003028 0.00835883654928 -0.0201 -0.0683143108362 0.00588095891011 -0.02015 -0.068194332829 0.0034199659733 -0.0202 -0.0681483024526 0.000979150640468 -0.02025 -0.0680253255053 -0.00143927119675 -0.0203 -0.0679761800652 -0.00383382614548 -0.02035 -0.0678508262331 -0.0062039023957 -0.0204 -0.0677991070501 -0.0085495488449 -0.02045 -0.067671841541 -0.0108715702538 -0.0205 -0.0676179564153 -0.0131714580225 -0.02055 -0.0674891307797 -0.0154515332149 -0.0206 -0.0674333905994 -0.0177150374537 -0.02065 -0.0673032737782 -0.0199664017844 -0.0207 -0.0672459188805 -0.0222115498831 -0.02075 -0.0671147196041 -0.0244583740277 -0.0208 -0.0670559388156 -0.0267173107863 -0.02085 -0.066923821803 -0.0290020885409 -0.0209 -0.0668637662337 -0.0313306015441 -0.02095 -0.0667308639378 -0.0337259028916 -0.021 -0.0666696569891 -0.0362171975653 -0.02105 -0.066536078132 -0.0388405798575 -0.0211 -0.066473822783 -0.0416389483603 -0.02115 -0.0663396585755 -0.0446599302751 -0.0212 -0.0662764426893 -0.0479497215303 -0.02125 -0.0661417713585 -0.0515395011039 -0.0213 -0.0660776715566 -0.0554206595609 -0.02135 -0.0659425616611 -0.0595084413324 -0.0214 -0.0658776461555 -0.0636069660636 -0.02145 -0.0657421590041 -0.0674131524028 -0.0215 -0.0656764896633 -0.0706049297219 -0.02155 -0.0655406810775 -0.0729909132952 -0.0216 -0.0654743149349 -0.0745935020897 -0.02165 -0.0653382365369 -0.0755855733137 -0.0217 -0.06527122689 -0.0761692994743 -0.02175 -0.0651349270392 -0.076504419978 -0.0218 -0.0650673242439 -0.0766955971021 -0.02185 -0.0649308487075 -0.0768051577849 -0.0219 -0.0648627007448 -0.076868582071 -0.02195 -0.0647260931742 -0.0769057296636 -0.022 -0.0646574460497 -0.076927717622 -0.02205 -0.0645207483104 -0.0769408169165 -0.0221 -0.0644516463255 -0.0769486168081 -0.02215 -0.0643148987157 -0.0769531979302 -0.0222 -0.064245384641 -0.0769557910812 -0.02225 -0.0641086260252 -0.0769571308885 -0.0223 -0.0640387412005 -0.0769576679044 -0.02235 -0.0639020090816 -0.0769576775529 -0.0224 -0.0638317934693 -0.0769573356536 -0.02245 -0.0636951240269 -0.0769567510095 -0.0225 -0.0636246162392 -0.0769559966226 -0.02255 -0.0634880443485 -0.0769551172195 -0.0226 -0.0634172816601 -0.0769541450376 -0.02265 -0.0632808408965 -0.076953098813 -0.0227 -0.0632098592425 -0.0769519937118 -0.02275 -0.0630735818706 -0.0769508374125 -0.0228 -0.0630024158275 -0.076949637543 -0.02285 -0.0628663327725 -0.0769483968797 -0.0229 -0.0627950155198 -0.0769471195391 -0.02295 -0.0626591563189 -0.0769458060508 -0.023 -0.0625877195832 -0.0769444587986 -0.02305 -0.0624521123229 -0.0769430772589 -0.0231 -0.0623805863106 -0.0769416629016 -0.02315 -0.0622452575549 -0.0769402147055 -0.0232 -0.0621736708784 -0.0769387336187 -0.02325 -0.0620386455925 -0.0769372183885 -0.0233 -0.0619670251924 -0.0769356696355 -0.02335 -0.0618323266647 -0.0769340860052 -0.0234 -0.061760697734 -0.0769324678911 -0.02345 -0.0616263475009 -0.0769308139002 -0.0235 -0.0615547334109 -0.076929124252 -0.02355 -0.0614207511833 -0.0769273975454 -0.0236 -0.0613491734124 -0.0769256338554 -0.02365 -0.0612155770055 -0.0769238317854 -0.0237 -0.0611440550708 -0.0769219912832 -0.02375 -0.0610108603373 -0.0769201109606 -0.0238 -0.0609394117309 -0.0769181906481 -0.02385 -0.0608066324981 -0.0769162289653 -0.0239 -0.0607352726255 -0.0769142256318 -0.02395 -0.0606029206361 -0.0769121792712 -0.024 -0.0605316627593 -0.0769100894967 -0.02405 -0.0603997476149 -0.0769079549314 -0.0241 -0.0603286027982 -0.0769057750844 -0.02415 -0.0601971319055 -0.0769035485733 -0.0242 -0.0601261089625 -0.0769012748055 -0.02425 -0.059995087481 -0.0768989523873 -0.0243 -0.0599241929234 -0.0768965806261 -0.02435 -0.0597936237146 -0.0768941581117 -0.0244 -0.0597228617026 -0.0768916840528 -0.02445 -0.0595927452799 -0.076889157018 -0.0245 -0.0595221175726 -0.0768865761188 -0.02455 -0.0593924520522 -0.0768839398976 -0.0246 -0.0593219579587 -0.0768812473703 -0.02465 -0.0591927390082 -0.0768784970489 -0.0247 -0.0591223753353 -0.0768756878552 -0.02475 -0.0589935961203 -0.0768728182671 -0.0248 -0.0589233571172 -0.0768698871142 -0.02485 -0.0587950082437 -0.0768668928373 -0.0249 -0.0587248855442 -0.0768638341758 -0.02495 -0.0585969549989 -0.0768607095309 -0.025 -0.0585269375582 -0.076857517554 -0.02505 -0.0583994106395 -0.0768542566052 -0.0251 -0.0583294846613 -0.0768509252506 -0.02515 -0.0582023439025 -0.0768475218078 -0.0252 -0.0581324927573 -0.0768440447606 -0.02525 -0.0580057178401 -0.0768404923838 -0.0253 -0.0579359219754 -0.0768368630822 -0.02535 -0.057809489632 -0.0768331550883 -0.0254 -0.0577397264643 -0.0768293667319 -0.02545 -0.0576136103594 -0.0768254962037 -0.0255 -0.0575438541491 -0.076821541763 -0.02555 -0.0574180247495 -0.0768175015602 -0.0256 -0.0573482464614 -0.0768133737883 -0.02565 -0.0572226708804 -0.0768091565598 -0.0257 -0.0571528380142 -0.0768048480064 -0.02575 -0.0570274798289 -0.0768004462052 -0.0258 -0.0569575562232 -0.0767959492322 -0.02585 -0.0568323752657 -0.0767913551321 -0.0259 -0.0567623208741 -0.0767866619309 -0.02595 -0.0566372729851 -0.0767818676446 -0.026 -0.0565670436055 -0.0767769702553 -0.02605 -0.0564420803428 -0.0767719677551 -0.0261 -0.0563716273084 -0.0767668580882 -0.02615 -0.056246695615 -0.0767616392273 -0.0262 -0.0561759654325 -0.0767563090852 -0.02625 -0.0560510072394 -0.07675086562 -0.0263 -0.0559799411584 -0.0767453067198 -0.02635 -0.0558548929245 -0.0767396303332 -0.0264 -0.0557834264446 -0.0767338343305 -0.02645 -0.0556582186202 -0.0767279166559 -0.0265 -0.0555862809063 -0.076721875169 -0.02655 -0.0554608372981 -0.0767157078159 -0.0266 -0.0553883504941 -0.0767094124523 -0.02665 -0.0552625875263 -0.0767029870318 -0.0267 -0.055189465958 -0.0766964294129 -0.02675 -0.0550632918043 -0.0766897375625 -0.0268 -0.0549894410334 -0.0766829093484 -0.02685 -0.0548627545899 -0.0766759427565 -0.0269 -0.0547880703007 -0.0766688356706 -0.02695 -0.0546607599801 -0.0766615861014 -0.027 -0.0545851266721 -0.0766541919559 -0.02705 -0.0544570689778 -0.0766466512752 -0.0271 -0.0543803584109 -0.0766389619951 -0.02715 -0.0542514162432 -0.0766311221923 -0.0272 -0.0541734855909 -0.0766231298374 -0.02725 -0.0540435062321 -0.0766149830473 -0.0273 -0.0539641958823 -0.0766066798334 -0.02735 -0.0538330085946 -0.0765982183586 -0.0274 -0.0537521395217 -0.0765895966803 -0.02745 -0.0536195526667 -0.0765808130111 -0.0275 -0.0535369232717 -0.0765718654591 -0.02755 -0.05340272084 -0.0765627522904 -0.0276 -0.0533181031367 -0.0765534716679 -0.02765 -0.0531820405528 -0.0765440219163 -0.0277 -0.053095175544 -0.0765344012574 -0.02775 -0.0529569745628 -0.0765246080766 -0.0278 -0.0528675666032 -0.0765146406576 -0.02785 -0.0527269090734 -0.0765044974489 -0.0279 -0.0526346189586 -0.0764941767994 -0.02795 -0.0524911391481 -0.0764836772237 -0.028 -0.0523955755847 -0.0764729971377 -0.02805 -0.0522488506907 -0.076462135123 -0.0281 -0.0521495597058 -0.0764510896634 -0.02815 -0.0519990980139 -0.0764398594084 -0.0282 -0.0518955497044 -0.076428442912 -0.02825 -0.0517407757307 -0.0764168388918 -0.0283 -0.0516323475623 -0.0764050459709 -0.02835 -0.0514725832401 -0.0763930629339 -0.0284 -0.051358538813 -0.0763808884728 -0.02845 -0.0511929794774 -0.0763685214392 -0.0285 -0.0510724413041 -0.0763559605922 -0.02855 -0.0509001247594 -0.0763432048467 -0.0286 -0.0507720390222 -0.0763302530265 -0.02865 -0.0505918052772 -0.0763171041083 -0.0287 -0.0504548957087 -0.0763037569773 -0.02875 -0.0502653340253 -0.0762902106666 -0.0288 -0.0501180409242 -0.0762764641181 -0.02885 -0.0499174193514 -0.0762625164177 -0.0289 -0.0497578179194 -0.0762483665585 -0.02895 -0.0495439883567 -0.0762340136713 -0.029 -0.0493696779386 -0.0762194567935 -0.02905 -0.0491399464565 -0.0762046950946 -0.0291 -0.0489478981626 -0.0761897276479 -0.02915 -0.0486988452585 -0.0761745536508 -0.0292 -0.0484851890816 -0.0761591722027 -0.02925 -0.0482124165362 -0.0761435825193 -0.0293 -0.0479721389998 -0.0761277837131 -0.02935 -0.0476699070949 -0.0761117750037 -0.0294 -0.0473964139762 -0.0760955555039 -0.02945 -0.0470571118738 -0.0760791244215 -0.0295 -0.046741583478 -0.0760624808507 -0.02955 -0.0463549403012 -0.0760456239693 -0.0296 -0.0459853609352 -0.0760285528334 -0.02965 -0.0455372453569 -0.0760112665663 -0.0297 -0.0450969103341 -0.0759937641607 -0.02975 -0.0445674633275 -0.0759760446599 -0.0298 -0.044032630813 -0.075958106961 -0.02985 -0.0433932969781 -0.0759399499927 -0.0299 -0.0427294161761 -0.0759215725217 -0.02995 -0.0419381308355 -0.0759029733189 -0.03 -0.0410936803368 -0.075884150973 -0.03005 -0.0400869678597 -0.0758651040474 -0.0301 -0.038983331128 -0.0758458308931 -0.03015 -0.0376633945912 -0.0758263297998 -0.0302 -0.0361785805586 -0.0758065988076 -0.03025 -0.0343932181799 -0.0757866358466 -0.0303 -0.0323380813121 -0.0757664385502 -0.03035 -0.0298546975966 -0.0757460043788 -0.0304 -0.0269492500645 -0.0757253304306 -0.03045 -0.0234439695111 -0.0757044135502 -0.0305 -0.019340565507 -0.0756832501281 -0.03055 -0.0144936832438 -0.0756618361916 -0.0306 -0.00900340004497 -0.075640167188 -0.03065 -0.00292355682868 -0.0756182380447 -0.0307 0.00334076037271 -0.0755960429297 -0.03075 0.00939035322735 -0.0755735752641 -0.0308 0.0145936742637 -0.0755508274421 -0.03085 0.0186057297164 -0.0755277907729 -0.0309 0.0211510511226 -0.0755044551231 -0.03095 0.0223731346668 -0.0754808087468 -0.031 0.0224000918328 -0.0754568377865 -0.03105 0.0215812088551 -0.0754325259081 -0.0311 0.0200754648479 -0.0754078535445 -0.03115 0.0181649993342 -0.0753827971762 -0.0312 0.0159128716651 -0.0753573281021 -0.03125 0.0135110236418 -0.0753314110753 -0.0313 0.0109515855981 -0.0753050022206 -0.03135 0.00837342616351 -0.0752780465315 -0.0314 0.00573129637533 -0.0752504743164 -0.03145 0.00313679588763 -0.0752221967965 -0.0315 0.000525832275584 -0.0751931001705 -0.03155 -0.00200427726536 -0.0751630382436 -0.0316 -0.0045274011897 -0.0751318228599 -0.03165 -0.00695410898185 -0.0750992121081 -0.0317 -0.0093634768276 -0.0750648954165 -0.03175 -0.0116706515571 -0.0750284753022 -0.0318 -0.0139575114314 -0.074989444677 -0.03185 -0.016142036232 -0.0749471591423 -0.0319 -0.0183076744629 -0.074900802802 -0.03195 -0.0203744034461 -0.0748493465177 -0.032 -0.0224267263166 -0.0747914965353 -0.03205 -0.0243863443556 -0.074725631637 -0.0321 -0.026338723891 -0.0746497258382 -0.03215 -0.0282073079116 -0.0745612536254 -0.0322 -0.0300785940579 -0.0744570733729 -0.03225 -0.0318778154108 -0.0743332841924 -0.0323 -0.0336924755918 -0.0741850497414 -0.03235 -0.0354494347227 -0.0740063815985 -0.0324 -0.0372368481508 -0.0737898724717 -0.03245 -0.0389825860066 -0.073526367761 -0.0325 -0.0407744992733 -0.0732045606337 -0.03255 -0.0425400643833 -0.0728104926462 -0.0326 -0.0443648569332 -0.0723269367695 -0.03265 -0.046173286614 -0.0717326339289 -0.0327 -0.0480451914872 -0.0710013451472 -0.03275 -0.0498976804468 -0.0701006693536 -0.0328 -0.0518001197865 -0.0689905570575 -0.03285 -0.0536577343796 -0.0676214176077 -0.0329 -0.0555261593608 -0.0659316570706 -0.03295 -0.0572984094819 -0.0638443652916 -0.033 -0.059020687831 -0.0612626221444 -0.03305 -0.0605836595246 -0.0580623525235 -0.0331 -0.0620387824111 -0.0540804518011 -0.03315 -0.0632909381931 -0.0490932185836 -0.0332 -0.0644108560877 -0.0427745723203 -0.03325 -0.0653249922313 -0.0346151292303 -0.0333 -0.0661223223507 -0.0237903586125 -0.03335 -0.0667428198416 -0.00911131003347 -0.0334 -0.0672820946301 0.0100894869334 -0.03345 -0.0676821316789 0.0304238213135 -0.0335 -0.0680362143645 0.0432283523524 -0.03355 -0.0682827128479 0.0464296891564 -0.0336 -0.0685099215072 0.046386038802 -0.03365 -0.0686520047133 0.0458812642007 -0.0337 -0.0687928715434 0.0451420439877 -0.03375 -0.0688636085564 0.044196647625 -0.0338 -0.0689449934793 0.0430519881689 -0.03385 -0.0689661983835 0.0417142199579 -0.0339 -0.0690058683771 0.0401862812231 -0.03395 -0.0689920731218 0.0384774514149 -0.034 -0.0690019757746 0.0366219079906 -0.03405 -0.0689630523008 0.0346337336237 -0.0341 -0.0689513865352 0.0325288089154 -0.03415 -0.0688941735663 0.0303247489264 -0.0342 -0.0688666684355 0.0280369727287 -0.03425 -0.0687959809604 0.025681966874 -0.0343 -0.0687566975824 0.023273728271 -0.03435 -0.0686759686219 0.0208262613978 -0.0344 -0.0686278177178 0.0183512582082 -0.03445 -0.0685395188039 0.0158597809566 -0.0345 -0.0684846047162 0.0133608770715 -0.03455 -0.0683905291483 0.0108626928511 -0.0346 -0.0683303843738 0.00837169218607 -0.03465 -0.0682318423403 0.00589339687029 -0.0347 -0.0681675905247 0.00343197041502 -0.03475 -0.0680655457287 0.000990711881579 -0.0348 -0.067998016513 -0.00142815293405 -0.03485 -0.0678931829322 -0.00382314842738 -0.0349 -0.0678229936301 -0.00619365585377 -0.03495 -0.0677159045727 -0.00853972444229 -0.035 -0.0676435186322 -0.0108621544588 -0.03505 -0.0675345762825 -0.0131624391039 -0.0351 -0.0674603453203 -0.0154428971585 -0.03515 -0.0673498564308 -0.0177067731956 -0.0352 -0.0672740505566 -0.0199584978573 -0.03525 -0.0671622522379 -0.0222039991379 -0.0353 -0.0670850820022 -0.024451171145 -0.03535 -0.0669721604 -0.0267104566707 -0.0354 -0.0668937927046 -0.0289955891282 -0.03545 -0.0667798965718 -0.0313244722026 -0.0355 -0.0667004662427 -0.0337201679741 -0.03555 -0.0665857168041 -0.0362118937918 -0.0356 -0.0665053350141 -0.0388357549805 -0.03565 -0.0663898331673 -0.0416346611174 -0.0357 -0.0663085935895 -0.0446562433639 -0.03575 -0.0661924251602 -0.0479466925614 -0.0358 -0.0661104084582 -0.0515371654562 -0.03585 -0.0659936480401 -0.0554190109747 -0.0359 -0.0659109251563 -0.0595074120607 -0.03595 -0.0657936389279 -0.0636064210142 -0.036 -0.0657102734916 -0.0674129086898 -0.03605 -0.065592521273 -0.0706048096243 -0.0361 -0.0655085713575 -0.0729908013362 -0.03615 -0.0653904081117 -0.0745933614774 -0.0362 -0.0653059275196 -0.0755854143948 -0.03625 -0.0651874044503 -0.0761691433208 -0.0363 -0.0651024436486 -0.0765042808778 -0.03635 -0.0649836089959 -0.0766954806607 -0.0364 -0.0648982157893 -0.0768050636976 -0.03645 -0.0647791153973 -0.0768685074052 -0.0365 -0.0646933354064 -0.0769056706459 -0.03655 -0.0645740131244 -0.0769276707366 -0.0366 -0.064487890118 -0.0769407791491 -0.03665 -0.0643683880719 -0.0769485858057 -0.0367 -0.0642819641876 -0.0769531718554 -0.03675 -0.0641623229554 -0.0769557685772 -0.0368 -0.064075638836 -0.0769571109244 -0.03685 -0.0639558975505 -0.076957649731 -0.0369 -0.0638689924184 -0.0769576606031 -0.03695 -0.063749188822 -0.0769573195124 -0.037 -0.0636621005201 -0.0769567353615 -0.03705 -0.0635422709935 -0.0769559812303 -0.0371 -0.0634550360056 -0.0769551019019 -0.03715 -0.063335215583 -0.0769541296502 -0.0372 -0.063247869042 -0.0769530832465 -0.03725 -0.0631280914107 -0.0769519778701 -0.0373 -0.0630406670899 -0.0769508212243 -0.03735 -0.0629209645729 -0.0769496209372 -0.0374 -0.0628334948601 -0.0769483798051 -0.03745 -0.0627138983806 -0.0769471019364 -0.0375 -0.0626264142325 -0.0769457878788 -0.03755 -0.0625069532596 -0.076944440003 -0.0376 -0.0624194841416 -0.0769430578025 -0.03765 -0.062300186625 -0.0769416427308 -0.0377 -0.0622127604411 -0.0769401937836 -0.03775 -0.0620936527384 -0.0769387118904 -0.0378 -0.0620062957573 -0.0769371958149 -0.03785 -0.0618874025587 -0.0769356461581 -0.0379 -0.061800139338 -0.0769340615815 -0.03795 -0.0616814835911 -0.0769324424578 -0.038 -0.0615943369036 -0.0769307874099 -0.03805 -0.0614759397416 -0.0769290966358 -0.0381 -0.0613889305044 -0.0769273687498 -0.03815 -0.0612708111762 -0.076925603805 -0.0382 -0.0611839583828 -0.0769238004198 -0.03825 -0.0610661341857 -0.0769219585197 -0.0383 -0.060979454841 -0.0769200767309 -0.03835 -0.0608619410589 -0.0769181548615 -0.0384 -0.060775450118 -0.0769161915448 -0.03845 -0.0606582599613 -0.0769141864778 -0.0385 -0.0605719702719 -0.0769121382976 -0.03855 -0.0604551148213 -0.0769100465942 -0.0386 -0.0603690370693 -0.0769079100036 -0.03865 -0.0602525252234 -0.076905728012 -0.0387 -0.0601666678807 -0.076903499249 -0.03875 -0.0600505063036 -0.0769012230991 -0.0388 -0.0599648755774 -0.0768988981801 -0.03885 -0.059849068649 -0.0768965237763 -0.0389 -0.0597636684319 -0.0768940984884 -0.03895 -0.0596482181985 -0.0768916215023 -0.039 -0.0595630500199 -0.0768890913966 -0.03905 -0.059447956146 -0.0768865072602 -0.0391 -0.0593630191238 -0.076883867645 -0.03915 -0.0592482788424 -0.0768811715442 -0.0392 -0.0591635696328 -0.0768784174787 -0.03925 -0.0590491776943 -0.0768756043481 -0.0393 -0.0589646904378 -0.0768727306386 -0.03935 -0.0588506390545 -0.0768697951575 -0.0394 -0.0587663653196 -0.0768667963536 -0.03945 -0.0586526441074 -0.0768637329443 -0.0395 -0.0585685728306 -0.0768606033383 -0.03955 -0.0584551687447 -0.0768574061653 -0.0396 -0.058371286161 -0.0768541397924 -0.03965 -0.0582581834227 -0.0768508027645 -0.0397 -0.0581744729874 -0.0768473934057 -0.03975 -0.0580616530014 -0.0768439101792 -0.0398 -0.0579780953042 -0.0768403513658 -0.03985 -0.0578655365662 -0.0768367153501 -0.0399 -0.0577821092304 -0.0768330003706 -0.03995 -0.0576697872172 -0.0768292047372 -0.04 -0.0575864647803 -0.0768253266465 -0.04005 -0.0574743518238 -0.0768213643383 -0.0401 -0.0573911056048 -0.0768173159688 -0.04015 -0.0572791707476 -0.0768131797123 -0.0402 -0.0571959686888 -0.0768089536867 -0.04025 -0.0570841775107 -0.0768046360059 -0.0403 -0.0570009839903 -0.0768002247521 -0.04035 -0.0568892984113 -0.0767957179843 -0.0404 -0.0568060740327 -0.0767911137524 -0.04045 -0.0566944520807 -0.0767864100659 -0.0405 -0.0566111534178 -0.0767816049462 -0.04055 -0.0564995489533 -0.0767766963596 -0.0406 -0.0564161282569 -0.0767716823038 -0.04065 -0.0563044906596 -0.0767665607079 -0.0407 -0.0562208955166 -0.0767613295502 -0.04075 -0.0561091693117 -0.0767559867294 -0.0408 -0.0560253422387 -0.0767505302093 -0.04085 -0.0559134666607 -0.0767449578648 -0.0409 -0.055829344638 -0.0767392676504 -0.04095 -0.0557172531264 -0.0767334574238 -0.041 -0.0556327670472 -0.0767275251355 -0.04105 -0.0555203866473 -0.0767214686334 -0.0411 -0.0554354606703 -0.0767152858702 -0.04115 -0.0553227113366 -0.0767089746907 -0.0412 -0.0552372621343 -0.0767025330553 -0.04125 -0.0551240559135 -0.0766959588124 -0.0413 -0.0550379917822 -0.0766892499362 -0.04135 -0.0549242318456 -0.0766824042853 -0.0414 -0.0548374516574 -0.0766754198527 -0.04145 -0.0547230311687 -0.0766682945143 -0.0415 -0.0546354231432 -0.0766610262881 -0.04155 -0.0545202239186 -0.0766536130741 -0.0416 -0.0544316641627 -0.0766460529208 -0.04165 -0.054315555081 -0.076638343758 -0.0417 -0.0542259058567 -0.0766304836699 -0.04175 -0.0541087409722 -0.0766224706218 -0.0418 -0.0540178486388 -0.0766143027386 -0.04185 -0.0538994649347 -0.0766059780271 -0.0419 -0.0538071574914 -0.0765974946585 -0.04195 -0.0536873721879 -0.0765888506861 -0.042 -0.0535934563237 -0.0765800443312 -0.04205 -0.0534720636419 -0.0765710736985 -0.0421 -0.0533763211828 -0.0765619370628 -0.04215 -0.0532530884388 -0.0765526325845 -0.0422 -0.0531552720476 -0.0765431585968 -0.04225 -0.0530299349133 -0.0765335133198 -0.0423 -0.052929762858 -0.0765236951476 -0.04235 -0.0528020195797 -0.0765137023626 -0.0424 -0.0526991693335 -0.0765035334221 -0.04245 -0.0525686736341 -0.0764931866742 -0.0425 -0.052462773998 -0.0764826606422 -0.04255 -0.0523291263167 -0.0764719537418 -0.0426 -0.0522197476601 -0.0764610645631 -0.04265 -0.052082484268 -0.07644999159 -0.0427 -0.051969126357 -0.0764387334807 -0.04275 -0.0518277057159 -0.0764272887894 -0.0428 -0.0517097824066 -0.0764156562422 -0.04285 -0.0515635679655 -0.0764038344624 -0.0429 -0.0514403878248 -0.0763918222432 -0.04295 -0.0512886261324 -0.076379618277 -0.043 -0.0511593676618 -0.0763672214233 -0.04305 -0.0510011602624 -0.0763546304417 -0.0431 -0.0508648399402 -0.0763418442548 -0.04315 -0.0506991069417 -0.0763288616866 -0.0432 -0.0505545375882 -0.0763156817211 -0.04325 -0.0503799699546 -0.0763023032437 -0.0433 -0.050225705896 -0.0762887252939 -0.04335 -0.0500407022337 -0.0762749468134 -0.0434 -0.0498749662292 -0.0762609668939 -0.04345 -0.0496775480489 -0.0762467845279 -0.0435 -0.0494981326788 -0.0762323988511 -0.04355 -0.0492858292454 -0.0762178088995 -0.0436 -0.049089961987 -0.0762030138467 -0.04365 -0.0488596516439 -0.0761880127636 -0.0437 -0.0486438075278 -0.0761728048503 -0.04375 -0.0483914956024 -0.0761573892031 -0.0438 -0.0481511328222 -0.0761417650388 -0.04385 -0.0478716355132 -0.0761259314652 -0.0439 -0.0476008157536 -0.0761098877014 -0.04395 -0.0472873019903 -0.0760936328541 -0.044 -0.0469781348653 -0.0760771661282 -0.04405 -0.0466214491816 -0.0760604866097 -0.0441 -0.0462632626776 -0.0760435934713 -0.04415 -0.045850903477 -0.0760264857581 -0.0442 -0.0454289785894 -0.0760091625853 -0.04425 -0.04494352236 -0.0759916229315 -0.0443 -0.04443711989 -0.075973865828 -0.04435 -0.043853736872 -0.0759558901541 -0.0444 -0.0432329531129 -0.075937694822 -0.04445 -0.0425154085557 -0.0759192785752 -0.0445 -0.041736069229 -0.0759006401628 -0.04455 -0.0408301842512 -0.075881778144 -0.0446 -0.039825460663 -0.0758626910529 -0.04465 -0.038648381746 -0.0758433772032 -0.0447 -0.0373151415788 -0.075823834846 -0.04475 -0.0357382104271 -0.0758040619738 -0.0448 -0.0339160649755 -0.0757840564661 -0.04485 -0.0317404003277 -0.075763815895 -0.0449 -0.0291858699222 -0.0757433376541 -0.04495 -0.0261207661749 -0.0757226187622 -0.045 -0.022502524214 -0.0757016559756 -0.04505 -0.0182023041132 -0.0756804455801 -0.0451 -0.0132226049272 -0.0756589834852 -0.04515 -0.00755509206994 -0.0756372649978 -0.0452 -0.00142753060569 -0.0756152848852 -0.04525 0.00484469002488 -0.0755930371239 -0.0453 0.0107025425959 -0.0755705149127 -0.04535 0.0156611822893 -0.0755477103781 -0.0454 0.0192949643588 -0.0755246145115 -0.04545 0.0215252876176 -0.0755012167931 -0.0455 0.0224104293502 -0.0754775050084 -0.04555 0.0222303871172 -0.0754534647205 -0.0456 0.0212017319645 -0.0754290788766 -0.04565 0.0196043492129 -0.0754043270035 -0.0457 0.0175767125295 -0.0753791844325 -0.04575 0.0153020397511 -0.0753536209859 -0.0458 0.0128333700206 -0.07532759951 -0.04585 0.0102872173842 -0.0753010736462 -0.0459 0.00766809834814 -0.075273985149 -0.04595 0.00505753888264 -0.0752462600908 -0.046 0.00243542850004 -0.0752178041697 -0.04605 -0.000134660191505 -0.0751884963999 -0.0461 -0.00268555208611 -0.075158181296 -0.04615 -0.00516328997985 -0.0751266587545 -0.0462 -0.00760751624689 -0.0750936716035 -0.04625 -0.00996965894191 -0.0750588898978 -0.0463 -0.0122931115308 -0.075021891712 -0.04635 -0.01453245546 -0.0749821392775 -0.0464 -0.0167332275675 -0.0749389498686 -0.04645 -0.0188520342773 -0.0748914598837 -0.0465 -0.0209358071784 -0.0748385809952 -0.04655 -0.0229427266713 -0.0747789461824 -0.0466 -0.0249208976821 -0.0747108437114 -0.04665 -0.0268300143409 -0.0746321359217 -0.0467 -0.0287193914841 -0.0745401596681 -0.04675 -0.0305503027867 -0.0744316038283 -0.0468 -0.032373307164 -0.0743023588914 -0.04685 -0.0341511991346 -0.0741473318213 -0.0469 -0.0359355736607 -0.0739602184257 -0.04695 -0.0376903272046 -0.0737332229947 -0.047 -0.0394673935327 -0.0734567131297 -0.04705 -0.0412307071418 -0.0731187941386 -0.0471 -0.0430310023633 -0.0727047840459 -0.04715 -0.0448301095393 -0.0721965647668 -0.0472 -0.0466746950445 -0.0715717788071 -0.04725 -0.0485208175679 -0.0708028310576 -0.0473 -0.0504066835361 -0.0698556419648 -0.04735 -0.0522778158202 -0.0686880760362 -0.0474 -0.0541596091152 -0.0672479323377 -0.04745 -0.0559844034711 -0.0654703127395 -0.0475 -0.05776552663 -0.0632740430053 -0.04755 -0.0594278401903 -0.0605565233918 -0.0476 -0.0609838599534 -0.0571857314878 -0.04765 -0.0623664637395 -0.05298663539 -0.0477 -0.0636036581368 -0.0477160471322 -0.04775 -0.0646488986096 -0.0410135188862 -0.0478 -0.0655508819846 -0.0323079512618 -0.04785 -0.0662805494339 -0.0206808799365 -0.0479 -0.0668979678635 -0.00491530280719 -0.04795 -0.0673796981609 0.0151162612059 -0.048 -0.0677862049049 0.0344621561793 -0.04805 -0.0680915761364 0.0446451174901 -0.0481 -0.06835189664 0.0465092986535 -0.04815 -0.0685367464395 0.0462855571539 -0.0482 -0.0686976249768 0.0457155786276 -0.04825 -0.0688003890022 0.04492834249 -0.0483 -0.068893139227 0.0439320798118 -0.04835 -0.0689392469588 0.0427412886429 -0.0484 -0.0689845374055 0.0413559554984 -0.04845 -0.0689908421537 0.0397832428434 -0.0485 -0.0690024787864 0.0380355041044 -0.04855 -0.0689803473762 0.0361468645679 -0.0486 -0.0689677373987 0.0341281678366 -0.04865 -0.0689249923838 0.0319976948053 -0.0487 -0.0688946699707 0.02977147194 -0.04875 -0.0688367902158 0.0274658754948 -0.0488 -0.0687933658524 0.0250964149832 -0.04885 -0.068724242223 0.0226773500812 -0.0489 -0.0686710087613 0.0202219862466 -0.04895 -0.068593433906 0.0177419544121 -0.049 -0.0685327653085 0.0152477731178 -0.04905 -0.0684487605075 0.0127482963414 -0.0491 -0.0683823814162 0.0102512355744 -0.04915 -0.0682934201062 0.00776282668635 -0.0492 -0.0682225920419 0.00528824439789 -0.04925 -0.0681297555329 0.00283143569458 -0.0493 -0.0680554075435 0.000395425219274 -0.04935 -0.0679594949239 -0.00201774979437 -0.0494 -0.067882316244 -0.00440683264566 -0.04945 -0.0677839226437 -0.00677136915224 -0.0495 -0.0677044288966 -0.00911159641657 -0.04955 -0.0676040015571 -0.0114284779595 -0.0496 -0.0675225822954 -0.0137237035256 -0.04965 -0.0674204609126 -0.0159998000174 -0.0497 -0.0673374138828 -0.018260281312 -0.04975 -0.0672338597364 -0.0205099079882 -0.0498 -0.0671494156532 -0.0227550463202 -0.04985 -0.0670446326876 -0.0250041543251 -0.0499 -0.0669589731913 -0.0272684109494 -0.04995 -0.066853123319 -0.02956248589 -0.05 -0.0667663940165 -0.0319054566897 -0.05005 -0.0666596082411 -0.0343218083745 -0.0501 -0.066571928205 -0.0368424009398 -0.05015 -0.0664643147337 -0.0395050700757 -0.0502 -0.0663757834253 -0.0423541895464 -0.05025 -0.0662674335807 -0.0454378281644 -0.0503 -0.066178135909 -0.0488001112382 -0.05035 -0.0660691284608 -0.0524652071909 -0.0504 -0.0659791384857 -0.0564094447851 -0.05045 -0.0658695428146 -0.0605232947359 -0.0505 -0.0657789264524 -0.0645814792202 -0.05055 -0.0656688048648 -0.0682643819602 -0.0506 -0.0655776218703 -0.0712681179596 -0.05065 -0.0654670312955 -0.0734518030711 -0.0507 -0.0653753367129 -0.0748854006664 -0.05075 -0.0652643299406 -0.0757594297393 -0.0508 -0.0651721751559 -0.0762695367665 -0.05085 -0.0650608017325 -0.0765615528957 -0.0509 -0.0649682352372 -0.0767282126832 -0.05095 -0.0648565421129 -0.0768239382321 -0.051 -0.064763610051 -0.0768795173002 -0.05105 -0.0646516420407 -0.0769121663569 -0.0511 -0.0645583885944 -0.0769315339811 -0.05115 -0.0644461886962 -0.0769430827872 -0.0512 -0.0643526563438 -0.0769499474175 -0.05125 -0.0642402659455 -0.0769539557741 -0.0513 -0.0641464956254 -0.0769561901163 -0.05135 -0.0640339546318 -0.0769573023822 -0.0514 -0.0639399858378 -0.0769576906596 -0.05145 -0.063827332741 -0.0769576024287 -0.0515 -0.063733203574 -0.0769571930626 -0.05155 -0.0636204754913 -0.076956562074 -0.0516 -0.0635262226878 -0.0769557734034 -0.05165 -0.063413455382 -0.0769548691712 -0.0517 -0.0633191143273 -0.0769538768905 -0.05175 -0.0632063422131 -0.0769528151722 -0.0518 -0.0631119469389 -0.0769516962458 -0.05185 -0.0629992030715 -0.0769505285895 -0.0519 -0.062904786236 -0.0769493177081 -0.05195 -0.0627921022819 -0.0769480674977 -0.052 -0.0626976951315 -0.0769467803714 -0.05205 -0.0625851013212 -0.0769454580554 -0.0521 -0.062490733635 -0.0769441014804 -0.05215 -0.062378258702 -0.0769427112962 -0.0522 -0.0622839587261 -0.0769412876922 -0.05225 -0.0621716298367 -0.0769398307563 -0.0523 -0.0620774242113 -0.0769383402897 -0.05235 -0.061965266891 -0.0769368160692 -0.0524 -0.0618711805757 -0.0769352576801 -0.05245 -0.0617592186329 -0.0769336647144 -0.0525 -0.0616652748317 -0.0769320366273 -0.05255 -0.0615535302843 -0.0769303728905 -0.0526 -0.0614597503727 -0.0769286728725 -0.05265 -0.0613482433768 -0.0769269359586 -0.0527 -0.0612546468326 -0.0769251614519 -0.05275 -0.0611433956151 -0.0769233486687 -0.0528 -0.0610499999527 -0.076921496857 -0.05285 -0.0609390207476 -0.0769196052728 -0.0529 -0.0608458414564 -0.076917673113 -0.05295 -0.0607351484448 -0.0769156995779 -0.053 -0.0606421989306 -0.0769136838137 -0.05305 -0.0605318041837 -0.0769116249663 -0.0531 -0.0604390957125 -0.0769095221307 -0.05315 -0.0603290091361 -0.0769073743983 -0.0532 -0.0602365507809 -0.0769051808109 -0.05325 -0.0601267800636 -0.0769029404044 -0.0533 -0.0600345786528 -0.0769006521656 -0.05335 -0.0599251292157 -0.0768983150734 -0.0534 -0.0598331892841 -0.0768959280573 -0.05345 -0.0597240642322 -0.0768934900376 -0.0535 -0.0596323879725 -0.0768909998845 -0.05355 -0.0595235880461 -0.0768884564584 -0.0536 -0.0594321752599 -0.0768858585682 -0.05365 -0.0593236987848 -0.0768832050132 -0.0537 -0.0592325468324 -0.0768804945391 -0.05375 -0.0591243896692 -0.0768777258828 -0.0538 -0.0590334934179 -0.076874897726 -0.05385 -0.0589256489095 -0.0768720087424 -0.0539 -0.0588350006798 -0.0768690575488 -0.05395 -0.0587274595947 -0.076866042755 -0.054 -0.0586370491002 -0.076862962913 -0.05405 -0.0585297995692 -0.0768598165688 -0.0541 -0.0584396138496 -0.0768566022093 -0.05415 -0.0583326412963 -0.0768533183174 -0.0542 -0.0582426646459 -0.0768499633159 -0.05425 -0.0581359517098 -0.0768465356253 -0.0543 -0.0580461655936 -0.0768430336057 -0.05435 -0.0579396920395 -0.0768394556162 -0.0544 -0.0578500749956 -0.0768357999561 -0.05445 -0.0577438176102 -0.0768320649259 -0.0545 -0.0576543451411 -0.0768282487663 -0.05455 -0.0575482776165 -0.0768243497214 -0.0546 -0.0574589220613 -0.0768203659761 -0.05465 -0.0573530148541 -0.0768162957212 -0.0547 -0.0572637452364 -0.0768121370893 -0.05475 -0.0571579654071 -0.0768078882213 -0.0548 -0.0570687472645 -0.0768035472013 -0.05485 -0.0569630582918 -0.0767991121243 -0.0549 -0.0568738534711 -0.0767945810304 -0.05495 -0.0567682150281 -0.0767899519728 -0.055 -0.0566789814464 -0.0767852229522 -0.05505 -0.0565733491479 -0.0767803919852 -0.0551 -0.0564840405189 -0.0767754570385 -0.05515 -0.0563783656202 -0.0767704160973 -0.0552 -0.0562889311257 -0.0767652670997 -0.05525 -0.0561831601696 -0.076760008005 -0.0553 -0.0560935440833 -0.0767546367283 -0.05535 -0.0559876184946 -0.0767491512088 -0.0554 -0.0558977597391 -0.0767435493446 -0.05545 -0.0557916153416 -0.0767378290606 -0.0555 -0.0557014469658 -0.0767319882441 -0.05555 -0.0555950134211 -0.0767260248117 -0.0556 -0.055504461997 -0.0767199366462 -0.05565 -0.0553976621496 -0.0767137216629 -0.0557 -0.0553066470584 -0.0767073777466 -0.05575 -0.0551993961598 -0.0767009028172 -0.0558 -0.0551078287527 -0.0766942947675 -0.05585 -0.0550000335567 -0.0766875515284 -0.0559 -0.0549078161757 -0.076680671007 -0.05595 -0.0547993738722 -0.0766736511508 -0.056 -0.0547063986888 -0.0766664898878 -0.05605 -0.0545971956406 -0.076659185189 -0.0561 -0.0545033432829 -0.0766517350091 -0.05615 -0.0543932535362 -0.0766441373485 -0.0562 -0.0542983914696 -0.0766363901944 -0.05625 -0.0541872749868 -0.0766284915816 -0.0563 -0.0540912555844 -0.0766204395352 -0.05635 -0.053978956137 -0.0766122321299 -0.0564 -0.0538816143773 -0.0766038674347 -0.05645 -0.0537679570287 -0.0765953435696 -0.0565 -0.0536691077396 -0.0765866586517 -0.05655 -0.053553895824 -0.076577810851 -0.0566 -0.0534533303686 -0.0765687983371 -0.05665 -0.0533363418523 -0.0765596193333 -0.0567 -0.0532338241276 -0.0765502720664 -0.05675 -0.0531148072003 -0.076540754818 -0.0568 -0.053010068775 -0.0765310658752 -0.05685 -0.0528887364835 -0.0765212035805 -0.0569 -0.0527814706644 -0.0765111662839 -0.05695 -0.0526574943398 -0.0765009523913 -0.057 -0.0525473488839 -0.076490560319 -0.05705 -0.0524203500504 -0.0764799885392 -0.0571 -0.0523069181587 -0.0764692355354 -0.05715 -0.0521764584906 -0.0764582998472 -0.0572 -0.0520592676024 -0.0764471800263 -0.05725 -0.0519248363974 -0.0764358746808 -0.0573 -0.0518033341475 -0.0764243824321 -0.05735 -0.0516643325574 -0.0764127019569 -0.0574 -0.0515378690371 -0.0764008319449 -0.05745 -0.0513935900706 -0.0763887711403 -0.0575 -0.051261395238 -0.0763765183014 -0.05755 -0.0511109981754 -0.0763640722392 -0.0576 -0.05097215281 -0.0763514317778 -0.05765 -0.0508146301602 -0.0763385957916 -0.0577 -0.050668028172 -0.0763255631687 -0.05775 -0.0505021625674 -0.076312332845 -0.0578 -0.0503464615567 -0.076298903768 -0.05785 -0.0501707688837 -0.0762852749297 -0.0579 -0.0500043245521 -0.0762714453327 -0.05795 -0.0498169780648 -0.0762574140213 -0.058 -0.0496377561263 -0.0762431800466 -0.05805 -0.0494364838614 -0.0762287424971 -0.0581 -0.0492419401498 -0.0762141004661 -0.05815 -0.0490238843123 -0.0761992530793 -0.0582 -0.0488107992461 -0.0761841994623 -0.05825 -0.0485723205502 -0.0761689387678 -0.0583 -0.0483365669429 -0.0761534701439 -0.05835 -0.0480729679213 -0.0761377927594 -0.0584 -0.0478091797844 -0.0761219057711 -0.05845 -0.0475143065123 -0.0761058083496 -0.0585 -0.047215397841 -0.076089499647 -0.05855 -0.0468810556764 -0.0760729788185 -0.0586 -0.0465375074499 -0.0760562449922 -0.05865 -0.0461525863032 -0.0760392972894 -0.0587 -0.0457513675781 -0.0760221347928 -0.05875 -0.0453005039024 -0.0760047565643 -0.0588 -0.0448234032121 -0.0759871616155 -0.05885 -0.0442848876087 -0.0759693489211 -0.0589 -0.0437058749589 -0.0759513173877 -0.05895 -0.0430483091643 -0.0759330658676 -0.059 -0.0423292798787 -0.0759145931242 -0.05905 -0.0415061372505 -0.0758958978419 -0.0591 -0.0405899424423 -0.0758769785921 -0.05915 -0.0395306336025 -0.0758578338369 -0.0592 -0.0383296577388 -0.0758384618924 -0.05925 -0.0369250396025 -0.0758188609294 -0.0593 -0.035303108203 -0.0757990289292 -0.05935 -0.0333835680924 -0.0757789636798 -0.0594 -0.0311308780643 -0.0757586627263 -0.05945 -0.0284408550955 -0.0757381233541 -0.0595 -0.025255134997 -0.0757173425342 -0.05955 -0.0214560859987 -0.0756963168923 -0.0596 -0.0169962571651 -0.0756750426384 -0.05965 -0.0118192944366 -0.0756535155201 -0.0597 -0.00602276736611 -0.0756317307282 -0.05975 0.000195717322253 -0.0756096828241 -0.0598 0.00640061616394 -0.0755873656106 -0.05985 0.01208678307 -0.075564772014 -0.0599 0.0167187363643 -0.0755418939024 -0.05995 0.0200056893233 -0.0755187218911 -0.06 0.0218606797536 -0.0754952450703 -0.06005 0.0224598290366 -0.0754714506832 -0.0601 0.0220247896284 -0.0754473236879 -0.06015 0.0208421424262 -0.0754228462122 -0.0602 0.0191062315342 -0.0753979968116 -0.06025 0.0170162160041 -0.0753727495168 -0.0603 0.0146711493576 -0.0753470725377 -0.06035 0.0121891619476 -0.0753209265687 -0.0604 0.00960775528724 -0.0752942625047 -0.06045 0.00700023640248 -0.0752670184505 -0.0605 0.0043722900274 -0.0752391157611 -0.06055 0.00177438164862 -0.0752104539213 -0.0606 -0.00080406791064 -0.075180903922 -0.06065 -0.00332456996913 -0.0751502998515 -0.0607 -0.00580634834694 -0.0751184282624 -0.06075 -0.0082174821597 -0.0750850148997 -0.0608 -0.0105819483798 -0.0750497082014 -0.06085 -0.0128715666491 -0.075012058938 -0.0609 -0.0151130126483 -0.074971495138 -0.06095 -0.0172803730493 -0.0749272913153 -0.061 -0.0194020003705 -0.0748785307029 -0.06105 -0.0214535825527 -0.0748240589608 -0.0611 -0.0234647640495 -0.0747624273849 -0.06115 -0.0254126601301 -0.0746918232449 -0.0612 -0.0273281784015 -0.074609984254 -0.06125 -0.0291899112223 -0.0745140935369 -0.0613 -0.0310300930712 -0.0744006505466 -0.06135 -0.0328288086314 -0.07426531239 -0.0614 -0.0346195280423 -0.0741026986461 -0.06145 -0.0363835714549 -0.0739061512115 -0.0615 -0.0381551609014 -0.0736674386161 -0.06155 -0.0399160686799 -0.0733763917859 -0.0616 -0.0417000941728 -0.0730204549661 -0.06165 -0.0434877804366 -0.0725841314692 -0.0617 -0.0453101861061 -0.0720482984961 -0.06175 -0.0471435524277 -0.0713893580853 -0.0618 -0.0490123280107 -0.0705781809765 -0.06185 -0.0508839164897 -0.0695787848317 -0.0619 -0.0527714050589 -0.0683466632608 -0.06195 -0.0546293044961 -0.0668266381598 -0.062 -0.0564574022674 -0.0649500241121 -0.06205 -0.0581992121157 -0.0626307234831 -0.0621 -0.0598483656286 -0.0597595072067 -0.06215 -0.0613499409268 -0.0561949323654 -0.0622 -0.062707516833 -0.0517475476763 -0.06225 -0.0638835050003 -0.0461501243168 -0.0623 -0.0649023530609 -0.0389993081372 -0.06235 -0.0657468219191 -0.0296481406797 -0.0624 -0.0664572358547 -0.0170751741431 -0.06245 -0.0670263557279 -0.000108490673115 -0.0625 -0.0674984681968 0.0205099184085 -0.06255 -0.0678659836117 0.0381596402844 -0.0626 -0.0681699272947 0.0456180879914 -0.06265 -0.0683983674229 0.0465029289503 -0.0627 -0.0685875952368 0.0461594981888 -0.06275 -0.0687214569716 0.0455259499574 -0.0628 -0.0688324445434 0.0446861632844 -0.06285 -0.0689014057728 0.0436372072442 -0.0629 -0.0689582525952 0.0423966438547 -0.06295 -0.0689819136486 0.040961344872 -0.063 -0.0690006201626 0.0393413020987 -0.06305 -0.0689921049761 0.0375551108859 -0.0631 -0.0689834914874 0.0356316717681 -0.06315 -0.0689517660996 0.0335821383736 -0.0632 -0.0689232976729 0.0314255634358 -0.06325 -0.0688746038676 0.0291772070167 -0.0633 -0.0688315196117 0.0268538413574 -0.06335 -0.0687702693113 0.0244702930928 -0.0634 -0.068716295682 0.0220408183232 -0.06345 -0.0686456441492 0.0195781568243 -0.0635 -0.0685834590811 0.017093720707 -0.06355 -0.0685056834736 0.0145975622764 -0.0636 -0.0684372272015 0.0120982340228 -0.06365 -0.0683539832957 0.0096030677827 -0.0637 -0.0682806714962 0.00711799180613 -0.06375 -0.068193171437 0.00464787726784 -0.0638 -0.0681160440155 0.00219639455364 -0.06385 -0.0680251812394 -0.000233671310891 -0.0639 -0.0679450074853 -0.0026405176799 -0.06395 -0.0678514454222 -0.00502308031542 -0.064 -0.0677687989592 -0.00738110621855 -0.06405 -0.067673034456 -0.00971500402663 -0.0641 -0.0675883469749 -0.0120259333156 -0.06415 -0.0674907558625 -0.0143157778791 -0.0642 -0.0674043558037 -0.0165873091444 -0.06425 -0.0673052257584 -0.0188443277948 -0.0643 -0.0672173662449 -0.0210919742491 -0.06435 -0.0671169205576 -0.0233370989184 -0.0644 -0.0670277996288 -0.0255887979843 -0.06445 -0.0669262144293 -0.0278590696234 -0.0645 -0.0668359897228 -0.0301636283111 -0.06455 -0.0667334065084 -0.0325228485149 -0.0646 -0.0666422059448 -0.0349627727009 -0.06465 -0.0665387406906 -0.0375160282511 -0.0647 -0.0664466702547 -0.0402222419829 -0.06475 -0.0663424200694 -0.0431271529352 -0.0648 -0.0662495694995 -0.0462788037692 -0.06485 -0.0661446174844 -0.0497181308913 -0.0649 -0.0660510644244 -0.0534601389212 -0.06495 -0.0659454832253 -0.057462825391 -0.065 -0.0658512962668 -0.0615885218606 -0.06505 -0.0657451506801 -0.0655822888832 -0.0651 -0.065650391591 -0.0691145980163 -0.06515 -0.0655437404661 -0.0719111083014 -0.0652 -0.0654484658153 -0.0738872555488 -0.06525 -0.0653413634438 -0.0751562543546 -0.0653 -0.0652456257887 -0.0759191521833 -0.06535 -0.0651381229181 -0.0763612948444 -0.0654 -0.0650419716685 -0.0766138864662 -0.06545 -0.0649341162357 -0.076758185852 -0.0655 -0.0648375982737 -0.0768412764459 -0.06555 -0.064729435927 -0.0768896667365 -0.0656 -0.064632596045 -0.076918172233 -0.06565 -0.0645241705097 -0.076935114133 -0.0657 -0.0644270517119 -0.0769452178371 -0.06575 -0.064318405036 -0.0769512066341 -0.0658 -0.0642210487356 -0.0769546741345 -0.06585 -0.0641122214439 -0.0769565686432 -0.0659 -0.0640146675821 -0.0769574629867 -0.06595 -0.0639056987663 -0.0769577089534 -0.066 -0.0638079858771 -0.0769575255206 -0.06605 -0.0636989132416 -0.0769570511053 -0.0661 -0.0636010784859 -0.0769563742887 -0.06615 -0.063491938374 -0.0769555524516 -0.0662 -0.0633940175579 -0.0769546232803 -0.06625 -0.0632848449624 -0.0769536116026 -0.0663 -0.0631868725409 -0.0769525341541 -0.06635 -0.0630777011003 -0.0769514019838 -0.0664 -0.062979710165 -0.0769502227694 -0.06645 -0.0628705721418 -0.076949001436 -0.0665 -0.0627725943892 -0.0769477415628 -0.06655 -0.0626635206299 -0.0769464452249 -0.0666 -0.0625655863136 -0.0769451140649 -0.06665 -0.0624566061911 -0.0769437487707 -0.0667 -0.0623587440574 -0.0769423500286 -0.06675 -0.0622498854039 -0.0769409178206 -0.0668 -0.062152122621 -0.0769394523368 -0.06685 -0.0620434116541 -0.0769379531814 -0.0669 -0.0619457737374 -0.0769364202709 -0.06695 -0.0618372349845 -0.0769348529955 -0.067 -0.0617397457212 -0.0769332511079 -0.06705 -0.0616314019455 -0.0769316138681 -0.0671 -0.0615340833216 -0.0769299409195 -0.06715 -0.0614259554505 -0.0769282314356 -0.0672 -0.0613288275805 -0.0769264849783 -0.06725 -0.061220934637 -0.0769247006571 -0.0673 -0.0611240156975 -0.0769228779652 -0.06735 -0.0610163747346 -0.0769210159604 -0.0674 -0.0609196808997 -0.0769191140729 -0.06745 -0.0608123069385 -0.076917171314 -0.0675 -0.0607158523204 -0.0769151870529 -0.06755 -0.0606087582917 -0.0769131602568 -0.0676 -0.0605125548831 -0.0769110902334 -0.06765 -0.0604057515716 -0.076908975906 -0.0677 -0.0603098091924 -0.0769068165198 -0.06775 -0.0602033051852 -0.076904610953 -0.0678 -0.0601076314308 -0.0769023583864 -0.06785 -0.0600014330656 -0.076900057652 -0.0679 -0.0599060332568 -0.0768977078642 -0.06795 -0.0598001445727 -0.0768953078065 -0.068 -0.059705021706 -0.0768928565254 -0.06805 -0.0595994443942 -0.0768903527542 -0.0681 -0.0595045990932 -0.0768877954699 -0.06815 -0.0593993324485 -0.0768851833536 -0.0682 -0.0593047629153 -0.0768825153117 -0.06825 -0.0591998037866 -0.0768797899712 -0.0683 -0.0591055057512 -0.0768770061669 -0.06835 -0.0590008484894 -0.0768741624706 -0.0684 -0.0589068151554 -0.076871257645 -0.06845 -0.0588024515571 -0.0768682902056 -0.0685 -0.0587086735433 -0.0768652588428 -0.06855 -0.0586045927913 -0.0768621620153 -0.0686 -0.0585110580707 -0.0768589983418 -0.06865 -0.0584072466679 -0.0768557662241 -0.0687 -0.0583139404964 -0.0768524642099 -0.06875 -0.0582103821901 -0.0768490906446 -0.0688 -0.058117287025 -0.0768456440064 -0.06885 -0.0580139627219 -0.076842122585 -0.0689 -0.0579210581337 -0.0768385247911 -0.06895 -0.0578179458038 -0.0768348488602 -0.069 -0.0577252083708 -0.0768310931384 -0.06905 -0.057622282933 -0.076827255809 -0.0691 -0.0575296861179 -0.0768233351561 -0.06915 -0.0574269193094 -0.0768193293134 -0.0692 -0.0573344333212 -0.0768152365069 -0.06925 -0.0572317935477 -0.0768110548232 -0.0693 -0.0571393851762 -0.0768067824341 -0.06935 -0.0570368373306 -0.0768024173831 -0.0694 -0.0569444697527 -0.0767979577921 -0.06945 -0.0568419750106 -0.0767934016652 -0.0695 -0.0567496075703 -0.0767887470794 -0.06955 -0.0566471231478 -0.0767839920038 -0.0696 -0.0565547110905 -0.0767791344756 -0.06965 -0.0564521899581 -0.0767741724343 -0.0697 -0.056359684126 -0.076769103883 -0.06975 -0.0562570746819 -0.0767639267366 -0.0698 -0.0561644211582 -0.0767586389699 -0.06985 -0.0560616668391 -0.0767532384784 -0.0699 -0.0559688065252 -0.0767477232148 -0.06995 -0.055865845353 -0.0767420910611 -0.07 -0.0557727134838 -0.076736339954 -0.07005 -0.0556694775397 -0.0767304677675 -0.0701 -0.0555760031086 -0.076724472429 -0.07015 -0.0554724179083 -0.076718351811 -0.0702 -0.0553785229936 -0.0767121038383 -0.07025 -0.0552745067629 -0.076705726388 -0.0703 -0.0551801057443 -0.0766992173884 -0.07035 -0.0550755685661 -0.0766925747273 -0.0704 -0.054980567196 -0.0766857963432 -0.07045 -0.0548754100017 -0.0766788801404 -0.0705 -0.0547797043127 -0.0766718240736 -0.07055 -0.0546738177006 -0.0766646260698 -0.0706 -0.0545772927225 -0.0766572841071 -0.07065 -0.0544705555587 -0.076649796141 -0.0707 -0.054373083793 -0.0766421601785 -0.07075 -0.0542653615494 -0.0766343742093 -0.0708 -0.054166801159 -0.0766264362749 -0.07085 -0.0540579439398 -0.0766183444041 -0.0709 -0.0539581365949 -0.0766100966785 -0.07095 -0.0538479767841 -0.0766016911719 -0.071 -0.0537467450881 -0.0765931260112 -0.07105 -0.0536350945277 -0.0765843993199 -0.0711 -0.0535322389235 -0.0765755092746 -0.07115 -0.0534188855193 -0.0765664540519 -0.0712 -0.0533141805589 -0.0765572318824 -0.07125 -0.0531988841761 -0.0765478410007 -0.0713 -0.0530920739999 -0.0765382796959 -0.07135 -0.052974561477 -0.0765285462632 -0.0714 -0.0528653543067 -0.0765186390529 -0.07145 -0.0527453133642 -0.0765085564235 -0.0715 -0.0526333747547 -0.0764982967893 -0.07155 -0.0525104465065 -0.0764878585753 -0.0716 -0.0523953910267 -0.076477240262 -0.07165 -0.0522691607234 -0.0764664403423 -0.0717 -0.0521505416309 -0.0764554573637 -0.07175 -0.0520205271268 -0.0764442898875 -0.0718 -0.0518978234688 -0.0764329365302 -0.07185 -0.0517634607583 -0.0764213959226 -0.0719 -0.0516360611174 -0.0764096667496 -0.07195 -0.0514966860418 -0.07639774771 -0.072 -0.0513638679052 -0.0763856375565 -0.07205 -0.0512186928274 -0.0763733350564 -0.0721 -0.0510795961574 -0.0763608390289 -0.07215 -0.0509276799451 -0.0763481483062 -0.0722 -0.0507812730047 -0.0763352617712 -0.07225 -0.0506214820245 -0.0763221783195 -0.0723 -0.0504665167278 -0.076308896895 -0.07235 -0.0502974735967 -0.0762954164519 -0.0724 -0.0501324265308 -0.0762817359899 -0.07245 -0.0499524420351 -0.0762678545177 -0.0725 -0.0497754356236 -0.0762537710864 -0.07255 -0.049582417133 -0.0762394847521 -0.0726 -0.0493911128725 -0.0762249946093 -0.07265 -0.0491824394566 -0.0762102997552 -0.0727 -0.0489738913178 -0.0761953993207 -0.07275 -0.0487462409883 -0.0761802924335 -0.0728 -0.0485166910071 -0.0761649782504 -0.07285 -0.0482657978808 -0.0761494559203 -0.0729 -0.0480103864609 -0.0761337246142 -0.07295 -0.0477306936003 -0.0761177834876 -0.073 -0.047443041522 -0.076101631712 -0.07305 -0.0471271952595 -0.0760852684358 -0.0731 -0.046798788934 -0.0760686928124 -0.07315 -0.0464368876664 -0.0760519039638 -0.0732 -0.0460561562718 -0.0760349010073 -0.07325 -0.0456346105835 -0.0760176830152 -0.0733 -0.0451855104023 -0.0760002490427 -0.07335 -0.0446852751331 -0.0759825980874 -0.0734 -0.0441450694857 -0.0759647291125 -0.07345 -0.0435388409248 -0.0759466410063 -0.0735 -0.0428745438694 -0.0759283326049 -0.07355 -0.0421222271819 -0.0759098026466 -0.0736 -0.0412848060521 -0.0758910497939 -0.07365 -0.0403260844546 -0.0758720725861 -0.0737 -0.0392409373306 -0.0758528694546 -0.07375 -0.0379831148732 -0.0758334386747 -0.0738 -0.0365346960929 -0.0758137783763 -0.07385 -0.0348336188881 -0.0757938864876 -0.0739 -0.0328425901601 -0.0757737607427 -0.07395 -0.0304770862494 -0.0757533986174 -0.074 -0.0276756323021 -0.0757327973259 -0.07405 -0.0243324044968 -0.0757119537493 -0.0741 -0.0203768122584 -0.075690864417 -0.07415 -0.0157241488232 -0.0756695254207 -0.0742 -0.0103832465007 -0.0756479323783 -0.07425 -0.00444133541767 -0.0756260803215 -0.0743 0.00181174217435 -0.0756039636339 -0.07435 0.00794367576422 -0.0755815758999 -0.0744 0.0133937090269 -0.0755589097966 -0.07445 0.0177067352589 -0.0755359568847 -0.0745 0.020612456506 -0.0755127074196 -0.07455 0.0221310927905 -0.0754891500447 -0.0746 0.0224304460104 -0.075465271465 -0.07465 0.0217864928936 -0.0754410559625 -0.0747 0.0204343340337 -0.0754164848271 -0.07475 0.0186002664196 -0.0753915355458 -0.0748 0.0164264068395 -0.0753661807915 -0.07485 0.0140461256001 -0.0753403870138 -0.0749 0.0115255976026 -0.0753141126293 -0.07495 0.0089412169549 -0.0752873055504 -0.075 0.00631817751086 -0.0752598999893 -0.07505 0.00370359119148 -0.075231812201 -0.0751 0.00110182890163 -0.0752029350275 -0.07515 -0.00145509525289 -0.0751731308255 -0.0752 -0.0039737269408 -0.0751422225459 -0.07525 -0.00643018372932 -0.0751099824459 -0.0753 -0.00883696537098 -0.0750761180628 -0.07535 -0.0111747392716 -0.0750402547671 -0.0754 -0.0134593546361 -0.075001914295 -0.07545 -0.015674139167 -0.0749604882862 -0.0755 -0.0178369450988 -0.0749152058645 -0.07555 -0.0199328383675 -0.0748650938134 -0.0756 -0.0219810881098 -0.0748089278025 -0.07565 -0.0239681740028 -0.0747451725048 -0.0757 -0.0259146520697 -0.0746719081764 -0.07575 -0.0278084135112 -0.0745867404562 -0.0758 -0.0296713609469 -0.0744866896257 -0.07585 -0.0314928539493 -0.074368054456 -0.0759 -0.0332961348309 -0.0742262448591 -0.07595 -0.0350719030325 -0.074055575976 -0.076 -0.0368444319081 -0.0738490148242 -0.07605 -0.0386052072366 -0.0735978682822 -0.0761 -0.0403786589729 -0.073291398702 -0.07615 -0.0421557656473 -0.07291634983 -0.0762 -0.0439592803696 -0.0724563615354 -0.07625 -0.0457771715227 -0.0718912458573 -0.0763 -0.0476272375184 -0.0711960892221 -0.07635 -0.0494903720091 -0.070340134182 -0.0764 -0.0513747681731 -0.0692853769455 -0.07645 -0.053249564892 -0.0679847881027 -0.0765 -0.055109686616 -0.066380012601 -0.07655 -0.0569114016355 -0.0643983048716 -0.0766 -0.0586395128401 -0.0619482491168 -0.07665 -0.0602460145168 -0.0589133695648 -0.0767 -0.0617193337112 -0.0551417461493 -0.07675 -0.0630236365938 -0.0504275398895 -0.0768 -0.0641659049373 -0.0444756240493 -0.07685 -0.0651315470023 -0.036832428993 -0.0769 -0.0659469314961 -0.0267647980707 -0.07695 -0.0666119999196 -0.0131551470581 -0.077 -0.0671613926575 0.00499803569304 -0.07705 -0.0675978298003 0.0257474701955 -0.0771 -0.0679545974682 0.0411131653717 -0.07715 -0.0682308390045 0.0461683344166 -0.0772 -0.0684552305409 0.0464535216656 -0.07725 -0.0686223630231 0.0460214206662 -0.0773 -0.068756698085 0.0453315352359 -0.07735 -0.0688493230188 0.0444375702554 -0.0774 -0.0689217281791 0.043338643345 -0.07745 -0.068962688165 0.0420480029893 -0.0775 -0.0689917566114 0.0405644247197 -0.07755 -0.0689962473646 0.0388979666366 -0.0776 -0.0689944595759 0.0370751920504 -0.07765 -0.0689727843357 0.0351179720269 -0.0777 -0.0689486888767 0.0330391066428 -0.07775 -0.0689079731061 0.0308575514624 -0.0778 -0.0688675341521 0.0285882243295 -0.07785 -0.068812788256 0.0262480593304 -0.0779 -0.0687602286892 0.0238512663989 -0.07795 -0.068695021703 0.0214121008766 -0.078 -0.0686333655534 0.0189426902299 -0.07805 -0.06856026521 0.0164543049057 -0.0781 -0.0684916972218 0.0139564628068 -0.07815 -0.0684125656523 0.011457502588 -0.0782 -0.0683386758633 0.00896431745266 -0.07825 -0.0682548729098 0.00648260309537 -0.0783 -0.0681768263768 0.00401688471837 -0.07835 -0.0680893517778 0.00157061233286 -0.0784 -0.0680080080458 -0.000853695712583 -0.07845 -0.0679176020596 -0.00325443378526 -0.0785 -0.0678336000775 -0.00563074597546 -0.07855 -0.0677408152644 -0.0079825594191 -0.0786 -0.0676546341465 -0.0103104644233 -0.07865 -0.0675598868614 -0.0126158108722 -0.0787 -0.0674718895683 -0.014900686572 -0.07875 -0.067375497043 -0.0171681174504 -0.0788 -0.0672859618937 -0.0194222070427 -0.07885 -0.0671881690344 -0.0216685031364 -0.0789 -0.0670973125005 -0.0239143686073 -0.07895 -0.066998311296 -0.0261695848415 -0.079 -0.0669063045407 -0.0284470140525 -0.07905 -0.0668062481539 -0.030763481395 -0.0791 -0.0667132290443 -0.0331407150042 -0.07915 -0.0666122420664 -0.035606379029 -0.0792 -0.066518323932 -0.0381948883055 -0.07925 -0.0664165098599 -0.0409476113941 -0.0793 -0.0663217878753 -0.0439114051397 -0.07935 -0.0662192345665 -0.0471336935523 -0.0794 -0.0661237904206 -0.0506510057047 -0.07945 -0.0660205740895 -0.0544671567169 -0.0795 -0.0659244794014 -0.058519210006 -0.07955 -0.0658206675388 -0.0626397831911 -0.0796 -0.0657239863548 -0.06654703156 -0.07965 -0.0656196398639 -0.069910598301 -0.0797 -0.0655224304868 -0.072495325517 -0.07975 -0.0654176052498 -0.0742731673151 -0.0798 -0.0653199215765 -0.0753922848421 -0.07985 -0.0652146695937 -0.0760570681874 -0.0799 -0.0651165620841 -0.0764402455938 -0.07995 -0.0650109322989 -0.076658916058 -0.08 -0.0649124486781 -0.0767840249879 -0.08005 -0.0648064875711 -0.0768562633709 -0.0801 -0.0647076733295 -0.0768984622265 -0.08015 -0.0646014253388 -0.076923386246 -0.0802 -0.064502324083 -0.0769382226016 -0.08025 -0.0643958318914 -0.0769470666912 -0.0803 -0.0642964855748 -0.0769522885674 -0.08035 -0.0641897902936 -0.0769552803979 -0.0804 -0.0640902393605 -0.0769568745936 -0.08045 -0.0639833806393 -0.0769575753919 -0.0805 -0.0638836641065 -0.0769576943199 -0.08055 -0.0637766801932 -0.0769574253101 -0.0806 -0.063676835694 -0.076956892115 -0.08065 -0.0635697634673 -0.0769561734248 -0.0807 -0.0634698272757 -0.076955321155 -0.08075 -0.0633627022622 -0.0769543686894 -0.0808 -0.0632627093028 -0.0769533388864 -0.08085 -0.0631555656784 -0.0769522463592 -0.0809 -0.0630555495195 -0.0769511015824 -0.08095 -0.0629484200944 -0.0769499110121 -0.081 -0.0628484129231 -0.0769486795764 -0.08105 -0.0627413291075 -0.0769474100302 -0.0811 -0.062641361687 -0.0769461046931 -0.08115 -0.0625343534393 -0.0769447645746 -0.0812 -0.0624344550503 -0.0769433907038 -0.08125 -0.0623275508141 -0.0769419832375 -0.0813 -0.0622277491861 -0.0769405425295 -0.08135 -0.0621209758176 -0.0769390683053 -0.0814 -0.0620212970561 -0.076937560541 -0.08145 -0.0619146797505 -0.0769360187359 -0.0815 -0.0618151482616 -0.0769344426366 -0.08155 -0.0617087104773 -0.0769328316179 -0.0816 -0.061609348893 -0.0769311852732 -0.08165 -0.0615031122784 -0.0769295029031 -0.0817 -0.0614039413848 -0.0769277839883 -0.08175 -0.061297925708 -0.0769260277796 -0.0818 -0.061198964377 -0.0769242336663 -0.08185 -0.0610931874596 -0.0769224008611 -0.0819 -0.0609944525838 -0.0769205286734 -0.08195 -0.0608889302377 -0.0769186162816 -0.082 -0.0607904366703 -0.0769166629216 -0.08205 -0.0606851826389 -0.0769146677377 -0.0821 -0.0605869431355 -0.0769126298953 -0.08215 -0.0604819690369 -0.0769105485032 -0.0822 -0.0603839942 -0.0769084226575 -0.08225 -0.0602793094731 -0.0769062514285 -0.0823 -0.0601816076994 -0.0769040338438 -0.08235 -0.0600772195518 -0.0769017689317 -0.0824 -0.0599797969814 -0.0768994556512 -0.08245 -0.0598757103398 -0.0768970929853 -0.0825 -0.0597785708072 -0.076894679824 -0.08255 -0.0596747882691 -0.0768922151015 -0.0826 -0.0595779332552 -0.0768896976388 -0.08265 -0.05947445504 -0.0768871263182 -0.0827 -0.0593778836223 -0.0768844998914 -0.08275 -0.0592747075217 -0.0768818171859 -0.0828 -0.0591784163238 -0.0768790768838 -0.08285 -0.0590755376499 -0.0768762777558 -0.0829 -0.0589795207898 -0.0768734184145 -0.08295 -0.0588769323225 -0.0768704975716 -0.083 -0.0587811813572 -0.0768675137707 -0.08305 -0.0586788732858 -0.0768644656635 -0.0831 -0.0585833771496 -0.0768613517254 -0.08315 -0.0584813370074 -0.076858170547 -0.0832 -0.0583860819434 -0.0768549205365 -0.08325 -0.0582842945372 -0.0768516002237 -0.0833 -0.0581892640235 -0.0768482079512 -0.08335 -0.0580877113536 -0.076844742188 -0.0834 -0.0579928860159 -0.0768412012133 -0.08345 -0.0578915471815 -0.0768375834362 -0.0835 -0.0577969046924 -0.0768338870752 -0.08355 -0.0576957557857 -0.0768301104814 -0.0836 -0.0576012707522 -0.0768262518156 -0.08365 -0.0575002847364 -0.0768223093728 -0.0837 -0.0574059285658 -0.0768182812594 -0.08375 -0.0573050751282 -0.0768141657173 -0.0838 -0.057210815871 -0.0768099608023 -0.08385 -0.0571100612575 -0.0768056647065 -0.0839 -0.0570158634296 -0.0768012754392 -0.08395 -0.0569151702496 -0.0767967911467 -0.084 -0.0568209946183 -0.0767922097966 -0.08405 -0.0567203216126 -0.0767875294934 -0.0841 -0.0566261249496 -0.0767827481678 -0.08415 -0.0565254267278 -0.0767778638878 -0.0842 -0.056431161523 -0.076772874553 -0.08425 -0.0563303882486 -0.0767677781997 -0.0843 -0.0562360023682 -0.0767625727022 -0.08435 -0.0561350993925 -0.0767572560703 -0.0844 -0.0560405356881 -0.0767518261588 -0.08445 -0.0559394431276 -0.0767462809572 -0.0845 -0.0558446389735 -0.0767406183065 -0.08455 -0.0557432912055 -0.0767348361816 -0.0846 -0.0556481779559 -0.0767289324161 -0.08465 -0.0555465030365 -0.0767229049765 -0.0847 -0.0554510053964 -0.0767167516959 -0.08475 -0.0553489243761 -0.0767104705387 -0.0848 -0.0552529596566 -0.0767040593436 -0.08485 -0.0551503857719 -0.0766975160793 -0.0849 -0.055053863017 -0.0766908385962 -0.08495 -0.0549507007483 -0.0766840248733 -0.085 -0.0548535197124 -0.076677072779 -0.08505 -0.0547496636697 -0.0766699803087 -0.0851 -0.0546517136052 -0.0766627453553 -0.08515 -0.0545470472102 -0.0766553659373 -0.0852 -0.0544482054344 -0.0766478399777 -0.08525 -0.0543425993646 -0.0766401655238 -0.0853 -0.0542427295675 -0.0766323405345 -0.08535 -0.0541360399079 -0.076624363091 -0.0854 -0.0540349901324 -0.0766162311934 -0.08545 -0.0539270561697 -0.0766079429624 -0.0855 -0.0538246564013 -0.0765994964451 -0.08555 -0.0537152979872 -0.0765908898068 -0.0856 -0.0536113572648 -0.0765821211461 -0.08565 -0.0535003716471 -0.0765731886772 -0.0857 -0.0533946745855 -0.0765640905536 -0.08575 -0.0532818325866 -0.076554825043 -0.0858 -0.0531741351707 -0.0765453903586 -0.08585 -0.0530591765528 -0.0765357848253 -0.0859 -0.0529492010224 -0.0765260067193 -0.08595 -0.0528318288345 -0.0765160544254 -0.086 -0.0527192574313 -0.0765059262846 -0.08605 -0.0525991310818 -0.0764956207449 -0.0861 -0.0524835983568 -0.0764851362154 -0.08615 -0.0523603250608 -0.0764744712092 -0.0862 -0.0522414083519 -0.0764636242047 -0.08625 -0.052114532508 -0.0764525937806 -0.0863 -0.0519917400728 -0.0764413784855 -0.08635 -0.0518607299785 -0.0764299769659 -0.0864 -0.0517334860898 -0.0764183878409 -0.08645 -0.0515977171927 -0.076406609824 -0.0865 -0.0514653432747 -0.0763946416038 -0.08655 -0.0513240768788 -0.07638248196 -0.0866 -0.0511857674241 -0.0763701296508 -0.08665 -0.0510381233853 -0.0763575835209 -0.0867 -0.0508929149236 -0.0763448423942 -0.08675 -0.0507378363013 -0.0763319051775 -0.0868 -0.0505845670156 -0.0763187707592 -0.08685 -0.0504207738118 -0.0763054381052 -0.0869 -0.0502580304213 -0.0762919061629 -0.08695 -0.050083958407 -0.0762781739525 -0.087 -0.0499100054786 -0.0762642404763 -0.08705 -0.0497237242629 -0.0762501048038 -0.0871 -0.0495364089606 -0.0762357659847 -0.08715 -0.0493355108738 -0.0762212231304 -0.0872 -0.0491321328537 -0.0762064753316 -0.08725 -0.0489135800553 -0.0761915217337 -0.0873 -0.0486907111107 -0.0761763614574 -0.08735 -0.0484506219787 -0.0761609936718 -0.0874 -0.0482038520084 -0.0761454175187 -0.08745 -0.0479371977313 -0.0761296321778 -0.0875 -0.0476607706994 -0.0761136367972 -0.08755 -0.0473609364531 -0.0760974305546 -0.0876 -0.0470472188654 -0.0760810125888 -0.08765 -0.0467053567682 -0.0760643820564 -0.0877 -0.0463440459015 -0.0760475380683 -0.08775 -0.0459481009807 -0.0760304797411 -0.0878 -0.0455250201393 -0.0760132061333 -0.08785 -0.0450582319786 -0.0759957162955 -0.0879 -0.044553456576 -0.0759780092084 -0.08795 -0.0439920028678 -0.0759600838251 -0.088 -0.0433768815135 -0.0759419390133 -0.08805 -0.0426860936619 -0.0759235735932 -0.0881 -0.041918419914 -0.0759049862768 -0.08815 -0.0410466030715 -0.0758861757038 -0.0882 -0.0400626926781 -0.0758671403803 -0.08825 -0.0389309784972 -0.0758478787057 -0.0883 -0.0376327377234 -0.0758283889137 -0.08835 -0.0361187919795 -0.0758086690905 -0.0884 -0.0343536440014 -0.0757887171111 -0.08845 -0.032267947564 -0.0757685306519 -0.0885 -0.0298030067778 -0.0757481071191 -0.08855 -0.0268655214893 -0.0757274436505 -0.0886 -0.0233773911999 -0.0757065370368 -0.08865 -0.0192419468793 -0.0756853837042 -0.0887 -0.014414066401 -0.0756639796253 -0.08875 -0.00889726701653 -0.0756423202789 -0.0888 -0.00284641700331 -0.0756204005355 -0.08885 0.00342944033498 -0.0755982145887 -0.0889 0.0094329342876 -0.0755757557998 -0.08895 0.0146329615743 -0.07555301658 -0.089 0.0185916201143 -0.0755299881729 -0.08905 0.0211350191661 -0.0755066604508 -0.0891 0.0223118063726 -0.0754830215915 -0.08915 0.0223472048373 -0.0754590577264 -0.0892 0.0214929673952 -0.0754347524272 -0.08925 0.0200034144145 -0.0754100860888 -0.0893 0.0180635006145 -0.0753850350661 -0.08935 0.0158316304158 -0.0753595705768 -0.0894 0.0134034624031 -0.0753336571945 -0.08945 0.0108664182299 -0.0753072508896 -0.0895 0.00826375057661 -0.0752802963846 -0.08955 0.00564523898141 -0.0752527237113 -0.0896 0.00302738468033 -0.075224443667 -0.08965 0.000440771418807 -0.0751953419759 -0.0897 -0.00211192132618 -0.075165271772 -0.08975 -0.00461026836211 -0.0751340441125 -0.0898 -0.00705903802159 -0.0751014160302 -0.08985 -0.00944340640505 -0.0750670756886 -0.0899 -0.0117722917484 -0.0750306239661 -0.08995 -0.0140340717395 -0.0749915517962 -0.09 -0.0162400791147 -0.0749492122764 -0.09005 -0.0183806659249 -0.0749027864819 -0.0901 -0.0204687515699 -0.0748512415026 -0.09015 -0.0224961505685 -0.0747932790223 -0.0902 -0.0244771011928 -0.0747272722053 -0.09025 -0.0264047894791 -0.0746511882774 -0.0903 -0.0282947926647 -0.0745624934289 -0.09035 -0.0301417332193 -0.0744580360198 -0.0904 -0.0319625738185 -0.0743339029913 -0.09045 -0.0337533406421 -0.074185243331 -0.0905 -0.0355322119938 -0.0740060508607 -0.09055 -0.0372962524509 -0.0737888969163 -0.0906 -0.0390642283711 -0.0735246011094 -0.09065 -0.0408332702006 -0.0732018256116 -0.0907 -0.0426213114361 -0.0728065746683 -0.09075 -0.0444235550478 -0.07232157645 -0.0908 -0.0462544068113 -0.0717255180196 -0.09085 -0.048103655993 -0.070992095699 -0.0909 -0.0499779344937 -0.0700888305057 -0.09095 -0.0518568884171 -0.0689755788883 -0.091 -0.0537348365946 -0.0676026357987 -0.09105 -0.0555781133091 -0.065908266496 -0.0911 -0.0573685500161 -0.0638153835541 -0.09115 -0.0590636501769 -0.0612268352358 -0.0912 -0.0606427919738 -0.0580182255666 -0.09125 -0.06206941285 -0.0540259678817 -0.0913 -0.0633369385732 -0.0490255650379 -0.09135 -0.064428529832 -0.0426895128547 -0.0914 -0.0653587163834 -0.0345058315034 -0.09145 -0.0661290797298 -0.0236459265309 -0.0915 -0.0667670481406 -0.00891903361558 -0.09155 -0.0672810009567 0.0103212350279 -0.0916 -0.0676998582995 0.0306171142726 -0.09165 -0.0680299685771 0.0432991630817 -0.0917 -0.068296242473 0.0464303238185 -0.09175 -0.0685004192487 0.046376647515 -0.0918 -0.0686628605433 0.045868468046 -0.09185 -0.0687813184471 0.0451265240858 -0.0919 -0.0688727388395 0.0441781005562 -0.09195 -0.0689321328163 0.0430305581341 -0.092 -0.0689741872186 0.0416897536033 -0.09205 -0.0689921597868 0.0401588668441 -0.0921 -0.0689992846411 0.0384472465666 -0.09215 -0.0689877082999 0.0365894898939 -0.0922 -0.0689697179394 0.0345991680313 -0.09225 -0.0689367455493 0.0324924310439 -0.0923 -0.0689004433335 0.0302867555215 -0.09235 -0.0688517750106 0.0279976463785 -0.0924 -0.0688019538092 0.025641527265 -0.09245 -0.0687416320574 0.0232324142393 -0.0925 -0.0686817108534 0.0207842749219 -0.09255 -0.0686126341575 0.0183087920033 -0.0926 -0.0685450754973 0.0158170021036 -0.09265 -0.0684693399989 0.0133179320798 -0.0927 -0.0683959314192 0.0108197088983 -0.09275 -0.0683150640135 0.00832877284223 -0.0928 -0.0682371120302 0.00585063093865 -0.09285 -0.06815223246 0.00338942389934 -0.0929 -0.0680706984759 0.000948439649913 -0.09295 -0.0679826336019 -0.00147011650666 -0.093 -0.0678982302026 -0.00386477741132 -0.09305 -0.0678075953071 -0.00623494263363 -0.0931 -0.0677208550125 -0.00858066869605 -0.09315 -0.0676281120141 -0.0109027733628 -0.0932 -0.067539436627 -0.0132027586192 -0.09325 -0.067444935954 -0.0154829631382 -0.0933 -0.0673546321187 -0.0177466461824 -0.09335 -0.0672586429231 -0.0199982661008 -0.0934 -0.0671669478235 -0.0222437783043 -0.09345 -0.0670696798568 -0.0244911206582 -0.0935 -0.0669767798377 -0.0267507850993 -0.09355 -0.0668783993099 -0.0290365747353 -0.0936 -0.0667844434037 -0.0313664746052 -0.09365 -0.0666850845253 -0.0337636514511 -0.0937 -0.0665901942935 -0.0362574386325 -0.09375 -0.0664899676727 -0.0388840700043 -0.0938 -0.0663942443838 -0.041686564042 -0.09385 -0.0662932431653 -0.0447125968092 -0.0939 -0.0661967730399 -0.048008233179 -0.09395 -0.0660950773847 -0.051604170647 -0.094 -0.065997935426 -0.0554907353408 -0.09405 -0.0658956157905 -0.0595813833389 -0.0941 -0.0657978685925 -0.0636780219539 -0.09415 -0.0656949881329 -0.0674761343224 -0.0942 -0.0655966959357 -0.0706546644411 -0.09425 -0.0654933122619 -0.0730258170816 -0.0943 -0.0653945304498 -0.0746156974567 -0.09435 -0.0652906969067 -0.0755987630813 -0.0944 -0.0651914771023 -0.0761768418894 -0.09445 -0.0650872437029 -0.0765086610131 -0.0945 -0.0649876345622 -0.0766979731823 -0.09455 -0.064883048661 -0.0768064932328 -0.0946 -0.0647830964408 -0.076869335951 -0.09465 -0.0646782032113 -0.0769061559327 -0.0947 -0.0645779521683 -0.0769279568381 -0.09475 -0.0644727949338 -0.0769409479206 -0.0948 -0.0643722875966 -0.076948684079 -0.09485 -0.0642669080508 -0.0769532271436 -0.0949 -0.0641661853944 -0.0769557970482 -0.09495 -0.0640606237352 -0.0769571224402 -0.095 -0.0639597252835 -0.0769576502261 -0.09505 -0.063854020291 -0.0769576538343 -0.0951 -0.0637529841723 -0.0769573077912 -0.09515 -0.0636471732473 -0.0769567201927 -0.0952 -0.0635460362231 -0.0769559635718 -0.09525 -0.0634401554088 -0.0769550823728 -0.0953 -0.0633389528882 -0.0769541086795 -0.09535 -0.0632330368778 -0.076953061081 -0.0954 -0.063131802918 -0.0769519547258 -0.09545 -0.0630258850462 -0.0769507971799 -0.0955 -0.0629246523344 -0.0769495961219 -0.09555 -0.0628187645507 -0.0769483542155 -0.0956 -0.0627175643685 -0.0769470756674 -0.09565 -0.062611737193 -0.0769457608832 -0.0957 -0.062510599364 -0.0769444123633 -0.09575 -0.0624048618263 -0.0769430294461 -0.0958 -0.0623038146495 -0.0769416137375 -0.09585 -0.0621981942194 -0.0769401640644 -0.0959 -0.0620972643969 -0.0769386815258 -0.09595 -0.0619917869101 -0.076937164705 -0.096 -0.0618909994719 -0.0769356143851 -0.09605 -0.0617856890544 -0.0769340290376 -0.0961 -0.0616850672834 -0.0769324092271 -0.09615 -0.0615799462777 -0.0769307533787 -0.0962 -0.0614795116374 -0.0769290618898 -0.09625 -0.061374600532 -0.0769273331707 -0.0963 -0.0612743725973 -0.0769255674792 -0.09635 -0.0611696899589 -0.0769237632256 -0.0964 -0.0610696863501 -0.0769219205436 -0.09645 -0.0609652487588 -0.0769200378487 -0.0965 -0.0608654850785 -0.0769181151589 -0.09655 -0.0607613070669 -0.0769161508958 -0.0966 -0.0606617968406 -0.0769141449669 -0.09665 -0.060557890836 -0.0769120957971 -0.0967 -0.0604586454562 -0.0769100031869 -0.09675 -0.0603550217261 -0.076907865561 -0.0968 -0.0602560503992 -0.0769056826143 -0.09685 -0.0601527169994 -0.0769034527673 -0.0969 -0.0600540266945 -0.0769011756105 -0.09695 -0.0599509894188 -0.0768988495554 -0.097 -0.0598525848176 -0.0768964740895 -0.09705 -0.059749847148 -0.0768940476102 -0.0971 -0.0596517305961 -0.0768915695029 -0.09715 -0.0595492936538 -0.0768890381469 -0.0972 -0.0594514651112 -0.0768864528266 -0.09725 -0.0593493276083 -0.0768838118985 -0.0973 -0.0592517846012 -0.076881114547 -0.09735 -0.0591499427904 -0.0768783591025 -0.0974 -0.0590526803594 -0.0768755446505 -0.09745 -0.0589511279812 -0.0768726694918 -0.0975 -0.0588541386262 -0.0768697326147 -0.09755 -0.0587528668512 -0.0768667322876 -0.0976 -0.0586561404723 -0.0768636674034 -0.09765 -0.0585551378411 -0.0768605361961 -0.0977 -0.0584586616753 -0.0768573374655 -0.09775 -0.0583579140298 -0.0768540694093 -0.0978 -0.0582616725774 -0.0768507307369 -0.09785 -0.0581611629824 -0.0768473196089 -0.0979 -0.0580651379233 -0.076843834647 -0.09795 -0.0579648465793 -0.0768402739745 -0.098 -0.0578690166817 -0.0768366361288 -0.09805 -0.0577689208247 -0.0768329191963 -0.0981 -0.0576732618346 -0.0768291216345 -0.09815 -0.0575733356167 -0.0768252414935 -0.0982 -0.0574778201306 -0.0768212771548 -0.09825 -0.0573780344863 -0.076817226634 -0.0983 -0.0572826318076 -0.0768130882416 -0.09835 -0.0571829542954 -0.0768088599603 -0.0984 -0.0570876302613 -0.0768045400347 -0.09845 -0.0569880248762 -0.0768001264178 -0.0985 -0.0568927416573 -0.0767956172934 -0.09855 -0.0567931686185 -0.0767910105879 -0.0986 -0.0566978844892 -0.0767863044303 -0.09865 -0.0565982999866 -0.076781496724 -0.0987 -0.0565029690474 -0.0767765855493 -0.09875 -0.0564033249452 -0.0767715687913 -0.0988 -0.0563078968082 -0.0767664444883 -0.09885 -0.0562081403041 -0.0767612105109 -0.0989 -0.05611255972 -0.076755864862 -0.09895 -0.0560126329388 -0.0767504054029 -0.099 -0.0559168393578 -0.0767448301078 -0.09905 -0.0558166788819 -0.0767391368337 -0.0991 -0.0557206059493 -0.0767333235328 -0.09915 -0.0556201422689 -0.0767273880632 -0.0992 -0.0555237172247 -0.0767213283625 -0.09925 -0.0554228740873 -0.0767151422955 -0.0993 -0.0553260170662 -0.0767088277925 -0.09935 -0.0552247107229 -0.0767023827307 -0.0994 -0.0551273339365 -0.0766958050394 -0.09945 -0.0550254722509 -0.0766890926141 -0.0995 -0.0549274790187 -0.0766822433902 -0.09955 -0.0548249604155 -0.0766752552863 -0.0996 -0.0547262440266 -0.076668126251 -0.09965 -0.0546229562589 -0.0766608542321 -0.0997 -0.054523398631 -0.0766534371983 -0.09975 -0.0544192173179 -0.076645873132 -0.0998 -0.0543186874034 -0.0766381600278 -0.09985 -0.054213474293 -0.0766302959079 -0.0999 -0.0541118261856 -0.0766222787986 -0.09995 -0.0540054270905 -0.0766141067666 -0.1 -0.0539024977718 -0.0766057778762 -0.10005 -0.0537947401051 -0.0765972902439 -0.1001 -0.0536903467457 -0.0765886419771 -0.10015 -0.0535810365625 -0.0765798312461 -0.1002 -0.0534749732773 -0.0765708562061 -0.10025 -0.0533638917116 -0.0765617150844 -0.1003 -0.0532559256415 -0.0765524060888 -0.10035 -0.0531428245927 -0.0765429275083 -0.1004 -0.0530326911502 -0.0765332776071 -0.10045 -0.0529172880364 -0.0765234547383 -0.1005 -0.0528046851064 -0.0765134572255 -0.10055 -0.052686656442 -0.0765032834879 -0.1006 -0.0525712372616 -0.076492931912 -0.10065 -0.0524502107545 -0.0764824009858 -0.1007 -0.0523315751244 -0.0764716891609 -0.10075 -0.0522071198856 -0.0764607949945 -0.1008 -0.0520848032435 -0.0764497170039 -0.10085 -0.0519564175684 -0.0764384538171 -0.1009 -0.0518298773045 -0.076427004019 -0.10095 -0.0516969733157 -0.0764153663082 -0.101 -0.0515655715037 -0.0764035393361 -0.10105 -0.0514274556972 -0.0763915218707 -0.1011 -0.0512904371217 -0.0763793126304 -0.10115 -0.0511462854914 -0.0763669104517 -0.1012 -0.0510027494323 -0.0763543141178 -0.10125 -0.0508515753896 -0.0763415225303 -0.1013 -0.0507004390457 -0.0763285345351 -0.10135 -0.050541051603 -0.0763153490971 -0.1014 -0.0503810021713 -0.0763019651212 -0.10145 -0.0502119508727 -0.0762883816298 -0.1015 -0.0500413820619 -0.0762745975824 -0.10155 -0.049860883577 -0.0762606120552 -0.1016 -0.0496778104642 -0.0762464240566 -0.10165 -0.0494836495005 -0.0762320327083 -0.1017 -0.0492855928331 -0.0762174370606 -0.10175 -0.0490749865581 -0.0762026362747 -0.1018 -0.0488588132707 -0.0761876294337 -0.10185 -0.0486282229792 -0.076172415727 -0.1019 -0.0483899229073 -0.0761569942614 -0.10195 -0.0481347881953 -0.0761413642442 -0.102 -0.0478691562135 -0.0761255247921 -0.10205 -0.0475835131391 -0.076109475116 -0.1021 -0.0472836883073 -0.0760932143295 -0.10215 -0.0469596104773 -0.0760767416308 -0.1022 -0.0466163947607 -0.0760600561111 -0.10225 -0.0462431585407 -0.0760431569372 -0.1023 -0.045843988431 -0.0760260431579 -0.10235 -0.0454067991521 -0.0760087138833 -0.1024 -0.0449341591626 -0.0759911680942 -0.10245 -0.0444121641699 -0.0759734048174 -0.1025 -0.0438410847684 -0.0759554229326 -0.10255 -0.0432042062454 -0.0759372213483 -0.1026 -0.0424982355762 -0.0759187988064 -0.10265 -0.0417020262431 -0.0759001540526 -0.1027 -0.0408066416759 -0.075881285643 -0.10275 -0.0397838379997 -0.0758621921081 -0.1028 -0.0386156366136 -0.0758428717565 -0.10285 -0.0372624134766 -0.0758233228356 -0.1029 -0.0356918718885 -0.0758035433304 -0.10295 -0.0338467790546 -0.0757835311159 -0.103 -0.0316737583405 -0.0757632837544 -0.10305 -0.0290919199657 -0.0757427986337 -0.1031 -0.0260243647903 -0.0757220727595 -0.10315 -0.0223735756317 -0.0757011028802 -0.1032 -0.0180662362902 -0.075679885265 -0.10325 -0.0130518907304 -0.0756584158121 -0.1033 -0.00738035431952 -0.0756366898065 -0.10335 -0.00123000773739 -0.0756147019995 -0.1034 0.00502384153779 -0.0755924463384 -0.10345 0.0108736874014 -0.0755699159989 -0.1035 0.01578278171 -0.0755471030675 -0.10355 0.0193865786555 -0.075523998501 -0.1036 0.0215603719606 -0.0755005917237 -0.10365 0.022421902427 -0.0754768704675 -0.1037 0.0221994257886 -0.0754528202142 -0.10375 0.0211629491421 -0.0754284238254 -0.1038 0.0195373151376 -0.0754036607036 -0.10385 0.0175130131363 -0.075378506039 -0.1039 0.015218486068 -0.0753529294552 -0.10395 0.0127591411726 -0.0753268935589 -0.104 0.0101975018835 -0.0753003516612 -0.10405 0.00759074330241 -0.0752732451043 -0.1041 0.00496694944968 -0.0752454994017 -0.10415 0.00235872681604 -0.0752170195426 -0.1042 -0.000223427413842 -0.0751876835991 -0.10425 -0.00275969075021 -0.0751573348885 -0.1043 -0.00524890350358 -0.0751257717477 -0.10435 -0.00767818932901 -0.0750927350346 -0.1044 -0.0100515376739 -0.0750578922832 -0.10445 -0.012359980518 -0.0750208184101 -0.1045 -0.0146104467066 -0.074980971663 -0.10455 -0.0167962846434 -0.0749376643622 -0.1046 -0.0189262476045 -0.0748900267188 -0.10465 -0.0209952613325 -0.0748369627504 -0.1047 -0.0230134611195 -0.0747770959374 -0.10475 -0.0249771343078 -0.0747087028309 -0.1048 -0.026897742283 -0.074629631289 -0.10485 -0.028772971848 -0.0745372003368 -0.1049 -0.0306156766196 -0.0744280768602 -0.10495 -0.0324249743347 -0.0742981242907 -0.105 -0.034215048489 -0.0741422162579 -0.10505 -0.0359862333032 -0.0739540075624 -0.1051 -0.037753615991 -0.0737256519965 -0.10515 -0.0395180393843 -0.0734474550251 -0.1052 -0.0412944170776 -0.0731074454251 -0.10525 -0.0430825447747 -0.0726908469774 -0.1053 -0.0448949996939 -0.0721794254093 -0.10535 -0.0467276366178 -0.0715506798897 -0.1054 -0.0485870042683 -0.070776838132 -0.10545 -0.0504606058702 -0.0698236010473 -0.1055 -0.052344197594 -0.0686485598692 -0.10555 -0.0542126116636 -0.0671991710628 -0.1056 -0.0560482478769 -0.0654101016163 -0.10565 -0.0578141484041 -0.0631996138945 -0.1057 -0.0594852379347 -0.0604643533726 -0.10575 -0.0610241877067 -0.0570712329057 -0.1058 -0.0624140286579 -0.0528436059182 -0.10585 -0.0636333100509 -0.0475356176135 -0.1059 -0.0646855391847 -0.0407820844548 -0.10595 -0.0655700727423 -0.03200345827 -0.106 -0.0663075611516 -0.0202690769631 -0.10605 -0.0669087084626 -0.0043624667387 -0.1061 -0.0673994278315 0.0157575349179 -0.10615 -0.0677908697786 0.0349364010831 -0.1062 -0.0681062261875 0.0447874264551 -0.10625 -0.0683524156838 0.0465123797185 -0.1063 -0.0685479472253 0.0462716130081 -0.10635 -0.068695344106 0.0456937450293 -0.1064 -0.0688092379216 0.0449003716991 -0.10645 -0.0688889478989 0.0438977574278 -0.1065 -0.0689464647398 0.0427010964838 -0.10655 -0.0689790206907 0.0413097847517 -0.1066 -0.0689969060435 0.0397314313783 -0.10665 -0.0689960276088 0.0379790512821 -0.1067 -0.0689855795899 0.0360862266616 -0.10675 -0.0689606183649 0.0340637949689 -0.1068 -0.0689296148779 0.0319301536626 -0.10685 -0.0688870683273 0.0297012312346 -0.1069 -0.0688409585053 0.0273934550968 -0.10695 -0.068785412263 0.0250222559035 -0.107 -0.068728066735 0.0226018918643 -0.10705 -0.0686627964673 0.020145604237 -0.1071 -0.0685969938736 0.0176649963903 -0.10715 -0.0685243614573 0.0151705331794 -0.1072 -0.0684521132681 0.012671031825 -0.10725 -0.0683738347359 0.01017415908 -0.1073 -0.0682966074664 0.00768611395458 -0.10735 -0.0682139381439 0.00521203455699 -0.1074 -0.0681328082031 0.0027558352406 -0.10745 -0.0680466726417 0.000320511148221 -0.1075 -0.067962435644 -0.00209192792692 -0.10755 -0.0678735197875 -0.00448024916193 -0.1076 -0.067786768406 -0.00684402177861 -0.10765 -0.067695585448 -0.00918350401785 -0.1077 -0.0676067651931 -0.0114996820378 -0.10775 -0.0675137028746 -0.0137942690086 -0.1078 -0.0674231522339 -0.0160698199048 -0.10785 -0.0673285069355 -0.0183298824259 -0.1079 -0.0672364863575 -0.0205792607626 -0.10795 -0.0671404877492 -0.0228243778201 -0.108 -0.0670472006175 -0.0250737651686 -0.10805 -0.066950029529 -0.0273386970921 -0.1081 -0.0668556373933 -0.0296339645571 -0.10815 -0.0667574387897 -0.0319787968485 -0.1082 -0.0666620724325 -0.0343978613927 -0.10825 -0.066562964868 -0.0369222277392 -0.1083 -0.0664667323786 -0.0395899469963 -0.10835 -0.0663668148872 -0.0424455666621 -0.1084 -0.0662698075462 -0.0455371799654 -0.10845 -0.0661691646742 -0.0489085904484 -0.1085 -0.0660714612629 -0.0525829741817 -0.10855 -0.065970166757 -0.056534610576 -0.1086 -0.0658718367072 -0.0606507190517 -0.10865 -0.0657699562064 -0.0647023912854 -0.1087 -0.0656710619053 -0.0683683962097 -0.10875 -0.0655686549125 -0.0713478238192 -0.1088 -0.0654692533894 -0.0735063916804 -0.10885 -0.0653663747161 -0.0749196188973 -0.1089 -0.0652665188759 -0.0757796947905 -0.10895 -0.0651632196906 -0.0762811980803 -0.109 -0.0650629592047 -0.0765682036608 -0.10905 -0.0649592877918 -0.0767320180302 -0.1091 -0.0648586697432 -0.0768261363285 -0.10915 -0.064754672047 -0.0768808020602 -0.1092 -0.0646537413869 -0.0769129256011 -0.10925 -0.0645494613947 -0.0769319861628 -0.1093 -0.0644482612604 -0.0769433524307 -0.10935 -0.0643437412602 -0.0769501066494 -0.1094 -0.0642423131806 -0.0769540469796 -0.10945 -0.0641375939229 -0.0769562386627 -0.1095 -0.0640359779437 -0.0769573236413 -0.10955 -0.0639310987368 -0.0769576941364 -0.1096 -0.0638293334906 -0.0769575940423 -0.10965 -0.0637243322512 -0.0769571765925 -0.1097 -0.0636224549947 -0.0769565399242 -0.10975 -0.0635173682757 -0.076955747161 -0.1098 -0.0634154149104 -0.0769548398563 -0.10985 -0.0633102779142 -0.0769538452032 -0.1099 -0.0632082829922 -0.0769527815578 -0.10995 -0.0631031295688 -0.0769516610273 -0.11 -0.0630011262813 -0.0769504919611 -0.11005 -0.0628959889076 -0.0769492798244 -0.1101 -0.0627940090559 -0.0769480284383 -0.11015 -0.0626889187967 -0.0769467402126 -0.1102 -0.062586992744 -0.0769454168217 -0.11025 -0.0624819791974 -0.0769440592101 -0.1103 -0.0623801358078 -0.0769426679862 -0.11035 -0.0622752270381 -0.0769412433615 -0.1104 -0.0621734936061 -0.0769397853872 -0.11045 -0.0620687160717 -0.076938293891 -0.1105 -0.0619671182482 -0.0769367686148 -0.11055 -0.0618624967265 -0.0769352091731 -0.1106 -0.061761058444 -0.0769336151236 -0.11065 -0.0616566159565 -0.0769319859523 -0.1107 -0.0615553593547 -0.0769303210967 -0.11075 -0.0614511170943 -0.076928619957 -0.1108 -0.0613500624492 -0.0769268818843 -0.11085 -0.0612460397112 -0.0769251062139 -0.1109 -0.0611452053675 -0.0769232922281 -0.11095 -0.0610414194835 -0.0769214392068 -0.111 -0.060940821791 -0.0769195463726 -0.11105 -0.0608372880673 -0.0769176129541 -0.1111 -0.0607369413211 -0.0769156381182 -0.11115 -0.0606336729808 -0.0769136210427 -0.1112 -0.0605335893637 -0.0769115608406 -0.11125 -0.0604305974901 -0.0769094566378 -0.1113 -0.0603307870186 -0.0769073074932 -0.11135 -0.0602280805022 -0.0769051124792 -0.1114 -0.0601285509737 -0.0769028705999 -0.11145 -0.0600261364606 -0.0769005808716 -0.1115 -0.0599268934031 -0.0768982422424 -0.11155 -0.0598247752458 -0.0768958536702 -0.1116 -0.0597258218695 -0.0768934140454 -0.11165 -0.0596240020786 -0.0768909222659 -0.1117 -0.0595253392274 -0.0768883771631 -0.11175 -0.0594238174226 -0.0768857775723 -0.1118 -0.0593254435245 -0.0768831222648 -0.11185 -0.0592242168846 -0.0768804100121 -0.1119 -0.0591261279006 -0.0768776395237 -0.11195 -0.059025191111 -0.0768748095061 -0.112 -0.0589273804826 -0.0768719186067 -0.11205 -0.0588267256823 -0.0768689654661 -0.1121 -0.0587291842747 -0.0768659486689 -0.11215 -0.0586288009957 -0.0768628667896 -0.1122 -0.058531517035 -0.07685971835 -0.11225 -0.0584313921355 -0.0768565018589 -0.1123 -0.0583343511379 -0.0768532157759 -0.11235 -0.05823446873 -0.0768498585444 -0.1124 -0.0581376534259 -0.0768464285628 -0.11245 -0.058037994792 -0.0768429242109 -0.1125 -0.057941385035 -0.0768393438267 -0.11255 -0.05784192853 -0.0768356857281 -0.1126 -0.0577455011925 -0.0768319481957 -0.11265 -0.0576462221349 -0.0768281294879 -0.1127 -0.0575499509919 -0.0768242278296 -0.11275 -0.0574508215353 -0.0768202414228 -0.1128 -0.0573546771237 -0.07681616844 -0.11285 -0.0572556661049 -0.07681200703 -0.1129 -0.0571596155614 -0.0768077553163 -0.11295 -0.0570606883286 -0.0768034113985 -0.113 -0.0569646952043 -0.0767989733553 -0.11305 -0.056865813413 -0.076794439241 -0.1131 -0.0567698374492 -0.0767898070938 -0.11315 -0.0566709588214 -0.076785074928 -0.1132 -0.0565749556948 -0.0767802407457 -0.11325 -0.0564760337456 -0.0767753025266 -0.1133 -0.0563799547688 -0.0767702582425 -0.11335 -0.0562809384773 -0.0767651058435 -0.1134 -0.0561847302429 -0.0767598432764 -0.11345 -0.0560855636734 -0.076754468468 -0.1135 -0.0559891676483 -0.0767489793455 -0.11355 -0.0558897895079 -0.076743373818 -0.1136 -0.0557931415492 -0.0767376497995 -0.11365 -0.0556934846636 -0.0767318051874 -0.1137 -0.0555965144554 -0.0767258378882 -0.11375 -0.0554965051631 -0.0767197457946 -0.1138 -0.0553991355606 -0.0767135268123 -0.11385 -0.0552986929986 -0.0767071788354 -0.1139 -0.0552008392502 -0.076700699775 -0.11395 -0.055099874512 -0.0766940875327 -0.114 -0.0550014433516 -0.0766873400311 -0.11405 -0.0548998585049 -0.076680455186 -0.1141 -0.0548007470835 -0.0766734309371 -0.11415 -0.0546984340069 -0.0766662652205 -0.1142 -0.0545985286267 -0.076658956 -0.11425 -0.054495367633 -0.0766515012383 -0.1143 -0.0543945422515 -0.076643898929 -0.11435 -0.0542904004629 -0.0766361470668 -0.1144 -0.0541885149235 -0.0766282436804 -0.11445 -0.0540832443377 -0.0766201868021 -0.1145 -0.0539801422555 -0.0766119745008 -0.11455 -0.0538735774368 -0.0766036048524 -0.1146 -0.0537690836743 -0.0765950759717 -0.11465 -0.0536610389895 -0.0765863859825 -0.1147 -0.0535549566275 -0.0765775330498 -0.11475 -0.0534452229224 -0.0765685153495 -0.1148 -0.0533373296086 -0.0765593311007 -0.11485 -0.0532256701929 -0.076549978536 -0.1149 -0.0531157137215 -0.0765404559332 -0.11495 -0.0530018594932 -0.0765307615849 -0.115 -0.0528895524193 -0.0765208938302 -0.11505 -0.0527731959111 -0.0765108510243 -0.1151 -0.0526582089608 -0.0765006315702 -0.11515 -0.0525389970296 -0.076490233889 -0.1152 -0.052420950975 -0.0764796564502 -0.11525 -0.0522984757624 -0.0764688977421 -0.1153 -0.0521769313513 -0.0764579563017 -0.11535 -0.0520507190406 -0.0764468306853 -0.1154 -0.0519251644168 -0.0764355194987 -0.11545 -0.0517946611379 -0.0764240213677 -0.1155 -0.051664496021 -0.0764123349668 -0.11555 -0.051529050046 -0.0764004589899 -0.1156 -0.0513935656534 -0.0763883921793 -0.11565 -0.0512524047178 -0.0763761332972 -0.1157 -0.0511107580791 -0.0763636811528 -0.11575 -0.0509629602193 -0.076351034574 -0.1158 -0.050814140997 -0.0763381924337 -0.11585 -0.050658596697 -0.076325153623 -0.1159 -0.0505013838886 -0.0763119170769 -0.11595 -0.0503367464292 -0.0762984817457 -0.116 -0.0501696512536 -0.0762848466203 -0.11605 -0.0499942708169 -0.0762710107059 -0.1161 -0.049815460471 -0.076256973046 -0.11615 -0.0496272956345 -0.0762427326939 -0.1162 -0.049434490201 -0.0762282887373 -0.11625 -0.0492309874467 -0.0762136402713 -0.1163 -0.0490213185585 -0.0761987864211 -0.11635 -0.0487992458649 -0.0761837263138 -0.1164 -0.048569060006 -0.0761684591011 -0.11645 -0.0483242733856 -0.0761529839329 -0.1165 -0.0480688536353 -0.0761372999767 -0.11655 -0.0477959640278 -0.0761214063904 -0.1166 -0.0475091294262 -0.0761053023436 -0.11665 -0.0472010185564 -0.0760889869892 -0.1167 -0.0468745361923 -0.0760724594809 -0.11675 -0.0465216389995 -0.0760557189472 -0.1168 -0.0461443435479 -0.0760387645081 -0.11685 -0.045733562019 -0.0760215952456 -0.1169 -0.0452900084557 -0.0760042102203 -0.11695 -0.0448030311743 -0.0759866084428 -0.117 -0.0442713871835 -0.0759687888855 -0.11705 -0.0436820317176 -0.0759507504538 -0.1171 -0.0430307093029 -0.0759324919971 -0.11715 -0.0423006331553 -0.0759140122766 -0.1172 -0.0414828065245 -0.0758953099733 -0.11725 -0.0405544826837 -0.0758763836554 -0.1173 -0.0394990837519 -0.0758572317807 -0.11735 -0.038284290396 -0.0758378526609 -0.1174 -0.0368814116176 -0.0758182444613 -0.11745 -0.0352430198963 -0.0757984051575 -0.1175 -0.0333218818566 -0.0757783325302 -0.11755 -0.0310487165401 -0.0757580241167 -0.1176 -0.028352261533 -0.0757374771935 -0.11765 -0.025140663884 -0.0757166887211 -0.1177 -0.0213295946656 -0.075695655313 -0.11775 -0.0168393630772 -0.0756743731654 -0.1178 -0.0116489239337 -0.07565283801 -0.11785 -0.00582690525612 -0.0756310450187 -0.1179 0.000390457600968 -0.0756089887311 -0.11795 0.00659515627967 -0.0755866629241 -0.118 0.0122473257722 -0.0755640604937 -0.11805 0.0168480203979 -0.0755411732711 -0.1181 0.0200815245587 -0.0755179918285 -0.11815 0.0219014431337 -0.0754945052025 -0.1182 0.0224561342659 -0.0754707005718 -0.11825 0.0220013232821 -0.0754465628135 -0.1183 0.0207903679837 -0.0754220739553 -0.11835 0.019048575176 -0.0753972124252 -0.1184 0.0169411157486 -0.075371952092 -0.11845 0.0145981425506 -0.0753462609559 -0.1185 0.0121044978021 -0.0753200994402 -0.11855 0.00952926823182 -0.075293418085 -0.1186 0.00691304474137 -0.0752661545322 -0.11865 0.00429333480047 -0.0752382295299 -0.1187 0.00168823029816 -0.0752095417727 -0.11875 -0.000880961451657 -0.0751799612231 -0.1188 -0.00340790549651 -0.0751493206429 -0.11885 -0.00587995870409 -0.0751174048797 -0.1189 -0.00829719137993 -0.0750839375066 -0.11895 -0.010651772186 -0.075048564207 -0.119 -0.0129473778931 -0.0750108322832 -0.11905 -0.0151789553139 -0.0749701654139 -0.1191 -0.0173523302128 -0.0749258326861 -0.11915 -0.0194642180634 -0.0748769105801 -0.1192 -0.0215219382595 -0.0748222363824 -0.11925 -0.0235235973103 -0.0747603510225 -0.1193 -0.0254778400914 -0.074689428963 -0.11935 -0.0273841388473 -0.074607192108 -0.1194 -0.0292525151883 -0.0745108040908 -0.11945 -0.0310838700755 -0.0743967403412 -0.1195 -0.0328896147821 -0.0742606283764 -0.11955 -0.0346719830031 -0.0740970513323 -0.1196 -0.0364435128714 -0.0738993062331 -0.11965 -0.0382072789344 -0.0736591063499 -0.1197 -0.039976151898 -0.0733662145575 -0.11975 -0.041752858108 -0.073007991264 -0.1198 -0.0435489015615 -0.0725688364564 -0.11985 -0.0453643197835 -0.072029499886 -0.1199 -0.0472061525056 -0.0713662262105 -0.11995 -0.0490678548549 -0.0705496914543 -0.12 -0.0509474507661 -0.0695436716528 -0.12005 -0.0528270664997 -0.0683033590717 -0.1201 -0.0546916983298 -0.0667731966537 -0.12015 -0.0565102998297 -0.0648840157207 -0.1202 -0.0582568846005 -0.0625490878715 -0.12025 -0.0598945552893 -0.0596583292725 -0.1203 -0.0613990576876 -0.0560690709823 -0.12035 -0.0627438026037 -0.0515899627991 -0.1204 -0.0639219512746 -0.045950572715 -0.12045 -0.0649279264357 -0.0387417978343 -0.1205 -0.0657750518604 -0.0293066520413 -0.12055 -0.0664735477027 -0.0166112689619 -0.1206 -0.0670464434034 0.000503212908887 -0.12065 -0.0675078506161 0.0211651227243 -0.1207 -0.0678802387013 0.0385634095219 -0.12075 -0.0681744937085 0.0457048743835 -0.1208 -0.068408627001 0.0464979767031 -0.12085 -0.0685888903917 0.0461425636434 -0.1209 -0.0687289943549 0.0455016853845 -0.12095 -0.068831506675 0.0446552834806 -0.121 -0.0689070641417 0.0435999818707 -0.12105 -0.0689557664567 0.0423532355951 -0.1211 -0.0689862508718 0.0409118485892 -0.12115 -0.0689970421097 0.0392860061077 -0.1212 -0.0689954964132 0.0374951753143 -0.12125 -0.0689791317044 0.035567511437 -0.1213 -0.0689544694907 0.0335142660892 -0.12135 -0.0689183711408 0.0313545554501 -0.1214 -0.0688767994039 0.0291035512232 -0.12145 -0.0688261777491 0.0267780748852 -0.1215 -0.0687720847807 0.0243928602351 -0.12155 -0.0687106464764 0.0219621711168 -0.1216 -0.0686471711762 0.0194986679898 -0.12165 -0.0685775802889 0.0170137439022 -0.1217 -0.0685069883236 0.0145173869448 -0.12175 -0.0684311752461 0.0120181179562 -0.1218 -0.0683551142443 0.00952321850285 -0.12185 -0.0682744876012 0.00703858186471 -0.1219 -0.0681941638956 0.00456904082918 -0.12195 -0.0681097585019 0.00211823268946 -0.122 -0.0680260613669 -0.000311086300415 -0.12205 -0.0679386428149 -0.00271714294838 -0.1221 -0.0678522326948 -0.00509889495889 -0.12215 -0.0677623719075 -0.0074561156355 -0.1222 -0.0676737435073 -0.0097892327801 -0.12225 -0.0675818701904 -0.012099432317 -0.1223 -0.067491397805 -0.014388620274 -0.12235 -0.0673978389303 -0.0166596010726 -0.1224 -0.0673058091394 -0.0189162096717 -0.12245 -0.0672108167346 -0.0211636370797 -0.1225 -0.0671174520484 -0.023408793598 -0.12255 -0.067021223329 -0.0256608587556 -0.1226 -0.0669266993278 -0.0279319331664 -0.12265 -0.0668293913037 -0.0302378655949 -0.1227 -0.0667338491016 -0.0325991932261 -0.12275 -0.0666355892099 -0.0350421552517 -0.1228 -0.0665391445217 -0.0375995978741 -0.12285 -0.0664400383678 -0.0403113657354 -0.1229 -0.0663427881294 -0.0432233490871 -0.12295 -0.0662429251495 -0.0463835493077 -0.123 -0.0661449523548 -0.0498324281037 -0.12305 -0.066044409947 -0.0535837251866 -0.1231 -0.065945787182 -0.0575929993576 -0.12315 -0.0658446337324 -0.061718994153 -0.1232 -0.0657454257675 -0.0657032763745 -0.12325 -0.0656437228694 -0.0692157016513 -0.1233 -0.0655439885537 -0.0719862658909 -0.12335 -0.0654417926238 -0.0739374190193 -0.1234 -0.065341586267 -0.0751871463925 -0.12345 -0.0652389497268 -0.075937269046 -0.1235 -0.0651383221069 -0.0763716802884 -0.12355 -0.0650352942412 -0.0766198095634 -0.1236 -0.0649342933352 -0.0767615821755 -0.12365 -0.0648309209104 -0.0768432442888 -0.1237 -0.0647295924133 -0.0768908206701 -0.12375 -0.0646259201124 -0.0769188559157 -0.1238 -0.0645243078007 -0.0769355219725 -0.12385 -0.0644203785229 -0.0769454608015 -0.1239 -0.0643185244979 -0.0769513495426 -0.12395 -0.064214379554 -0.0769547549575 -0.124 -0.0641123243958 -0.0769566104872 -0.12405 -0.0640080036257 -0.0769574796242 -0.1241 -0.0639057864809 -0.0769577092207 -0.12415 -0.0638013283189 -0.0769575146572 -0.1242 -0.0636989869481 -0.0769570327507 -0.12425 -0.0635944284563 -0.0769563504895 -0.1243 -0.0634919992584 -0.076955524837 -0.12435 -0.0633873761445 -0.0769545926364 -0.1244 -0.0632848941675 -0.0769535787335 -0.12445 -0.0631802407888 -0.0769524993251 -0.1245 -0.0630777397261 -0.0769513656394 -0.12455 -0.0629730890762 -0.0769501849522 -0.1246 -0.062870601244 -0.0769489624233 -0.12465 -0.0627659849212 -0.0769477013005 -0.1247 -0.0626635412179 -0.0769464039062 -0.12475 -0.0625589893768 -0.0769450715946 -0.1248 -0.0624566192266 -0.0769437052958 -0.12485 -0.0623521605141 -0.0769423054382 -0.1249 -0.0622498917988 -0.076940872233 -0.12495 -0.0621455532832 -0.0769394056374 -0.125 -0.0620434122684 -0.0769379054687 -0.12505 -0.0619392193641 -0.0769363714322 -0.1251 -0.0618372306238 -0.0769348031143 -0.12515 -0.0617332070164 -0.0769332000757 -0.1252 -0.0616313933588 -0.0769315617558 -0.12525 -0.0615275609316 -0.0769298876242 -0.1253 -0.0614259433272 -0.0769281770175 -0.12535 -0.0613223220916 -0.0769264293399 -0.1254 -0.061220919605 -0.0769246438488 -0.12545 -0.0611175276335 -0.0769228198953 -0.1255 -0.0610163573582 -0.0769209566702 -0.12555 -0.0609132107209 -0.0769190534757 -0.1256 -0.0608122877173 -0.0769171094429 -0.12565 -0.0607094004212 -0.0769151238261 -0.1257 -0.0606087376579 -0.0769130956993 -0.12575 -0.0605061215905 -0.0769110242677 -0.1258 -0.060405729889 -0.0769089085498 -0.12585 -0.0603033947643 -0.0769067476993 -0.1259 -0.0602032827466 -0.076904540679 -0.12595 -0.0601012360537 -0.0769022865884 -0.126 -0.0600014100918 -0.0768999843341 -0.12605 -0.0598996570448 -0.0768976329587 -0.1261 -0.0598001212108 -0.0768952313113 -0.12615 -0.0596986646993 -0.0768927783751 -0.1262 -0.0595994207164 -0.0768902729409 -0.12625 -0.0594982612567 -0.0768877139299 -0.1263 -0.0593993084501 -0.0768851000736 -0.12635 -0.0592984441365 -0.0768824302293 -0.1264 -0.0591997793846 -0.0768797030679 -0.12645 -0.0590992058387 -0.0768769173815 -0.1265 -0.0590008235207 -0.0768740717796 -0.12655 -0.0589005338374 -0.0768711649878 -0.1266 -0.0588024257771 -0.0768681955542 -0.12665 -0.0587024104662 -0.076865162137 -0.1267 -0.0586045658715 -0.0768620632227 -0.12675 -0.0585048127959 -0.0768588974024 -0.1268 -0.0584072181939 -0.0768556631013 -0.12685 -0.0583077124988 -0.0768523588437 -0.1269 -0.0582103516595 -0.0768489829947 -0.12695 -0.0581110756906 -0.0768455340124 -0.127 -0.0580139295409 -0.076842010203 -0.12705 -0.0579148627557 -0.0768384099603 -0.1271 -0.0578179092841 -0.0768347315335 -0.12715 -0.0577190281467 -0.0768309732544 -0.1272 -0.0576222422886 -0.0768271333175 -0.12725 -0.057523520146 -0.0768232099952 -0.1273 -0.0574268736522 -0.0768192014302 -0.12735 -0.0573282805951 -0.0768151058385 -0.1274 -0.0572317418818 -0.0768109213145 -0.12745 -0.0571332445799 -0.0768066460214 -0.1275 -0.0570367785475 -0.0768022780089 -0.12755 -0.0569383400546 -0.0767978153921 -0.1276 -0.0568419078816 -0.0767932561801 -0.12765 -0.0567434874145 -0.076788598444 -0.1277 -0.0566470463161 -0.0767838401571 -0.12775 -0.0565485989898 -0.0767789793518 -0.1278 -0.0564521019301 -0.0767740139711 -0.12785 -0.0563535784509 -0.076768942014 -0.1279 -0.0562569738154 -0.0767637613981 -0.12795 -0.056158320125 -0.0767584700952 -0.128 -0.0560615513313 -0.076753066003 -0.12805 -0.0559627081832 -0.0767475470716 -0.1281 -0.0558657132253 -0.0767419111848 -0.12815 -0.0557666156974 -0.0767361562774 -0.1282 -0.0556693266193 -0.076730280225 -0.12825 -0.05556990354 -0.0767242809531 -0.1283 -0.0554722458098 -0.076718156336 -0.12835 -0.0553724190805 -0.0767119042969 -0.1284 -0.0552743108629 -0.0767055227144 -0.12845 -0.0551739946728 -0.0766990095157 -0.1285 -0.0550753459746 -0.0766923625902 -0.12855 -0.0549744458709 -0.076685579875 -0.1286 -0.0548751575304 -0.0766786592763 -0.12865 -0.054773569322 -0.0766715987475 -0.1287 -0.0546735318226 -0.0766643962178 -0.12875 -0.0545711402931 -0.0766570496637 -0.1288 -0.0544702323618 -0.0766495570433 -0.12885 -0.0543669097412 -0.0766419163621 -0.1289 -0.0542649966825 -0.0766341256124 -0.12895 -0.0541606008312 -0.0766261828341 -0.129 -0.0540575325471 -0.076618086059 -0.12905 -0.0539519047961 -0.0766098333668 -0.1291 -0.0538475134266 -0.0766014228349 -0.12915 -0.0537404759952 -0.0765928525881 -0.1292 -0.0536345730893 -0.0765841207535 -0.12925 -0.0535259259832 -0.0765752255056 -0.1293 -0.053418299094 -0.0765661650251 -0.12935 -0.0533078163634 -0.07655693754 -0.1294 -0.0531982249314 -0.0765475412895 -0.12945 -0.0530856501363 -0.0765379745597 -0.1295 -0.0529738204877 -0.076528235651 -0.12955 -0.0528588611744 -0.0765183229105 -0.1296 -0.0527444804099 -0.0765082347019 -0.12965 -0.0526268013381 -0.0764979694361 -0.1297 -0.0525095098202 -0.076487525544 -0.12975 -0.0523887246171 -0.0764769015021 -0.1298 -0.0522681066809 -0.0764660958095 -0.12985 -0.052143767483 -0.0764551070095 -0.1299 -0.0520193398632 -0.0764439336699 -0.12995 -0.0518909243655 -0.0764325744028 -0.13 -0.0517621216773 -0.0764210278458 -0.13005 -0.0516290168215 -0.076409292679 -0.1301 -0.0514951732007 -0.0763973676082 -0.13015 -0.0513566544652 -0.0763852513812 -0.1302 -0.0512169801514 -0.0763729427725 -0.13025 -0.0510721850165 -0.0763604405958 -0.1303 -0.0509257362137 -0.0763477436912 -0.13035 -0.0507736298401 -0.0763348509355 -0.1304 -0.0506192695391 -0.0763217612325 -0.13045 -0.0504585999305 -0.0763084735198 -0.1305 -0.0502949464417 -0.0762949867598 -0.13055 -0.0501241851988 -0.0762812999456 -0.1306 -0.0499495437556 -0.0762674120941 -0.13065 -0.0497668068671 -0.0762533222498 -0.1307 -0.0495790775973 -0.0762390294769 -0.13075 -0.0493820181545 -0.0762245328631 -0.1308 -0.0491785705682 -0.0762098315138 -0.13085 -0.0489642314031 -0.0761949245526 -0.1309 -0.0487417307182 -0.0761798111155 -0.13095 -0.0485063388969 -0.0761644903515 -0.131 -0.0482605018688 -0.0761489614181 -0.13105 -0.0479991773422 -0.0761332234778 -0.1311 -0.0477244230583 -0.0761172756948 -0.13115 -0.0474307581744 -0.076101117232 -0.1312 -0.0471196993066 -0.0760847472459 -0.13125 -0.0467851402001 -0.076068164881 -0.1313 -0.0464278269233 -0.0760513692673 -0.13135 -0.0460407445254 -0.0760343595126 -0.1314 -0.0456235168971 -0.076017134697 -0.13145 -0.0451677814047 -0.0759996938658 -0.1315 -0.0446714887673 -0.0759820360239 -0.13155 -0.0441242332861 -0.0759641601238 -0.1316 -0.0435214104666 -0.0759460650609 -0.13165 -0.0428494475105 -0.0759277496597 -0.1317 -0.0420997469605 -0.0759092126651 -0.13175 -0.0412537253518 -0.0758904527272 -0.1318 -0.0402964275757 -0.0758714683907 -0.13185 -0.0392012351425 -0.0758522580738 -0.1319 -0.0379429984737 -0.0758328200561 -0.13195 -0.0364822765882 -0.0758131524528 -0.132 -0.0347779363901 -0.0757932531951 -0.13205 -0.0327711202116 -0.0757731200007 -0.1321 -0.0303980828422 -0.0757527503465 -0.13215 -0.0275758505713 -0.0757321414279 -0.1322 -0.0242195215066 -0.0757112901245 -0.13225 -0.0202376996198 -0.0756901929439 -0.1323 -0.0155678975437 -0.0756688459728 -0.13235 -0.0102006187642 -0.0756472448028 -0.1324 -0.00424864420429 -0.0756253844556 -0.13245 0.00201326686011 -0.0756032592825 -0.1325 0.00812708108405 -0.0755808628505 -0.13255 0.0135524126687 -0.0755581877951 -0.1326 0.0178183953633 -0.0755352256482 -0.13265 0.0206838077496 -0.0755119666101 -0.1327 0.0221553918035 -0.0754883992773 -0.13275 0.0224256688728 -0.0754645102769 -0.1328 0.0217506774678 -0.0754402838148 -0.13285 0.020385203006 -0.075415701065 -0.1329 0.0185332900587 -0.075390739388 -0.13295 0.0163561868779 -0.0753653712741 -0.133 0.0139654589191 -0.075339562958 -0.13305 0.0114469691491 -0.075313272556 -0.1331 0.00885593185882 -0.0752864476091 -0.13315 0.00623760386178 -0.0752590218226 -0.1332 0.00361829033502 -0.0752309108098 -0.13325 0.00102258369564 -0.0752020065554 -0.1333 -0.00153809597465 -0.0751721703242 -0.13335 -0.00405002557148 -0.0751412236386 -0.1334 -0.0065097800326 -0.0751089369451 -0.13345 -0.00890959487728 -0.0750750154559 -0.1335 -0.0112504946346 -0.0750390816195 -0.13355 -0.0135280946606 -0.0750006534756 -0.1336 -0.0157459990762 -0.0749591180555 -0.13365 -0.0179018718638 -0.0749136987169 -0.1337 -0.0200009865124 -0.0748634150957 -0.13375 -0.0220424787139 -0.0748070339819 -0.1338 -0.0240329743114 -0.0747430090824 -0.13385 -0.0259729554748 -0.0746694070877 -0.1339 -0.0278704012707 -0.0745838169167 -0.13395 -0.0297272008982 -0.074483238218 -0.134 -0.0315527425501 -0.0743639443568 -0.13405 -0.0333503125266 -0.0742213139327 -0.1341 -0.0351305746876 -0.0740496235432 -0.13415 -0.0368978970538 -0.0738417927252 -0.1342 -0.0386636568832 -0.0735890699048 -0.13425 -0.0404324177819 -0.0732806454213 -0.1343 -0.042214961566 -0.0729031743144 -0.13435 -0.0440141948239 -0.0724401870818 -0.1344 -0.0458377779632 -0.0718713608397 -0.13445 -0.0476836567582 -0.07117161531 -0.1345 -0.0495522828112 -0.0703099866771 -0.13455 -0.0514319788066 -0.0692482147636 -0.1346 -0.0533113207121 -0.0679389498592 -0.13465 -0.0551653998777 -0.0663234329016 -0.1347 -0.0569699103384 -0.0643284005688 -0.13475 -0.058690018357 -0.0618617557632 -0.1348 -0.0602973113439 -0.0588060877281 -0.13485 -0.0617609108035 -0.0550081108532 -0.1349 -0.0630647664595 -0.0502598240486 -0.13495 -0.0641967608788 -0.0442623795315 -0.135 -0.0651620371048 -0.0365554935556 -0.13505 -0.0659678045515 -0.0263947495642 -0.1351 -0.0666334946672 -0.0126519346826 -0.13515 -0.0671744519376 0.00564208574 -0.1352 -0.0676126751448 0.0263694697007 -0.13525 -0.0679621121799 0.041422369651 -0.1353 -0.0682410801748 0.0462139192855 -0.13535 -0.0684589609392 0.0464458106338 -0.1354 -0.0686294713387 0.0460039427953 -0.13545 -0.0687578527537 0.0453075184262 -0.1355 -0.0688542826406 0.0444069047655 -0.13555 -0.0689211061606 0.043302001438 -0.1356 -0.0689661485897 0.0420052465031 -0.13565 -0.0689898875621 0.0405158610845 -0.1357 -0.0689986426115 0.0388438098712 -0.13575 -0.0689917008947 0.0370166840829 -0.1358 -0.0689744102971 0.0350553898072 -0.13585 -0.0689452866391 0.032973036371 -0.1359 -0.0689090354061 0.0307884868854 -0.13595 -0.0688636607726 0.0285166674504 -0.136 -0.0688134320385 0.0261744985295 -0.13605 -0.0687560066416 0.0237761340298 -0.1361 -0.0686953506638 0.0213358180543 -0.13615 -0.0686288827584 0.0188656091045 -0.1362 -0.0685603541283 0.016376758985 -0.13625 -0.0684870173218 0.0138787205504 -0.1363 -0.068412468867 0.0113798088567 -0.13635 -0.0683338452532 0.00888686182043 -0.1364 -0.0682546301785 0.00640555029283 -0.13645 -0.0681718791048 0.00394035502113 -0.1365 -0.0680889923891 0.00149470257857 -0.13655 -0.0680029692727 -0.000928923237152 -0.1366 -0.0679171477496 -0.00332893803195 -0.13665 -0.067828488541 -0.00570451309019 -0.1367 -0.0677402823016 -0.00805559569207 -0.13675 -0.0676494639268 -0.0103827997118 -0.1368 -0.0675592875432 -0.0126874973024 -0.13685 -0.0674666713579 -0.0149718028721 -0.1369 -0.0673748407751 -0.0172387735834 -0.13695 -0.0672807039153 -0.0194925520979 -0.137 -0.0671874631115 -0.0217387374463 -0.13705 -0.0670920211713 -0.0239847582471 -0.1371 -0.066997561466 -0.0262404829356 -0.13715 -0.0669009849529 -0.0285188837281 -0.1372 -0.0668054590301 -0.0308369260914 -0.13725 -0.0667078853173 -0.0332165093083 -0.1373 -0.0666114174257 -0.0356855001438 -0.13735 -0.0665129594663 -0.038278534898 -0.1374 -0.0664156528613 -0.041037190033 -0.13745 -0.0663164055404 -0.0440084412541 -0.1375 -0.0662183479111 -0.0472395888833 -0.13755 -0.0661183926894 -0.0507665289325 -0.1376 -0.0660196601354 -0.0545915522029 -0.13765 -0.0659190684517 -0.0586489723945 -0.1377 -0.0658197283877 -0.0627676814498 -0.13775 -0.0657185641415 -0.0666627943597 -0.1378 -0.065618677424 -0.0700045299691 -0.13785 -0.0655169987955 -0.0725631303574 -0.1379 -0.0654166212798 -0.0743173638172 -0.13795 -0.0653144820613 -0.0754190830558 -0.138 -0.0652136657366 -0.0760726567965 -0.13805 -0.0651111162975 -0.0764491561349 -0.1381 -0.0650099101067 -0.0766639998909 -0.13815 -0.0649069980907 -0.0767869460082 -0.1382 -0.0648054485221 -0.0768579603007 -0.13825 -0.0647022193452 -0.0768994596171 -0.1383 -0.0646003708489 -0.0769239780316 -0.13835 -0.0644968680471 -0.0769385753998 -0.1384 -0.0643947633221 -0.0769472761003 -0.13845 -0.0642910287822 -0.0769524105024 -0.1385 -0.0641887089579 -0.0769553478767 -0.13855 -0.064084783059 -0.0769569076576 -0.1386 -0.0639822878043 -0.0769575861488 -0.13865 -0.0638782094998 -0.0769576904537 -0.1387 -0.0637755770825 -0.0769574114908 -0.13875 -0.0636713839427 -0.0769568715018 -0.1388 -0.0635686512611 -0.0769561478767 -0.13885 -0.0634643794971 -0.0769552920764 -0.1389 -0.0633615820971 -0.0769543368151 -0.13895 -0.0632572665709 -0.076953304903 -0.139 -0.0631544386481 -0.0769522105275 -0.13905 -0.0630501128654 -0.0769510642805 -0.1391 -0.0629472872489 -0.0769498722912 -0.13915 -0.0628429833342 -0.0769486396753 -0.1392 -0.0627401914522 -0.0769473689033 -0.13925 -0.0626359401053 -0.0769460625134 -0.1393 -0.0625332119336 -0.0769447212501 -0.13935 -0.0624290423707 -0.0769433463745 -0.1394 -0.0623264063682 -0.0769419377888 -0.13945 -0.062222346254 -0.076940496083 -0.1395 -0.0621198292912 -0.0769390207358 -0.13955 -0.0620159046646 -0.0769375119589 -0.1396 -0.0619135319492 -0.0769359690111 -0.13965 -0.0618097671489 -0.0769343918717 -0.1397 -0.0617075621509 -0.0769327796811 -0.13975 -0.0616039797406 -0.0769311322608 -0.1398 -0.0615019641185 -0.0769294486834 -0.13985 -0.0613985848154 -0.0769277286517 -0.1399 -0.0612967783464 -0.0769259711957 -0.13995 -0.0611936209525 -0.0769241759201 -0.14 -0.0610920414657 -0.0769223418237 -0.14005 -0.060989122803 -0.0769204684244 -0.1401 -0.0608877861169 -0.0769185546942 -0.14015 -0.0607851209668 -0.07691660007 -0.1402 -0.0606840408299 -0.0769146034971 -0.14025 -0.0605816418757 -0.0769125643345 -0.1403 -0.0604808299105 -0.0769104814994 -0.14035 -0.0603787076819 -0.0769083542741 -0.1404 -0.0602781733305 -0.0769061815449 -0.14045 -0.0601763361508 -0.0769039625178 -0.1405 -0.0600760866231 -0.0769016960447 -0.14055 -0.0599745405584 -0.0768993812554 -0.1406 -0.0598745807825 -0.076897016964 -0.14065 -0.0597733295926 -0.0768946022239 -0.1407 -0.0596736621662 -0.0768921358077 -0.14075 -0.0595727072566 -0.0768896166924 -0.1408 -0.0594733323985 -0.0768870436061 -0.14085 -0.0593726727709 -0.076884415449 -0.1409 -0.0592735882711 -0.0768817309017 -0.14095 -0.0591732204729 -0.0768789887878 -0.141 -0.059074421641 -0.0768761877379 -0.14105 -0.058974339713 -0.0768733264991 -0.1411 -0.0588758193249 -0.0768704036501 -0.14115 -0.058776014746 -0.0768674178623 -0.1412 -0.0586777629861 -0.0768643676606 -0.14125 -0.0585782246122 -0.076861251642 -0.1413 -0.0584802290079 -0.0768580682764 -0.14135 -0.0583809430027 -0.0768548160879 -0.1414 -0.0582831883529 -0.0768514934913 -0.14145 -0.0581841381135 -0.0768480989393 -0.1415 -0.0580866064094 -0.0768446307916 -0.14155 -0.0579877724799 -0.076841087432 -0.1416 -0.0578904428101 -0.0768374671658 -0.14165 -0.0577918027795 -0.0768337683108 -0.1417 -0.0576946512231 -0.0768299891196 -0.14175 -0.057596179613 -0.076826127847 -0.1418 -0.0574991791178 -0.0768221826948 -0.14185 -0.0574008472485 -0.0768181518586 -0.1419 -0.0573039674843 -0.0768140334917 -0.14195 -0.0572057433166 -0.0768098257346 -0.142 -0.0571089505079 -0.0768055266953 -0.14205 -0.0570107984646 -0.0768011344638 -0.1421 -0.0569140551965 -0.0767966471064 -0.14215 -0.0568159359494 -0.0767920626672 -0.1422 -0.0567192009344 -0.0767873791749 -0.14225 -0.0566210711548 -0.0767825946331 -0.1423 -0.0565242989686 -0.0767777070375 -0.14235 -0.0564261110414 -0.0767727143574 -0.1424 -0.0563292518091 -0.0767676145602 -0.14245 -0.0562309534903 -0.0767624055863 -0.1425 -0.0561339525178 -0.0767570853806 -0.14255 -0.0560354865414 -0.0767516518607 -0.1426 -0.0559382838919 -0.076746102954 -0.14265 -0.055839587508 -0.0767404365617 -0.1427 -0.0557421174977 -0.0767346505998 -0.14275 -0.0556431219265 -0.076728742959 -0.1428 -0.0555453125392 -0.0767227115499 -0.14285 -0.0554459423409 -0.0767165542603 -0.1429 -0.0553477145435 -0.0767102690011 -0.14295 -0.0552478868726 -0.0767038536634 -0.143 -0.0551491538039 -0.076697306165 -0.14305 -0.0550487775324 -0.0766906244063 -0.1431 -0.0549494435581 -0.076683806318 -0.14315 -0.0548484182508 -0.0766768498164 -0.1432 -0.0547483778474 -0.0766697528505 -0.14325 -0.0546465925468 -0.0766625133592 -0.1433 -0.0545457289803 -0.076655129317 -0.14335 -0.0544430607697 -0.076647598691 -0.1434 -0.0543412445331 -0.0766399194862 -0.14345 -0.0542375568385 -0.076632089704 -0.1435 -0.054134643801 -0.0766241073852 -0.14355 -0.0540297843671 -0.0766159705707 -0.1436 -0.0539256135614 -0.0766076773426 -0.14365 -0.0538194120336 -0.0765992257873 -0.1437 -0.053713803011 -0.0765906140332 -0.14375 -0.0536060680388 -0.0765818402165 -0.1438 -0.0534988176921 -0.0765729025162 -0.14385 -0.0533893334401 -0.076563799122 -0.1439 -0.0532802121697 -0.0765545282678 -0.14395 -0.0531687340997 -0.076545088202 -0.144 -0.053057481164 -0.0765354772168 -0.14405 -0.0529437309024 -0.0765256936223 -0.1441 -0.0528300487483 -0.076515735772 -0.14415 -0.052713707815 -0.0765056020397 -0.1442 -0.0525972551257 -0.0764952908432 -0.14425 -0.0524779572148 -0.0764848006235 -0.1443 -0.0523583403289 -0.0764741298644 -0.14435 -0.0522356617524 -0.0764632770751 -0.1444 -0.0521124240043 -0.0764522408063 -0.14445 -0.0519858717835 -0.0764410196362 -0.1445 -0.0518584801704 -0.0764296121843 -0.14455 -0.0517274770788 -0.0764180170987 -0.1446 -0.0515953054487 -0.0764062330664 -0.14465 -0.0514591710724 -0.076394258804 -0.1447 -0.0513214787487 -0.0763820930659 -0.14475 -0.0511794053124 -0.0763697346376 -0.1448 -0.0510353096803 -0.0763571823386 -0.14485 -0.0508863308838 -0.0763444350197 -0.1449 -0.0507347718878 -0.0763314915633 -0.14495 -0.0505777223559 -0.0763183508837 -0.145 -0.0504174160482 -0.0763050119234 -0.14505 -0.0502508779718 -0.0762914736544 -0.1451 -0.0500802550517 -0.0762777350742 -0.14515 -0.0499024871751 -0.0762637952093 -0.1452 -0.049719610675 -0.0762496531069 -0.14525 -0.0495284525849 -0.0762353078402 -0.1453 -0.0493309062002 -0.0762207584985 -0.14535 -0.0491236475552 -0.0762060041957 -0.1454 -0.048908381956 -0.0761910440551 -0.14545 -0.0486815811781 -0.0761758772201 -0.1455 -0.0484446992449 -0.0761605028383 -0.14555 -0.0481939280728 -0.0761449200729 -0.1456 -0.0479303797469 -0.076129128083 -0.14565 -0.0476498570566 -0.0761131260371 -0.1457 -0.0473529978777 -0.0760969130924 -0.14575 -0.0470350548806 -0.0760804884075 -0.1458 -0.0466959948324 -0.0760638511187 -0.14585 -0.0463302781489 -0.0760470003561 -0.1459 -0.0459369011455 -0.0760299352156 -0.14595 -0.0455091598178 -0.0760126547743 -0.146 -0.0450446148019 -0.0759951580623 -0.14605 -0.0445348128706 -0.0759774440778 -0.1461 -0.0439751399888 -0.0759595117531 -0.14615 -0.0433544551185 -0.0759413599727 -0.1462 -0.0426647722348 -0.0759229875357 -0.14625 -0.0418907297615 -0.0759043931696 -0.1463 -0.0410190037326 -0.0758855754926 -0.14635 -0.0400274912766 -0.0758665330252 -0.1464 -0.0388943113657 -0.0758472641444 -0.14645 -0.037586549282 -0.0758277670968 -0.1465 -0.0360687198559 -0.0758080399453 -0.14655 -0.0342910654483 -0.0757880805758 -0.1466 -0.0321977858286 -0.0757678866401 -0.14665 -0.0297158936245 -0.075747455553 -0.1467 -0.0267656342292 -0.0757267844256 -0.14675 -0.0232549477203 -0.0757058700538 -0.1468 -0.0191014552497 -0.0756847088348 -0.14685 -0.0142477233834 -0.0756632967423 -0.1469 -0.00871422277141 -0.0756416292213 -0.14695 -0.00264706962954 -0.0756197011385 -0.147 0.00362504674352 -0.0755975066474 -0.14705 0.00961450287943 -0.075575039097 -0.1471 0.0147774294736 -0.0755522908495 -0.14715 0.0186958991208 -0.0755292531239 -0.1472 0.0211907256219 -0.0755059157286 -0.14725 0.0223307835884 -0.075482266798 -0.1473 0.0223307002344 -0.0754582923756 -0.14735 0.0214560371083 -0.0754339759578 -0.1474 0.0199462526297 -0.0754092978111 -0.14745 0.0179982828074 -0.0753842341611 -0.1475 0.0157555277858 -0.0753587560253 -0.14755 0.0133260812635 -0.0753328277524 -0.1476 0.0107830176386 -0.0753064049864 -0.14765 0.00818252112125 -0.0752794320562 -0.1477 0.0055604628052 -0.0752518384461 -0.14775 0.00294652393765 -0.07522353427 -0.1478 0.00035761630299 -0.0751944043304 -0.14785 -0.00219029852002 -0.0751643005987 -0.1479 -0.00469033194446 -0.0751330326038 -0.14795 -0.00713393677499 -0.0751003554541 -0.148 -0.00951973765536 -0.0750659548368 -0.14805 -0.0118433370616 -0.0750294285316 -0.1481 -0.0141064973582 -0.0749902635488 -0.14815 -0.0163072531836 -0.0749478081087 -0.1482 -0.0184492916824 -0.0749012371812 -0.14825 -0.0205322632648 -0.0748495103022 -0.1483 -0.0225612765612 -0.0747913197681 -0.14835 -0.0245373364252 -0.0747250271625 -0.1484 -0.0264668868382 -0.0746485853829 -0.14845 -0.0283523094795 -0.0745594429707 -0.1485 -0.030201448931 -0.0744544265032 -0.14855 -0.0320181086701 -0.0743295961101 -0.1486 -0.0338114976569 -0.0741800677286 -0.14865 -0.0355866660951 -0.0739997945071 -0.1487 -0.0373538147971 -0.073781297669 -0.14875 -0.0391186033509 -0.0735153351389 -0.1488 -0.0408912395764 -0.0731904930786 -0.14885 -0.042676555514 -0.0727926820978 -0.1489 -0.0444827522756 -0.0723045148915 -0.14895 -0.0463111152676 -0.0717045360341 -0.149 -0.0481643271621 -0.0709662657094 -0.14905 -0.0500358593562 -0.0700570067351 -0.1491 -0.0519181399504 -0.0689363441425 -0.14915 -0.0537923095654 -0.0675542331306 -0.1492 -0.0556374413912 -0.0658485089626 -0.14925 -0.0574222945126 -0.063741530062 -0.1493 -0.059117237458 -0.0611354088048 -0.14935 -0.0606888552731 -0.0579047250779 -0.1494 -0.062113688759 -0.0538843672093 -0.14945 -0.0633726354238 -0.0488473689144 -0.1495 -0.0644620379285 -0.0424618999831 -0.14955 -0.0653839060719 -0.0342081897947 -0.1496 -0.0661528260563 -0.0232453822295 -0.14965 -0.0667835466725 -0.00837638997681 -0.1497 -0.0672972300987 0.0109855984211 -0.14975 -0.0677100114103 0.0311808432288 -0.1498 -0.0680409019345 0.0435174896342 -0.14985 -0.0683020247287 0.0464480748396 -0.1499 -0.0685077412521 0.0463651629182 -0.14995 -0.0686656721783 0.0458480907799 -0.15 -0.0687861759732 0.0450998547974 -0.15005 -0.0688735125764 0.0441447268748 -0.1501 -0.0689352831908 0.0429911929841 -0.15015 -0.0689735390151 0.0416441837727 -0.1502 -0.0689941059464 0.0401074748414 -0.15025 -0.0689976270931 0.0383904468437 -0.1503 -0.068988790524 0.0365284537686 -0.15035 -0.0689673330636 0.0345340793292 -0.1504 -0.0689371987175 0.032424011899 -0.15045 -0.0688975275413 0.0302154071396 -0.1505 -0.0688517640335 0.0279239589208 -0.15055 -0.0687986459768 0.0255659277875 -0.1506 -0.0687412742705 0.0231553841818 -0.15065 -0.0686781103226 0.0207061951126 -0.1507 -0.0686120139025 0.0182300385748 -0.15075 -0.0685412539736 0.0157378815267 -0.1508 -0.0684685183963 0.0132387215249 -0.15085 -0.0683919410463 0.0107406348241 -0.1509 -0.068314085669 0.00825002462863 -0.15095 -0.0682329909837 0.00577236072448 -0.151 -0.0681511301466 0.00331174688582 -0.15105 -0.0680664748953 0.000871444075892 -0.1511 -0.0679814315706 -0.00154637599116 -0.15115 -0.0678939249838 -0.00394026580967 -0.1512 -0.0678063116465 -0.00630965516475 -0.15125 -0.0677164838048 -0.0086546161961 -0.1513 -0.0676267603428 -0.0109759962341 -0.15135 -0.0675350112684 -0.0132753141657 -0.1514 -0.0674435266375 -0.0155549431262 -0.15145 -0.0673501616703 -0.0178181686459 -0.1515 -0.0672571839551 -0.0200694983846 -0.15155 -0.0671624393178 -0.0223149355448 -0.1516 -0.0670681774952 -0.0245624961662 -0.15165 -0.0669722388223 -0.0268227583532 -0.1517 -0.0668768585405 -0.0291096503103 -0.15175 -0.0667798743345 -0.0314412993347 -0.1518 -0.0666835093967 -0.0338410589377 -0.15185 -0.0665856008229 -0.0363384672558 -0.1519 -0.0664883615433 -0.0389699875274 -0.15195 -0.0663896295693 -0.0417788280573 -0.152 -0.0662916088803 -0.0448127456737 -0.15205 -0.0661921394974 -0.0481175737788 -0.1521 -0.0660934174089 -0.0517231862202 -0.15215 -0.0659932854426 -0.0556180730864 -0.1522 -0.0658939323035 -0.0597126062952 -0.15225 -0.0657932042076 -0.0638048815231 -0.1523 -0.0656932830985 -0.067587972392 -0.15235 -0.0655920190008 -0.0707427039486 -0.1524 -0.06549158748 -0.0730875848155 -0.15245 -0.0653898426732 -0.0746550966346 -0.1525 -0.0652889540515 -0.0756223375554 -0.15255 -0.0651867800813 -0.0761904687378 -0.1526 -0.0650854843489 -0.0765164393799 -0.15265 -0.0649829298042 -0.0767024169135 -0.1527 -0.0648812743024 -0.0768090544048 -0.15275 -0.0647783853811 -0.0768708284657 -0.1528 -0.0646764152761 -0.0769070364436 -0.15285 -0.0645732361816 -0.0769284801282 -0.1529 -0.0644709947941 -0.0769412605495 -0.15295 -0.0643675680054 -0.0769488689613 -0.153 -0.0642650970283 -0.0769533344227 -0.15305 -0.0641614634726 -0.076955855116 -0.1531 -0.0640588031051 -0.0769571498733 -0.15315 -0.0639550022595 -0.0769576571136 -0.1532 -0.0638521912831 -0.0769576477233 -0.15325 -0.0637482612301 -0.076957292265 -0.1533 -0.0636453370481 -0.0769566986722 -0.15335 -0.063541314504 -0.0769559372133 -0.1534 -0.063438313162 -0.0769550529373 -0.15345 -0.0633342334908 -0.0769540763892 -0.1535 -0.0632311896843 -0.0769530269726 -0.15355 -0.0631270868982 -0.0769519186624 -0.1536 -0.063024033964 -0.0769507598501 -0.15365 -0.0629199407049 -0.0769495572607 -0.1537 -0.0628169105937 -0.076948314324 -0.15375 -0.0627128580971 -0.0769470344485 -0.1538 -0.0626098813285 -0.0769457187236 -0.15385 -0.0625058993708 -0.0769443689739 -0.1539 -0.0624030049738 -0.0769429851348 -0.15395 -0.0622991218061 -0.0769415682393 -0.154 -0.0621963372483 -0.076940117628 -0.15405 -0.0620925795238 -0.0769386339159 -0.1541 -0.0619899306374 -0.0769371161221 -0.15415 -0.0618863233362 -0.0769355646248 -0.1542 -0.0617838342427 -0.0769339782598 -0.15425 -0.0616804005966 -0.076932357257 -0.1543 -0.0615780936326 -0.0769307003406 -0.15435 -0.0614748550529 -0.0769290076365 -0.1544 -0.0613727506995 -0.0769272777953 -0.15445 -0.0612697267079 -0.0769255108596 -0.1545 -0.061167843523 -0.0769237054273 -0.15455 -0.0610650516856 -0.0769218614668 -0.1546 -0.06096340624 -0.076919977534 -0.15465 -0.0608608621046 -0.0769180535269 -0.1547 -0.0607594689204 -0.0769160879645 -0.15475 -0.060657185957 -0.0769140806749 -0.1548 -0.0605560574501 -0.0769120301423 -0.15485 -0.0604540469948 -0.0769099361237 -0.1549 -0.0603531934202 -0.0769077970689 -0.15495 -0.060251464622 -0.0769056126617 -0.155 -0.060150894022 -0.0769033813173 -0.15505 -0.060049453792 -0.0769011026436 -0.1551 -0.0599491719461 -0.0768987750197 -0.15515 -0.0598480249077 -0.076896397976 -0.1552 -0.0597480352828 -0.0768939698536 -0.15525 -0.0596471837224 -0.0768914901033 -0.1553 -0.0595474874237 -0.0768889570269 -0.15535 -0.0594469312415 -0.0768863699936 -0.1554 -0.0593475269639 -0.0768837272644 -0.15545 -0.0592472636254 -0.0768810281256 -0.1555 -0.0591481476038 -0.0768782707959 -0.15555 -0.0590481720883 -0.0768754544777 -0.1556 -0.0589493380444 -0.076872577346 -0.15565 -0.0588496427898 -0.0768696385193 -0.1557 -0.0587510818746 -0.076866636128 -0.15575 -0.0586516567182 -0.0768635692063 -0.1558 -0.0585533574509 -0.0768604358398 -0.15585 -0.0584541895656 -0.0768572349793 -0.1559 -0.0583561377658 -0.0768539646652 -0.15595 -0.058257211587 -0.0768506237661 -0.156 -0.0581593902961 -0.0768472102778 -0.15605 -0.0580606874375 -0.0768437229883 -0.1561 -0.0579630768304 -0.0768401598496 -0.15615 -0.057864575992 -0.0768365195711 -0.1562 -0.0577671532777 -0.076832800063 -0.15625 -0.0576688301361 -0.0768289999592 -0.1563 -0.0575715694379 -0.0768251171296 -0.15635 -0.0574733965181 -0.0768211501361 -0.1564 -0.0573762687382 -0.0768170968108 -0.15645 -0.0572782152694 -0.076812955647 -0.1565 -0.0571811879319 -0.0768087244423 -0.15655 -0.0570832196749 -0.0768044016257 -0.1566 -0.0569862567372 -0.0767999849635 -0.15665 -0.0568883357822 -0.0767954728254 -0.1567 -0.0567913974218 -0.0767908629503 -0.15675 -0.0566934819588 -0.0767861536536 -0.1568 -0.0565965243199 -0.0767813426512 -0.15685 -0.0564985683614 -0.0767764282098 -0.1569 -0.0564015432569 -0.0767714080273 -0.15695 -0.0563034963206 -0.0767662803278 -0.157 -0.0562063508907 -0.0767610427959 -0.15705 -0.0561081576273 -0.0767556936192 -0.1571 -0.0560108339334 -0.0767502304745 -0.15715 -0.0559124336857 -0.0767446515192 -0.1572 -0.0558148682373 -0.0767389544274 -0.15725 -0.055716194534 -0.076733137333 -0.1573 -0.0556183177394 -0.0767271979132 -0.15735 -0.0555192976946 -0.0767211342852 -0.1574 -0.0554210332086 -0.0767149441355 -0.15745 -0.0553215868186 -0.0767086255714 -0.1575 -0.0552228507855 -0.0767021762947 -0.15755 -0.0551228901093 -0.0766955944091 -0.1576 -0.0550235902713 -0.0766888776373 -0.15765 -0.0549230184602 -0.0766820240866 -0.1577 -0.0548230531023 -0.0766750315058 -0.15775 -0.054721763257 -0.0766678980123 -0.1578 -0.0546210199709 -0.0766606213876 -0.15785 -0.0545188937974 -0.0766531997659 -0.1579 -0.0544172480154 -0.0766456309667 -0.15795 -0.0543141542278 -0.0766379131469 -0.158 -0.0542114674819 -0.0766300441693 -0.15805 -0.0541072599028 -0.076622022219 -0.1581 -0.0540033777532 -0.076613845207 -0.15815 -0.0538978930539 -0.0766055113528 -0.1582 -0.0537926426179 -0.076597018621 -0.15825 -0.0536856976119 -0.0765883652708 -0.1583 -0.0535788845978 -0.076579549324 -0.15835 -0.0534702729865 -0.0765705690841 -0.1584 -0.0533616781189 -0.0765614226338 -0.15845 -0.0532511665618 -0.0765521083254 -0.1585 -0.0531405412558 -0.0765426243071 -0.15855 -0.0530278646011 -0.076532968984 -0.1586 -0.052914925698 -0.076523140572 -0.15865 -0.0527997811645 -0.0765131375321 -0.1587 -0.0526842044895 -0.0765029581501 -0.15875 -0.0525662445226 -0.076492600946 -0.1588 -0.0524476569549 -0.0764820642784 -0.15885 -0.0523264804096 -0.0764713467284 -0.1589 -0.0522044500574 -0.0764604467279 -0.15895 -0.0520795912322 -0.0764493629197 -0.159 -0.051953615173 -0.0764380938103 -0.15905 -0.0518245300759 -0.0764266381066 -0.1591 -0.0516940189402 -0.0764149943891 -0.15915 -0.0515600679553 -0.0764031614276 -0.1592 -0.0514243263977 -0.0763911378758 -0.15925 -0.051284752225 -0.0763789225666 -0.1593 -0.051142953954 -0.0763665142259 -0.15935 -0.0509968532822 -0.0763539117478 -0.1594 -0.0508480088408 -0.076341113927 -0.15945 -0.0506942956151 -0.0763281197164 -0.1595 -0.0505372103926 -0.0763149279775 -0.15955 -0.0503745676875 -0.0763015377187 -0.1596 -0.0502077865987 -0.0762879478625 -0.15965 -0.0500346028362 -0.0762741574683 -0.1597 -0.0498563365724 -0.0762601655158 -0.15975 -0.0496706199783 -0.0762459711095 -0.1598 -0.0494786454432 -0.0762315732782 -0.15985 -0.0492779077713 -0.0762169711648 -0.1599 -0.0490694318035 -0.0762021638405 -0.15995 -0.0488505280171 -0.0761871504779 -0.16 -0.0486219980573 -0.0761719301793 -0.16005 -0.0483809018246 -0.0761565021375 -0.1601 -0.048127738594 -0.076140865476 -0.16015 -0.0478592225892 -0.0761250193939 -0.1602 -0.0475754359921 -0.0761089630212 -0.16025 -0.0472726082576 -0.0760926955508 -0.1603 -0.0469502350028 -0.0760762161024 -0.16035 -0.0466038533207 -0.0760595238434 -0.1604 -0.0462321166555 -0.0760426178648 -0.16045 -0.0458295532557 -0.0760254972879 -0.1605 -0.0453935804017 -0.0760081611499 -0.16055 -0.0449172242416 -0.0759906085008 -0.1606 -0.0443960450222 -0.0759728382965 -0.16065 -0.0438207811415 -0.0759548494828 -0.1607 -0.0431841368058 -0.0759366408996 -0.16075 -0.0424732869524 -0.0759182113511 -0.1608 -0.0416764455777 -0.0758995595165 -0.16085 -0.0407751276997 -0.0758806840108 -0.1609 -0.0397503706951 -0.0758615832995 -0.16095 -0.0385746053935 -0.0758422557466 -0.161 -0.0372173795542 -0.0758226995358 -0.16105 -0.0356367316642 -0.0758029127033 -0.1611 -0.0337844650733 -0.0757828930617 -0.16115 -0.0315974614622 -0.0757626382201 -0.1612 -0.0290037898209 -0.0757421455042 -0.16125 -0.0259169224259 -0.0757214119617 -0.1613 -0.0222486672351 -0.0757004342783 -0.16135 -0.0179170680326 -0.0756792087596 -0.1614 -0.0128828433726 -0.0756577312397 -0.16145 -0.00719017357054 -0.0756359970328 -0.1615 -0.0010321269124 -0.0756140008228 -0.16155 0.00521952818372 -0.0755917365773 -0.1616 0.0110450866101 -0.0755691973985 -0.16165 0.0159194862738 -0.0755463753809 -0.1617 0.0194761842741 -0.0755232613973 -0.16175 0.021607919072 -0.0754998448623 -0.1618 0.0224289387915 -0.0754761134054 -0.16185 0.0221788710524 -0.0754520524707 -0.1619 0.0211182283098 -0.0754276447863 -0.16195 0.0194795878475 -0.075402869671 -0.162 0.0174426973046 -0.0753777021252 -0.16205 0.0151437791006 -0.0753521116097 -0.1621 0.0126780829416 -0.0753260604408 -0.16215 0.0101164965922 -0.0752995016286 -0.1622 0.00750656166523 -0.0752723760457 -0.16225 0.0048850718583 -0.0752446086656 -0.1623 0.00227528451206 -0.0752161037 -0.16235 -0.000303435679957 -0.0751867382797 -0.1624 -0.00284046451568 -0.0751563544366 -0.16245 -0.00532570849084 -0.0751247489207 -0.1625 -0.00775540107191 -0.0750916604997 -0.16255 -0.0101245745437 -0.0750567541165 -0.1626 -0.0124333126564 -0.0750196013595 -0.16265 -0.0146795860022 -0.0749796563575 -0.1627 -0.0168657538337 -0.0749362262291 -0.16275 -0.0189916233338 -0.0748884347645 -0.1628 -0.0210611007946 -0.0748351779597 -0.16285 -0.0230753957265 -0.0747750694131 -0.1629 -0.0250397518146 -0.0747063734112 -0.16295 -0.0269567290891 -0.0746269227181 -0.163 -0.0288329482469 -0.0745340176978 -0.16305 -0.0306723857291 -0.0744243022789 -0.1631 -0.0324830688949 -0.0742936115685 -0.16315 -0.0342703242032 -0.0741367843521 -0.1632 -0.0360433652553 -0.0739474324824 -0.16325 -0.037808434787 -0.0737176569031 -0.1633 -0.0395752146752 -0.0734376979566 -0.16335 -0.0413497730048 -0.0730955042333 -0.1634 -0.0431406868398 -0.0726762006588 -0.16345 -0.044951665723 -0.072161431083 -0.1635 -0.0467872634225 -0.0715285441803 -0.16355 -0.0486451134243 -0.0707495815898 -0.1636 -0.050521317186 -0.0697900134673 -0.16365 -0.0524026671646 -0.0686071436739 -0.1637 -0.0542725255979 -0.0671480680702 -0.16375 -0.0561043625382 -0.0653469955526 -0.1638 -0.0578698193926 -0.0631215942924 -0.16385 -0.0595351002353 -0.0603677126064 -0.1639 -0.0610717098936 -0.0569511366397 -0.16395 -0.0624542520112 -0.0526935072833 -0.164 -0.0636702913969 -0.0473461348236 -0.16405 -0.0647150091802 -0.0405387954492 -0.1641 -0.0655966933241 -0.031682967389 -0.16415 -0.0663275289009 -0.0198352171445 -0.1642 -0.0669269305907 -0.00378080067718 -0.16425 -0.0674121916644 0.0164267935201 -0.1643 -0.0678030243926 0.0354216141649 -0.16435 -0.0681139519291 0.0449279428122 -0.1644 -0.0683604042563 0.0465144987135 -0.16445 -0.0685522440805 0.0462569648319 -0.1645 -0.0687004980556 0.0456709764767 -0.16455 -0.0688111936959 0.0448711987214 -0.1646 -0.0688921511862 0.0438620120372 -0.16465 -0.0689467972605 0.0426592489302 -0.1647 -0.0689808576694 0.0412617470865 -0.16475 -0.0689960929636 0.0396775507955 -0.1648 -0.068996890686 0.0379203806655 -0.16485 -0.0689839449276 0.0360232359043 -0.1649 -0.0689607764555 0.0339969572476 -0.16495 -0.0689273828203 0.031860056946 -0.165 -0.0688867091316 0.0296283628069 -0.16505 -0.0688382867518 0.0273183542206 -0.1651 -0.0687846687265 0.0249453789864 -0.16515 -0.0687250676492 0.0225236939932 -0.1652 -0.0686617638189 0.0200664728386 -0.16525 -0.0685937483116 0.017585290677 -0.1653 -0.068523108512 0.0150905560642 -0.16535 -0.0684486798763 0.0125910483616 -0.1654 -0.0683724115872 0.0100943876896 -0.16545 -0.0682930290769 0.00760673508037 -0.1655 -0.0682123815039 0.00513319067376 -0.16555 -0.0681291163091 0.00267763505451 -0.1656 -0.0680450096015 0.00024303291922 -0.16565 -0.0679586535667 -0.00216863421459 -0.1657 -0.0678717704906 -0.00455615831393 -0.16575 -0.0677829135547 -0.00691913254281 -0.1658 -0.0676937650033 -0.00925783722022 -0.16585 -0.0676028506866 -0.0115732816876 -0.1659 -0.0675118227324 -0.0138672036806 -0.16595 -0.0674191880691 -0.0161421870148 -0.166 -0.0673265758794 -0.0184018147035 -0.16605 -0.0672324802524 -0.0206509364126 -0.1661 -0.0671385126148 -0.0228960336551 -0.16615 -0.0670431586232 -0.0251457147423 -0.1662 -0.0669480157236 -0.0274113530705 -0.16625 -0.0668515643375 -0.0297078661678 -0.1663 -0.0667553906726 -0.0320546404238 -0.16635 -0.0666579722431 -0.0344765329114 -0.1664 -0.0665608860242 -0.03700482943 -0.16645 -0.0664626083179 -0.0396778035045 -0.1665 -0.06636470833 -0.0425401791552 -0.16655 -0.0662656623847 -0.0456400681373 -0.1666 -0.0661670329927 -0.0490209252024 -0.16665 -0.0660672974034 -0.0527048741811 -0.1667 -0.0659680122214 -0.0566640390758 -0.16675 -0.0658676562778 -0.0607822493265 -0.1668 -0.0657677808491 -0.0648268675828 -0.16685 -0.0656668668267 -0.0684751117448 -0.1669 -0.0655664605849 -0.0714293018851 -0.16695 -0.0654650454241 -0.0735620187182 -0.167 -0.0653641631302 -0.0749544119373 -0.16705 -0.0652622996631 -0.0758002759518 -0.1671 -0.0651609924498 -0.0762930363199 -0.16715 -0.065058730288 -0.0765749560107 -0.1672 -0.0649570464135 -0.0767358829637 -0.16725 -0.0648544325882 -0.0768283701055 -0.1673 -0.0647524179785 -0.0768821084196 -0.16735 -0.0646494973955 -0.0769136981074 -0.1674 -0.0645471960231 -0.0769324464544 -0.16745 -0.0644440117777 -0.0769436270621 -0.1675 -0.0643414659201 -0.0769502688349 -0.16755 -0.0642380595023 -0.0769541398999 -0.1676 -0.0641353099013 -0.0769562880548 -0.16765 -0.0640317213194 -0.0769573452297 -0.1677 -0.0639288072756 -0.0769576975353 -0.16775 -0.0638250751258 -0.0769575853539 -0.1678 -0.0637220345488 -0.0769571596066 -0.16785 -0.0636181960521 -0.0769565171585 -0.1679 -0.0635150654875 -0.0769557201742 -0.16795 -0.0634111565093 -0.0769548097513 -0.168 -0.0633079711522 -0.0769538126369 -0.16805 -0.0632040262086 -0.0769527470433 -0.1681 -0.0631008199017 -0.0769516248387 -0.16815 -0.0629968721481 -0.0769504543524 -0.1682 -0.0628936773606 -0.0769492409005 -0.16825 -0.0627897585615 -0.076947988333 -0.1683 -0.0626866063499 -0.0769466989532 -0.16835 -0.0625827468314 -0.0769453744831 -0.1684 -0.062479666784 -0.0769440157834 -0.16845 -0.0623758953718 -0.0769426235152 -0.1685 -0.0622729155425 -0.0769411978201 -0.16855 -0.0621692594917 -0.0769397388019 -0.1686 -0.0620664063266 -0.0769382462275 -0.16865 -0.0619628912474 -0.0769367198889 -0.1687 -0.0618601895101 -0.0769351593468 -0.16875 -0.061756839293 -0.0769335642051 -0.1688 -0.0616543119907 -0.0769319339022 -0.16885 -0.0615511487327 -0.0769302679178 -0.1689 -0.0614488170426 -0.0769285656093 -0.16895 -0.0613458609757 -0.0769268263661 -0.169 -0.0612437441763 -0.0769250494852 -0.16905 -0.0611410136008 -0.0769232342831 -0.1691 -0.0610391290059 -0.0769213800057 -0.16915 -0.0609366402256 -0.076919485906 -0.1692 -0.0608350031227 -0.0769175511822 -0.16925 -0.0607327703859 -0.0769155750284 -0.1693 -0.0606313939778 -0.076913556595 -0.16935 -0.0605294294201 -0.0769114950192 -0.1694 -0.0604283247694 -0.0769093894025 -0.16945 -0.0603266383589 -0.0769072388252 -0.1695 -0.0602258143342 -0.0769050423378 -0.16955 -0.0601244138195 -0.0769027989632 -0.1696 -0.0600238770446 -0.0769005076984 -0.16965 -0.059922767904 -0.0768981675079 -0.1697 -0.0598225227078 -0.0768957773324 -0.16975 -0.059721708101 -0.0768933360768 -0.1698 -0.0596217564699 -0.0768908426233 -0.16985 -0.0595212371896 -0.0768882958161 -0.1699 -0.0594215787181 -0.0768856944769 -0.16995 -0.0593213531406 -0.0768830373878 -0.17 -0.0592219849816 -0.076880323308 -0.17005 -0.0591220490154 -0.0768775509568 -0.1701 -0.0590229658277 -0.0768747190295 -0.17015 -0.0589233128607 -0.0768718261821 -0.1702 -0.0588245067551 -0.076868871045 -0.17025 -0.0587251275983 -0.0768658522105 -0.1703 -0.0586265880779 -0.0768627682439 -0.17035 -0.0585274709021 -0.0768596176738 -0.1704 -0.0584291847954 -0.0768563990005 -0.17045 -0.0583303150607 -0.0768531106895 -0.1705 -0.0582322664479 -0.0768497511768 -0.17055 -0.0581336268267 -0.076846318866 -0.1706 -0.0580357969576 -0.0768428121298 -0.17065 -0.0579373672446 -0.0768392293112 -0.1707 -0.0578397344399 -0.0768355687216 -0.17075 -0.0577414914468 -0.0768318286459 -0.1708 -0.0576440309881 -0.0768280073365 -0.17085 -0.0575459484269 -0.0768241030224 -0.1709 -0.0574486324291 -0.0768201139 -0.17095 -0.0573506807721 -0.0768160381456 -0.171 -0.0572534780307 -0.0768118739027 -0.17105 -0.0571556243466 -0.0768076192984 -0.1711 -0.0570585001653 -0.0768032724273 -0.17115 -0.0569607079339 -0.0767988313714 -0.1712 -0.0568636239203 -0.0767942941807 -0.17125 -0.0567658528089 -0.0767896588964 -0.1713 -0.0566687666329 -0.0767849235284 -0.17135 -0.0565709722389 -0.0767800860821 -0.1714 -0.0564738373582 -0.076775144533 -0.17145 -0.0563759709101 -0.0767700968559 -0.1715 -0.0562787362419 -0.0767649409974 -0.17155 -0.0561807442426 -0.076759674907 -0.1716 -0.0560833537815 -0.0767542965079 -0.17165 -0.0559851776003 -0.0767488037303 -0.1717 -0.0558875699768 -0.0767431944799 -0.17175 -0.0557891453664 -0.0767374666737 -0.1718 -0.0556912533204 -0.0767316182059 -0.17185 -0.0555925098498 -0.0767256469859 -0.1719 -0.0554942596232 -0.0767195509035 -0.17195 -0.0553951200212 -0.0767133278672 -0.172 -0.0552964306425 -0.0767069757685 -0.17205 -0.055196810019 -0.0767004925211 -0.1721 -0.0550975924586 -0.0766938760245 -0.17215 -0.0549973973922 -0.0766871242039 -0.1722 -0.0548975535775 -0.0766802349728 -0.17225 -0.0547966810458 -0.0766732062739 -0.1723 -0.0546961026948 -0.0766660360409 -0.17235 -0.0545944388056 -0.0766587222409 -0.1724 -0.0544930060478 -0.0766512628343 -0.17245 -0.0543904245381 -0.0766436558177 -0.1725 -0.0542880042829 -0.076635899184 -0.17255 -0.0541843647445 -0.0766279909649 -0.1726 -0.0540808087439 -0.0766199291909 -0.17265 -0.0539759545043 -0.0766117119341 -0.1727 -0.0538710970367 -0.0766033372685 -0.17275 -0.053764852627 -0.0765948033123 -0.1728 -0.0536585077254 -0.0765861081875 -0.17285 -0.0535506758426 -0.0765772500625 -0.1729 -0.0534426339613 -0.0765682271116 -0.17295 -0.053332991806 -0.0765590375571 -0.173 -0.0532230157931 -0.0765496796303 -0.17305 -0.0531113106348 -0.0765401516122 -0.1731 -0.0529991308407 -0.076530451794 -0.17315 -0.0528850746158 -0.0765205785183 -0.1732 -0.0527703829223 -0.0765105301389 -0.17325 -0.0526536456219 -0.0765003050619 -0.1733 -0.0525360881048 -0.0764899017076 -0.17335 -0.0524162896237 -0.0764793185485 -0.1734 -0.0522954574838 -0.0764685540721 -0.17345 -0.052172157513 -0.0764576068182 -0.1735 -0.0520475757944 -0.0764464753424 -0.17355 -0.0519202611998 -0.0764351582535 -0.1736 -0.0517913746427 -0.0764236541765 -0.17365 -0.0516594435827 -0.0764119617889 -0.1737 -0.0515255987522 -0.0764000797836 -0.17375 -0.0513883405254 -0.0763880069061 -0.1738 -0.051248763041 -0.0763757419177 -0.17385 -0.0511053322962 -0.0763632836305 -0.1739 -0.0509590975545 -0.0763506308715 -0.17395 -0.0508084809738 -0.0763377825165 -0.174 -0.0506544761347 -0.0763247374559 -0.17405 -0.0504954489507 -0.0763114946271 -0.1741 -0.0503323230641 -0.0762980529798 -0.17415 -0.0501633916884 -0.0762844115073 -0.1742 -0.0499894895033 -0.0762705692143 -0.17425 -0.0498088149268 -0.0762565251462 -0.1743 -0.0496220879547 -0.0762422783558 -0.17435 -0.049427382145 -0.0762278279328 -0.1744 -0.0492252675656 -0.0762131729716 -0.17445 -0.0490136514158 -0.0761983125992 -0.1745 -0.0487929048008 -0.0761832459417 -0.17455 -0.0485607103653 -0.0761679721526 -0.1746 -0.0483171709279 -0.0761524903806 -0.17465 -0.0480596615943 -0.0761367997947 -0.1747 -0.0477879171399 -0.0761208995517 -0.17475 -0.0474988846146 -0.0761047888222 -0.1748 -0.0471917844617 -0.0760884667576 -0.17485 -0.0468629571851 -0.0760719325126 -0.1749 -0.0465108899811 -0.0760551852138 -0.17495 -0.0461310468544 -0.0760382239817 -0.175 -0.0457208470554 -0.0760210478963 -0.17505 -0.0452744607982 -0.076003656018 -0.1751 -0.0447877162615 -0.075986047355 -0.17515 -0.0442528304569 -0.0759682208791 -0.1752 -0.0436632049981 -0.0759501754927 -0.17525 -0.0430080400399 -0.0759319100441 -0.1753 -0.0422769511196 -0.0759134232905 -0.17535 -0.0414543790135 -0.0758947139111 -0.1754 -0.040523917735 -0.0758757804695 -0.17545 -0.0394623866897 -0.0758566214204 -0.1755 -0.0382437187042 -0.07583723507 -0.17555 -0.0368325487276 -0.075817619579 -0.1756 -0.0351875812644 -0.0757977729162 -0.17565 -0.0332548151127 -0.0757776928562 -0.1757 -0.0309709896952 -0.0757573769275 -0.17575 -0.0282580646727 -0.0757368223981 -0.1758 -0.0250303372522 -0.0757160262174 -0.17585 -0.021197226637 -0.0756949849876 -0.1759 -0.0166863408619 -0.0756736948901 -0.17595 -0.0114725567314 -0.0756521516413 -0.176 -0.00563500915811 -0.0756303503933 -0.17605 0.000590706855479 -0.0756082856645 -0.1761 0.0067849036401 -0.075585951205 -0.17615 0.0124123315976 -0.075563339881 -0.1762 0.0169716262259 -0.0755404434862 -0.17625 0.0201612937831 -0.0755172525494 -0.1763 0.0219364636631 -0.075493756053 -0.17635 0.0224565802412 -0.0754699411109 -0.1764 0.0219724765345 -0.0754457925184 -0.17645 0.0207430676944 -0.0754212922023 -0.1765 0.0189858472274 -0.0753964184617 -0.17655 0.0168707029938 -0.0753711450021 -0.1766 0.0145202504432 -0.0753454396117 -0.17665 0.0120246336254 -0.0753192624401 -0.1767 0.00944600574847 -0.0752925636687 -0.17675 0.00683070957584 -0.0752652804715 -0.1768 0.00420967299916 -0.0752373329833 -0.17685 0.00160696159957 -0.0752086190998 -0.1769 -0.000962515773331 -0.0751790077448 -0.17695 -0.00348634997076 -0.0751483303392 -0.177 -0.00595819810582 -0.0751163700087 -0.17705 -0.00837201223383 -0.0750828481321 -0.1771 -0.0107262023652 -0.0750474076114 -0.17715 -0.0130183109425 -0.0750095922465 -0.1772 -0.0152494878947 -0.0749688213249 -0.17725 -0.0174194246257 -0.0749243584542 -0.1773 -0.0195310139824 -0.0748752732988 -0.17735 -0.0215854508956 -0.0748203946925 -0.1774 -0.0235870012359 -0.0747582531018 -0.17745 -0.0255382007622 -0.0746870100618 -0.1775 -0.0274446664844 -0.0746043715205 -0.17755 -0.0293103275163 -0.0745074814365 -0.1776 -0.0311422146454 -0.0743927909923 -0.17765 -0.0329456606621 -0.0742558978367 -0.1777 -0.0347290093707 -0.0740913483204 -0.17775 -0.0364987282803 -0.0738923941704 -0.1778 -0.0382639742549 -0.073650692876 -0.17785 -0.0400315442414 -0.0733559386117 -0.1779 -0.0418102045702 -0.0729954071473 -0.17795 -0.043605364064 -0.0725533941487 -0.178 -0.0454230356118 -0.0720105206845 -0.17805 -0.04726411711 -0.0713428724924 -0.1781 -0.049127950276 -0.0705209289576 -0.17815 -0.0510063549932 -0.0695082220626 -0.1782 -0.0528872614264 -0.0682596396323 -0.17825 -0.0547494440568 -0.0667192416193 -0.1783 -0.0565676742364 -0.0648173706428 -0.17835 -0.0583098757994 -0.062466659822 -0.1784 -0.0599451618634 -0.0595561588143 -0.17845 -0.0614434713372 -0.0559419531608 -0.1785 -0.0627844714065 -0.0514307584078 -0.17855 -0.0639557080454 -0.0457488714946 -0.1786 -0.0649578862893 -0.0384813133144 -0.17865 -0.0657986370637 -0.0289608866198 -0.1787 -0.0664942701889 -0.0161413923219 -0.17875 -0.0670619401081 0.00112096146173 -0.1788 -0.0675216674533 0.0218193229554 -0.17885 -0.0678899498228 0.038956776383 -0.1789 -0.0681835086062 0.0457857131318 -0.17895 -0.0684143790621 0.0464924301103 -0.179 -0.0685946383668 0.0461253580086 -0.17905 -0.0687320522071 0.0454772487677 -0.1791 -0.0688350191237 0.0446241777207 -0.17915 -0.0689082654296 0.0435625562559 -0.1792 -0.0689577238911 0.0423096023467 -0.17925 -0.0689861500804 0.0408621357891 -0.1793 -0.0689978983548 0.0392304927274 -0.17935 -0.0689944668499 0.0374350375095 -0.1794 -0.0689791954364 0.0355031553778 -0.17945 -0.068952767628 0.0334462105754 -0.1795 -0.0689178564336 0.0312833765936 -0.17955 -0.0688746046277 0.0290297353209 -0.1796 -0.0688252354707 0.0267021617063 -0.17965 -0.0687695243506 0.0243152898366 -0.1797 -0.0687093842796 0.0218833984721 -0.17975 -0.0686443363585 0.0194190611209 -0.1798 -0.0685760757291 0.0169336589187 -0.17985 -0.0685039451326 0.0144371090753 -0.1799 -0.0684294846312 0.0119379068123 -0.17995 -0.0683519107732 0.00944327808286 -0.18 -0.0682726520943 0.00695908593718 -0.18005 -0.068190835418 0.0044901209809 -0.1801 -0.0681078083986 0.00203999064547 -0.18015 -0.0680226339329 -0.000388580148182 -0.1802 -0.0679366005746 -0.00279384546273 -0.18025 -0.0678487256912 -0.00517478656515 -0.1803 -0.0677602543187 -0.00753120195839 -0.18035 -0.0676701714901 -0.00986353924809 -0.1804 -0.067579689924 -0.0121730104887 -0.18045 -0.0674877718185 -0.0144615439989 -0.1805 -0.0673956056598 -0.0167319778022 -0.18055 -0.067302137668 -0.0189881810137 -0.1806 -0.0672085379451 -0.021235396408 -0.18065 -0.0671137417043 -0.0234805937711 -0.1807 -0.0670189049042 -0.0257330376875 -0.18075 -0.0669229553525 -0.0280049311442 -0.1808 -0.0668270379517 -0.0303122598408 -0.18085 -0.0667300757275 -0.0326757231707 -0.1809 -0.0666332047727 -0.035121760081 -0.18095 -0.0665353452381 -0.0376834344226 -0.181 -0.066437626049 -0.0404008097347 -0.18105 -0.0663389658752 -0.0433199232852 -0.1811 -0.0662404876774 -0.0464887261768 -0.18115 -0.0661411096594 -0.049947184885 -0.1812 -0.066041949697 -0.0537077414269 -0.18125 -0.0659419262698 -0.0577234710382 -0.1813 -0.0658421528153 -0.061849500094 -0.18135 -0.0657415486321 -0.0658239386599 -0.1814 -0.0656412231946 -0.0693161683482 -0.18145 -0.0655400970137 -0.0720606742607 -0.1815 -0.0654392759478 -0.0739869316204 -0.18155 -0.0653376820068 -0.0752175752344 -0.1816 -0.0652364176882 -0.0759550949173 -0.18165 -0.0651344067063 -0.0763818945526 -0.1817 -0.0650327483845 -0.0766256353238 -0.18175 -0.0649303682894 -0.0767649233516 -0.1818 -0.064828362704 -0.0768451810018 -0.18185 -0.0647256591485 -0.076891956574 -0.1819 -0.0646233509617 -0.0769195292195 -0.18195 -0.0645203676851 -0.0769359235039 -0.182 -0.0644177997789 -0.0769457000658 -0.18205 -0.0643145788485 -0.0769514900325 -0.1821 -0.0642117925189 -0.0769548343553 -0.18215 -0.0641083744822 -0.0769566512892 -0.1822 -0.0640054095553 -0.0769574956576 -0.18225 -0.0639018335272 -0.0769577089662 -0.1823 -0.0637987284244 -0.0769575035005 -0.18235 -0.0636950321347 -0.0769570140835 -0.1824 -0.0635918239056 -0.0769563265178 -0.18245 -0.0634880437227 -0.076955496999 -0.1825 -0.0633847680629 -0.0769545618659 -0.18255 -0.0632809390046 -0.0769535456811 -0.1826 -0.0631776302589 -0.0769524643846 -0.18265 -0.0630737859879 -0.0769513291302 -0.1827 -0.0629704771374 -0.0769501470254 -0.18275 -0.0628666499391 -0.0769489232542 -0.1828 -0.0627633725685 -0.0769476609248 -0.18285 -0.0626595933092 -0.0769463624347 -0.1829 -0.062556377558 -0.0769450290046 -0.18295 -0.0624526756292 -0.0769436616688 -0.183 -0.062349550129 -0.0769422607206 -0.18305 -0.0622459533784 -0.0769408264924 -0.1831 -0.0621429451806 -0.0769393588028 -0.18315 -0.0620394798389 -0.0769378576009 -0.1832 -0.0619366143401 -0.0769363224502 -0.18325 -0.0618333049453 -0.0769347530749 -0.1833 -0.061730605812 -0.076933148892 -0.18335 -0.0616274751351 -0.0769315094817 -0.1834 -0.0615249642302 -0.0769298341695 -0.18345 -0.0614220332032 -0.0769281224332 -0.1835 -0.0613197305164 -0.0769263735341 -0.18355 -0.0612170181644 -0.0769245868697 -0.1836 -0.0611149417455 -0.07692276165 -0.18365 -0.0610124651216 -0.0769208972038 -0.1837 -0.060910631017 -0.0769189926953 -0.18375 -0.0608084051402 -0.0769170473899 -0.1838 -0.0607068273325 -0.076915060408 -0.18385 -0.0606048651295 -0.0769130309536 -0.1839 -0.060503555481 -0.0769109581028 -0.18395 -0.0604018677303 -0.0769088409989 -0.184 -0.0603008359283 -0.0769066786716 -0.18405 -0.0601994312083 -0.0769044702033 -0.1841 -0.0600986847146 -0.076902214575 -0.18415 -0.0599975693526 -0.0768999108072 -0.1842 -0.0598971133533 -0.0768975578296 -0.18425 -0.0597962913762 -0.0768951545993 -0.1843 -0.059696128732 -0.0768926999928 -0.18435 -0.0595956018172 -0.0768901929026 -0.1844 -0.0594957330151 -0.0768876321494 -0.18445 -0.059395500441 -0.0768850165601 -0.1845 -0.0592959235444 -0.0768823448976 -0.18455 -0.0591959821418 -0.0768796159224 -0.1846 -0.059096692741 -0.0768768283379 -0.18465 -0.0589970368409 -0.0768739808373 -0.1847 -0.0588980279987 -0.0768710720633 -0.18475 -0.0587986493758 -0.076868100642 -0.1848 -0.0586999115688 -0.0768650651546 -0.18485 -0.0586007993808 -0.0768619641596 -0.1849 -0.0585023204372 -0.0768587961768 -0.18495 -0.05840346116 -0.0768555596981 -0.185 -0.0583052261894 -0.0768522531816 -0.18505 -0.0582066035407 -0.0768488750539 -0.1851 -0.0581085948523 -0.0768454237124 -0.18515 -0.0580101897052 -0.0768418975195 -0.1852 -0.0579123867175 -0.0768382948133 -0.18525 -0.0578141770049 -0.0768346138944 -0.1853 -0.0577165561417 -0.0768308530436 -0.18535 -0.057618516742 -0.0768270105025 -0.1854 -0.0575210513079 -0.0768230844968 -0.18545 -0.0574231539121 -0.0768190732119 -0.1855 -0.0573258139527 -0.0768149748217 -0.18555 -0.0572280269146 -0.0768107874589 -0.1856 -0.0571307790518 -0.0768065092489 -0.18565 -0.0570330672074 -0.076802138276 -0.1857 -0.056935874444 -0.076797672621 -0.18575 -0.0568381989027 -0.076793110324 -0.1858 -0.0567410203999 -0.0767884494259 -0.18585 -0.0566433383042 -0.0767836879271 -0.1859 -0.0565461291183 -0.0767788238336 -0.18595 -0.0564483933549 -0.076773855112 -0.186 -0.0563511041267 -0.0767687797384 -0.18605 -0.0562532629976 -0.0767635956512 -0.1861 -0.0561558395978 -0.0767583008018 -0.18615 -0.0560578364312 -0.0767528931063 -0.1862 -0.0559602195353 -0.0767473704972 -0.18625 -0.0558619922273 -0.0767417308742 -0.1863 -0.0557641168262 -0.0767359721571 -0.18635 -0.055665597314 -0.0767300922349 -0.1864 -0.0555673921393 -0.0767240890208 -0.18645 -0.0554685057744 -0.0767179604002 -0.1865 -0.0553698926195 -0.0767117042862 -0.18655 -0.0552705574362 -0.0767053185669 -0.1866 -0.0551714503682 -0.076698801161 -0.18665 -0.0550715762288 -0.0766921499657 -0.1867 -0.0549718806574 -0.0766853629118 -0.18675 -0.0548713682392 -0.0766784379114 -0.1868 -0.0547709798163 -0.0766713729134 -0.18685 -0.0546697194204 -0.0766641658515 -0.1869 -0.0545685227505 -0.0766568146993 -0.18695 -0.0544663928972 -0.076649317418 -0.187 -0.0543642600048 -0.0766416720116 -0.18705 -0.0542611257641 -0.0766338764744 -0.1871 -0.0541579142735 -0.0766259288461 -0.18715 -0.0540536252782 -0.0766178271594 -0.1872 -0.0539491762459 -0.076609569495 -0.18725 -0.0538435643259 -0.0766011539301 -0.1873 -0.0537376996518 -0.0765925785917 -0.18735 -0.0536305759969 -0.076583841606 -0.1874 -0.0535230953133 -0.0765749411504 -0.18745 -0.053414247058 -0.0765658754039 -0.1875 -0.0533049239768 -0.0765566425984 -0.18755 -0.0531941100714 -0.0765472409707 -0.1876 -0.053082687635 -0.0765376688115 -0.18765 -0.0529696338285 -0.0765279244183 -0.1877 -0.0528558189683 -0.0765180061433 -0.18775 -0.0527402116761 -0.076507912347 -0.1878 -0.0526236684184 -0.0764976414457 -0.18785 -0.0525051471862 -0.0764871918666 -0.1879 -0.0523854882774 -0.0764765620924 -0.18795 -0.0522636364597 -0.076465750618 -0.188 -0.0521404129728 -0.0764547559931 -0.18805 -0.0520147461184 -0.0764435767812 -0.1881 -0.0518874344543 -0.0764322116011 -0.18815 -0.0517573857336 -0.0764206590857 -0.1882 -0.0516253712487 -0.0764089179219 -0.18825 -0.051490273026 -0.076396986811 -0.1883 -0.0513528292431 -0.0763848645075 -0.18835 -0.0512118895653 -0.0763725497811 -0.1884 -0.0510681515323 -0.0763600414526 -0.18845 -0.0509204238689 -0.076347338357 -0.1885 -0.0507693536931 -0.0763344393782 -0.18855 -0.0506136975904 -0.0763213434149 -0.1886 -0.0504540394093 -0.0763080494116 -0.18865 -0.0502890687962 -0.0762945563256 -0.1887 -0.050119289261 -0.0762808631569 -0.18875 -0.0499433037356 -0.0762669689173 -0.1888 -0.0497615124296 -0.0762528726578 -0.18885 -0.049572404789 -0.0762385734375 -0.1889 -0.0493762464143 -0.0762240703506 -0.18895 -0.0491713765083 -0.0762093624973 -0.189 -0.0489578827623 -0.0761944490073 -0.18905 -0.0487339029033 -0.0761793290115 -0.1891 -0.0484992858604 -0.0761640016647 -0.18915 -0.0482518952934 -0.0761484661192 -0.1892 -0.0479912543973 -0.076132721543 -0.18925 -0.0477148480637 -0.076116767095 -0.1893 -0.0474217471274 -0.0761006019431 -0.18935 -0.0471089037923 -0.0760842252385 -0.1894 -0.0467747484867 -0.0760676361301 -0.18945 -0.0464154697632 -0.0760508337427 -0.1895 -0.0460285724651 -0.076033817188 -0.18955 -0.0456091273882 -0.0760165855404 -0.1896 -0.0451532716848 -0.0759991378484 -0.18965 -0.0446544033506 -0.0759814731113 -0.1897 -0.0441065912728 -0.075963590284 -0.18975 -0.0435006718503 -0.0759454882557 -0.1898 -0.0428275129358 -0.0759271658527 -0.18985 -0.0420739402408 -0.0759086218131 -0.1899 -0.0412257624132 -0.0758898547874 -0.18995 -0.0402634111029 -0.0758708633135 -0.19 -0.039164588031 -0.0758516458084 -0.19005 -0.0378994657398 -0.0758322005438 -0.1901 -0.0364328198458 -0.0758125256326 -0.19015 -0.0347187442491 -0.0757926189966 -0.1902 -0.0327024770529 -0.0757724783492 -0.19025 -0.0303154273114 -0.0757521011563 -0.1903 -0.0274787108245 -0.0757314846064 -0.19035 -0.0241028090796 -0.0757106255659 -0.1904 -0.0201010508954 -0.075689520532 -0.19045 -0.015407734864 -0.0756681655748 -0.1905 -0.0100205265764 -0.0756465562711 -0.19055 -0.00405242041924 -0.0756246876212 -0.1906 0.00221153524495 -0.0756025539551 -0.19065 0.00831299214099 -0.075580148811 -0.1907 0.0137068258554 -0.0755574647938 -0.19075 0.0179318144738 -0.0755344933956 -0.1908 0.0207506349858 -0.0755112247717 -0.19085 0.0221816436041 -0.0754876474611 -0.1909 0.0224168295787 -0.0754637480226 -0.19095 0.0217173164836 -0.0754395105757 -0.191 0.0203324736248 -0.0754149161871 -0.19105 0.0184691193078 -0.0753899420805 -0.1911 0.0162826456108 -0.0753645605713 -0.19115 0.0138877829327 -0.0753387376683 -0.1912 0.0113651670524 -0.0753124311941 -0.19125 0.00877372769059 -0.075285588306 -0.1913 0.00615393624624 -0.075258142207 -0.19135 0.00353611217846 -0.0752300078542 -0.1914 0.000940289344124 -0.0752010763763 -0.19145 -0.00161795753076 -0.0751712079289 -0.1915 -0.00412934718766 -0.0751402226022 -0.19155 -0.00658623456022 -0.0751078890097 -0.1916 -0.00898523163728 -0.0750739100284 -0.19165 -0.0113231133623 -0.0750379051546 -0.1917 -0.0135998321218 -0.0749993887122 -0.19175 -0.0158147322646 -0.074957743083 -0.1918 -0.0179697901002 -0.0749121858246 -0.19185 -0.0200660210607 -0.0748617293678 -0.1919 -0.0221068577941 -0.0748051315683 -0.19195 -0.0240946768374 -0.0747408350836 -0.192 -0.0260342472384 -0.0746668929521 -0.19205 -0.0279293101009 -0.0745808772514 -0.1921 -0.0297860320637 -0.0744797668624 -0.19215 -0.0316095738519 -0.074359809565 -0.1922 -0.0334074869928 -0.0742163524386 -0.19225 -0.0351862131998 -0.0740436332685 -0.1923 -0.0369543664833 -0.0738345237931 -0.19235 -0.0387190985453 -0.073580213581 -0.1924 -0.0404891880235 -0.0732698204725 -0.19245 -0.0422711724659 -0.0728899101867 -0.1925 -0.0440721232212 -0.0724239031031 -0.19255 -0.0458954142814 -0.0718513404776 -0.1926 -0.0477430802961 -0.07114697417 -0.19265 -0.0496112216688 -0.0702796325355 -0.1927 -0.0514921627829 -0.0692107971687 -0.19275 -0.053370077695 -0.0678927956728 -0.1928 -0.0552240292093 -0.0662664618152 -0.19285 -0.0570253699839 -0.0642580101221 -0.1929 -0.0587433683086 -0.0617746556828 -0.19295 -0.0603455085112 -0.0586980422559 -0.193 -0.0618052772842 -0.054873500177 -0.19305 -0.0631027776846 -0.0500908309108 -0.1931 -0.0642303918479 -0.0440473959726 -0.19315 -0.0651894304997 -0.0362760705087 -0.1932 -0.0659914719675 -0.0260210372118 -0.19325 -0.0666519367028 -0.0121438252722 -0.1933 -0.0671903351676 0.00628941589684 -0.19335 -0.0676245123614 0.0269856612454 -0.1934 -0.0679724749375 0.0417200164929 -0.19345 -0.0682483492 0.0462552808138 -0.1935 -0.0684655541268 0.0464375727384 -0.19355 -0.0686336346059 0.0459860755052 -0.1936 -0.0687618772644 0.0452831641653 -0.19365 -0.0688563178457 0.0443758820106 -0.1937 -0.0689233558247 0.043265005957 -0.19375 -0.0689667009926 0.0419621182737 -0.1938 -0.0689908887008 0.0404669237448 -0.19385 -0.0689981435191 0.038789282752 -0.1939 -0.068991808784 0.0369578198856 -0.19395 -0.0689731538459 0.0349924523704 -0.194 -0.0689447459821 0.0329066265984 -0.19405 -0.0689072260547 0.0307190915632 -0.1941 -0.0688626430783 0.0284447955757 -0.19415 -0.068811214137 0.026100635524 -0.1942 -0.0687546337748 0.0237007148378 -0.19425 -0.0686928273521 0.0212592625856 -0.1943 -0.0686272422239 0.0187882697874 -0.19435 -0.0685575997885 0.0162989687526 -0.1944 -0.0684851724765 0.0138007470119 -0.19445 -0.0684095375486 0.0113018965312 -0.1945 -0.068331842296 0.0088091988585 -0.19455 -0.068251561425 0.00632830115461 -0.1946 -0.0681697519507 0.00386363851998 -0.19465 -0.0680858153278 0.00141861526675 -0.1947 -0.0680007429937 -0.00100432060634 -0.19475 -0.0679138839932 -0.00340360484751 -0.1948 -0.0678261818178 -0.00577843686545 -0.19485 -0.0677369480225 -0.00812878309197 -0.1949 -0.0676470908053 -0.0104552819515 -0.19495 -0.0675558949617 -0.0127593274057 -0.195 -0.0674642425131 -0.0150430609135 -0.19505 -0.0673713992344 -0.0173095709243 -0.1951 -0.0672782275633 -0.0195630396409 -0.19515 -0.0671839798532 -0.0218091179887 -0.1952 -0.0670895037316 -0.0240553008758 -0.19525 -0.0669940421928 -0.0263115444847 -0.1953 -0.0668984315259 -0.0285909316958 -0.19535 -0.0668019083155 -0.0309105701181 -0.1954 -0.0667053000351 -0.0332925302957 -0.19545 -0.0666078390105 -0.0357648841937 -0.1955 -0.0665103457451 -0.0383624882857 -0.19555 -0.0664120498712 -0.0411271282192 -0.1956 -0.0663137662672 -0.044105891273 -0.19565 -0.0662147230158 -0.0473459443698 -0.1957 -0.0661157303578 -0.0508825264135 -0.19575 -0.0660160156637 -0.0547163686082 -0.1958 -0.0659163852592 -0.0587789906116 -0.19585 -0.0658160664128 -0.0628955419108 -0.1959 -0.0657158620646 -0.0667781596736 -0.19595 -0.0656149998263 -0.0700977949758 -0.196 -0.0655142796418 -0.072630215228 -0.19605 -0.0654129297914 -0.0743609708249 -0.1961 -0.0653117475076 -0.075445477865 -0.19615 -0.0652099619741 -0.0760879979181 -0.1962 -0.0651083679186 -0.0764579230866 -0.19625 -0.0650061955963 -0.0766690027272 -0.1963 -0.0649042373802 -0.0767898213674 -0.19635 -0.0648017247162 -0.076859631558 -0.1964 -0.0646994477296 -0.0769004421972 -0.19645 -0.0645966391384 -0.0769245613485 -0.1965 -0.0644940868952 -0.076938923084 -0.19655 -0.0643910250432 -0.0769474825645 -0.1966 -0.0642882394113 -0.0769525305308 -0.19665 -0.0641849653985 -0.0769554142902 -0.1967 -0.0640819867401 -0.0769569399452 -0.19675 -0.0639785402068 -0.0769575965196 -0.1968 -0.063875407459 -0.0769576862362 -0.19685 -0.0637718266454 -0.0769573975445 -0.1969 -0.063668577363 -0.0769568507072 -0.19695 -0.0635648991403 -0.0769561223046 -0.197 -0.0634615695187 -0.076955262889 -0.19705 -0.0633578294052 -0.0769543049586 -0.1971 -0.0632544542905 -0.0769532708441 -0.19715 -0.0631506864543 -0.0769521747305 -0.1972 -0.0630472993364 -0.0769510269198 -0.19725 -0.0629435365789 -0.0769498336109 -0.1973 -0.0628401695659 -0.0769485997243 -0.19735 -0.0627364432872 -0.0769473278183 -0.1974 -0.0626331270618 -0.0769460202891 -0.19745 -0.0625294672084 -0.0769446779666 -0.1975 -0.0624262309687 -0.0769433020039 -0.19755 -0.0623226659693 -0.076941892379 -0.1976 -0.0622195373606 -0.0769404495978 -0.19765 -0.0621160940543 -0.0769389732027 -0.1977 -0.0620130990947 -0.0769374633399 -0.19775 -0.0619098026563 -0.0769359193201 -0.1978 -0.0618069656624 -0.0769343410714 -0.19785 -0.0617038395278 -0.0769327277754 -0.1979 -0.0616011830403 -0.076931079214 -0.19795 -0.0614982488333 -0.0769293944919 -0.198 -0.0613957935453 -0.0769276732816 -0.19805 -0.0612930710071 -0.0769259146372 -0.1981 -0.0611908356953 -0.0769241181409 -0.19815 -0.0610883426183 -0.0769222828089 -0.1982 -0.0609863440788 -0.0769204081429 -0.19825 -0.0608840962434 -0.0769184931266 -0.1983 -0.0607823492301 -0.0769165371859 -0.19835 -0.060680360346 -0.0769145392734 -0.1984 -0.0605788775139 -0.076912498741 -0.19845 -0.0604771591638 -0.0769104145098 -0.1985 -0.0603759510135 -0.0769082858578 -0.19855 -0.0602745125991 -0.0769061116726 -0.1986 -0.060173587424 -0.0769038911582 -0.19865 -0.0600724361142 -0.076901623166 -0.1987 -0.05997179995 -0.0768993068252 -0.19875 -0.0598709406307 -0.0768969409482 -0.1988 -0.0597705972056 -0.0768945245884 -0.19885 -0.0596700324317 -0.0768920565163 -0.1989 -0.0595699831187 -0.0768895357095 -0.19895 -0.0594697130655 -0.0768869608933 -0.199 -0.0593699568332 -0.0768843309686 -0.19905 -0.0592699792465 -0.0768816446136 -0.1991 -0.0591705126086 -0.0768789006522 -0.19915 -0.0590708227531 -0.0768760977128 -0.1992 -0.0589716397154 -0.0768732345425 -0.19925 -0.0588722303208 -0.0768703097181 -0.1993 -0.0587733223266 -0.0768673219106 -0.19935 -0.0586741835304 -0.0768642696437 -0.1994 -0.0585755393986 -0.076861151513 -0.19945 -0.0584766586805 -0.0768579659884 -0.1995 -0.0583782645371 -0.0768547115914 -0.19955 -0.0582796266469 -0.0768513867378 -0.1996 -0.0581814658494 -0.0768479898769 -0.19965 -0.0580830527275 -0.0768445193704 -0.1997 -0.0579851057793 -0.0768409735974 -0.19975 -0.0578868964628 -0.0768373508668 -0.1998 -0.0577891409106 -0.0768336494902 -0.19985 -0.0576911114244 -0.0768298677251 -0.1999 -0.0575935217452 -0.0768260038192 -0.19995 -0.0574956449812 -0.0768220559801 -0.2 -0.0573981924485 -0.0768180223953 -0.20005 -0.0573004380186 -0.0768139012251 -0.2001 -0.0572030905436 -0.076809690601 -0.20015 -0.0571054246107 -0.0768053886391 -0.2002 -0.0570081465636 -0.0768009934191 -0.20025 -0.0569105316484 -0.0767965030166 -0.2003 -0.0568132836451 -0.0767919154648 -0.20035 -0.0567156783919 -0.0767872288026 -0.2004 -0.0566184170427 -0.0767824410217 -0.20045 -0.0565207759538 -0.0767775501291 -0.2005 -0.0564234535781 -0.0767725540812 -0.20055 -0.0563257267006 -0.076767450858 -0.2006 -0.0562282909836 -0.0767622383861 -0.20065 -0.0561304235387 -0.0767569146238 -0.2007 -0.0560328171358 -0.0767514774742 -0.20075 -0.0559347490947 -0.0767459248791 -0.2008 -0.0558369091698 -0.0767402547246 -0.20085 -0.0557385747487 -0.0767344649417 -0.2009 -0.0556404324268 -0.0767285534055 -0.20095 -0.0555417594986 -0.0767225180425 -0.201 -0.0554432392332 -0.0767163567241 -0.20105 -0.0553441486425 -0.076710067378 -0.2011 -0.0552451674692 -0.0767036478786 -0.20115 -0.0551455722193 -0.0766970961607 -0.2012 -0.0550460388759 -0.0766904101078 -0.20125 -0.0549458431798 -0.0766835876683 -0.2013 -0.0548456570788 -0.076676626741 -0.20135 -0.0547447552413 -0.0766695252932 -0.2014 -0.0546438052527 -0.0766622812464 -0.20145 -0.0545420803459 -0.0766548925933 -0.2015 -0.0544402433557 -0.0766473572834 -0.20155 -0.0543375656514 -0.0766396733407 -0.2016 -0.0542347048578 -0.0766318387487 -0.20165 -0.0541309299716 -0.0766238515673 -0.2017 -0.0540268928571 -0.0766157098194 -0.20175 -0.0539218595304 -0.0766074116066 -0.2018 -0.0538164754367 -0.0765989549972 -0.20185 -0.0537100028834 -0.0765903381392 -0.2019 -0.0536030801054 -0.0765815591508 -0.20195 -0.0534949648258 -0.0765726162307 -0.202 -0.0533862871135 -0.0765635075507 -0.20205 -0.053276299049 -0.0765542313644 -0.2021 -0.0531656213753 -0.0765447859021 -0.20215 -0.0530534992435 -0.0765351694762 -0.2022 -0.0529405426563 -0.0765253803786 -0.20225 -0.0528259882649 -0.0765154169828 -0.2023 -0.0527104335952 -0.0765052776449 -0.20235 -0.052593104865 -0.0764949608022 -0.2024 -0.0524745849816 -0.0764844648784 -0.20245 -0.0523540873369 -0.0764737883769 -0.2025 -0.0522321775587 -0.0764629297894 -0.20255 -0.0521080532321 -0.0764518876859 -0.2026 -0.0519822593748 -0.0764406606279 -0.20265 -0.0518539740249 -0.0764292472537 -0.2027 -0.0517237173911 -0.0764176461947 -0.20275 -0.051590643226 -0.0764058561567 -0.2028 -0.0514552415931 -0.0763938758398 -0.20285 -0.0513166359154 -0.076381704017 -0.2029 -0.0511752792631 -0.0763693394573 -0.20295 -0.0510302569444 -0.0763567809988 -0.203 -0.0508819761671 -0.0763440274758 -0.20305 -0.0507294739953 -0.076331077789 -0.2031 -0.0505731001783 -0.0763179308367 -0.20315 -0.0504118302063 -0.0763045855788 -0.2032 -0.0502459410281 -0.0762910409721 -0.20325 -0.0500743288299 -0.0762772960308 -0.2033 -0.0498971772193 -0.0762633497665 -0.20335 -0.049713279193 -0.0762492012427 -0.2034 -0.0495226971562 -0.0762348495178 -0.20345 -0.0493240882924 -0.0762202936971 -0.2035 -0.0491173554782 -0.0762055328798 -0.20355 -0.0489009748763 -0.0761905662048 -0.2036 -0.0486746363048 -0.076175392801 -0.20365 -0.0484365712417 -0.0761600118309 -0.2037 -0.0481861804293 -0.0761444224436 -0.20375 -0.0479213594606 -0.0761286238122 -0.2038 -0.0476411100906 -0.0761126150915 -0.20385 -0.0473428589267 -0.076096395452 -0.2039 -0.0470250467404 -0.0760799640389 -0.20395 -0.0466844329702 -0.0760633200008 -0.204 -0.0463186536677 -0.0760464624545 -0.20405 -0.0459234996894 -0.0760293905076 -0.2041 -0.0454954276028 -0.0760121032238 -0.20415 -0.0450287911093 -0.0759945996441 -0.2042 -0.0445182781962 -0.0759768787533 -0.20425 -0.0439560608298 -0.0759589394936 -0.2043 -0.0433341126353 -0.0759407807357 -0.20435 -0.0426412171691 -0.0759224012877 -0.2044 -0.0418650888602 -0.0759037998631 -0.20445 -0.040989141311 -0.0758849750877 -0.2045 -0.0399942891754 -0.0758659254674 -0.20455 -0.0388553323246 -0.0758466493856 -0.2046 -0.0375422857604 -0.0758271450734 -0.20465 -0.0360162564738 -0.0758074105981 -0.2047 -0.0342303001034 -0.0757874438293 -0.20475 -0.0321251095245 -0.075767242421 -0.2048 -0.0296304339645 -0.0757468037699 -0.20485 -0.0266630644506 -0.0757261249866 -0.2049 -0.0231339735044 -0.0757052028468 -0.20495 -0.0189581407737 -0.0756840337433 -0.205 -0.0140827976454 -0.0756626136263 -0.20505 -0.00852851883052 -0.0756409379316 -0.2051 -0.00244960603676 -0.0756190014974 -0.20515 0.00382247739276 -0.075596798461 -0.2052 0.00979313241358 -0.0755743221355 -0.20525 0.0149227233276 -0.075551564857 -0.2053 0.018796634749 -0.0755285177968 -0.20535 0.0212471510916 -0.0755051707219 -0.2054 0.022346525903 -0.0754815117003 -0.20545 0.0223154061038 -0.0754575267093 -0.2055 0.0214163921815 -0.0754331991477 -0.20555 0.0198907357985 -0.0754085091741 -0.2056 0.0179306968017 -0.0753834328624 -0.20565 0.0156813153978 -0.0753579410493 -0.2057 0.0132465178373 -0.0753319978364 -0.20575 0.0107016303317 -0.0753055585584 -0.2058 0.00809920648515 -0.0752785671278 -0.20585 0.005477759576 -0.0752509524955 -0.2059 0.00286362990385 -0.0752226240678 -0.20595 0.00027656130376 -0.0751934657362 -0.206 -0.0022706807417 -0.0751633282818 -0.20605 -0.00476828555758 -0.0751320197112 -0.2061 -0.00721082519888 -0.0750992931756 -0.20615 -0.00959395880115 -0.0750648318848 -0.2062 -0.0119163639994 -0.0750282304796 -0.20625 -0.0141768181448 -0.0749889720363 -0.2063 -0.0163764051499 -0.0749463998467 -0.20635 -0.0185158216175 -0.0748996827495 -0.2064 -0.0205977522416 -0.0748477726588 -0.20645 -0.0226243183482 -0.0747893524357 -0.2065 -0.0245995509303 -0.0747227719898 -0.20655 -0.0265269142897 -0.0746459698096 -0.2066 -0.0284118103313 -0.074556376655 -0.20665 -0.0302591119721 -0.0744507971908 -0.2067 -0.0320756352134 -0.0743252645428 -0.20675 -0.0338676218351 -0.0741748613934 -0.2068 -0.0356431217698 -0.0739934999342 -0.20685 -0.0374093657624 -0.0737736509585 -0.2069 -0.0391749904724 -0.0735060102815 -0.20695 -0.0409472183219 -0.0731790875643 -0.207 -0.0427338196522 -0.0727786991451 -0.20705 -0.0445399742261 -0.0722873414851 -0.2071 -0.0463698426583 -0.071683415702 -0.20715 -0.0482230248636 -0.0709402646606 -0.2072 -0.0500957836721 -0.0700249714676 -0.20725 -0.0519773969341 -0.0688968478411 -0.2073 -0.0538517365068 -0.0675055067358 -0.20735 -0.0556947278078 -0.0657883500991 -0.2074 -0.0574779261049 -0.0636671774868 -0.20745 -0.0591687245673 -0.0610433582609 -0.2075 -0.0607367425518 -0.057790436339 -0.20755 -0.0621558265976 -0.0537417536413 -0.2076 -0.0634101279126 -0.0486678331825 -0.20765 -0.064493411889 -0.0422324371465 -0.2077 -0.0654109033491 -0.0339078638759 -0.20775 -0.0661744736514 -0.0228408991188 -0.2078 -0.0668018841863 -0.00782889115364 -0.20785 -0.0673114036094 0.0116514893367 -0.2079 -0.0677220338307 0.0317359065257 -0.20795 -0.0680498163199 0.0437254140047 -0.208 -0.0683096977621 0.0464633404479 -0.20805 -0.0685130716158 0.0463532666189 -0.2081 -0.068670387465 0.0458273919051 -0.20815 -0.0687890617451 0.045072866167 -0.2082 -0.0688761966963 0.0441110414569 -0.20825 -0.0689364766869 0.042951506284 -0.2083 -0.0689748039384 0.041598288935 -0.20835 -0.0689941068888 0.0400557549093 -0.2084 -0.068997882873 0.0383334060293 -0.20845 -0.0689879371218 0.0364671775585 -0.2085 -0.0689668600732 0.0344687609219 -0.20855 -0.0689357244868 0.0323553854075 -0.2086 -0.0688965211058 0.030143857981 -0.20865 -0.068849832963 0.0278500950157 -0.2087 -0.0687972442376 0.0254901584734 -0.20875 -0.0687390030567 0.0230782068674 -0.2088 -0.068676412117 0.0206279744321 -0.20885 -0.0686094864367 0.0181511638832 -0.2089 -0.0685393306573 0.0156586452456 -0.20895 -0.0684657954765 0.0131594116177 -0.209 -0.0683898445192 0.0106614657883 -0.20905 -0.0683112116663 0.0081711945709 -0.2091 -0.0682307592508 0.00569401177353 -0.20915 -0.0681481376616 0.00323400138751 -0.2092 -0.0680641359775 0.000794381957614 -0.20925 -0.0679783447254 -0.00162269436843 -0.2093 -0.0678914996953 -0.00401581225007 -0.20935 -0.0678031484319 -0.00638442028829 -0.2094 -0.0677139877392 -0.00872861662109 -0.20945 -0.0676235343019 -0.0110492687508 -0.2095 -0.0675324562273 -0.0133479211095 -0.20955 -0.0674402480771 -0.0156269736483 -0.2096 -0.0673475566921 -0.0178897455996 -0.20965 -0.0672538608221 -0.0201407875535 -0.2097 -0.0671597914226 -0.0223861571616 -0.20975 -0.0670648160091 -0.0246339439345 -0.2098 -0.0669695535523 -0.0268948177836 -0.20985 -0.0668734636548 -0.0291828281942 -0.2099 -0.0667771561452 -0.031516250091 -0.20995 -0.0666800851325 -0.033918621464 -0.21 -0.0665828533704 -0.0364196888139 -0.21005 -0.066484911235 -0.0390561417587 -0.2101 -0.0663868559181 -0.0418713799337 -0.21015 -0.0662881353517 -0.0449132311724 -0.2102 -0.0661893422716 -0.0482272866186 -0.21025 -0.0660899231047 -0.051842568013 -0.2103 -0.0659904669394 -0.0557456927842 -0.21035 -0.0658904193852 -0.0598439075868 -0.2104 -0.0657903664776 -0.0639314992747 -0.21045 -0.0656897535124 -0.0676992236473 -0.2105 -0.0655891639073 -0.0708299538467 -0.21055 -0.0654880430095 -0.0731485891912 -0.2106 -0.0653869719368 -0.0746939109454 -0.21065 -0.0652853963542 -0.0756455271118 -0.2107 -0.0651838953115 -0.0762038640368 -0.21075 -0.0650819149838 -0.0765240845888 -0.2108 -0.0649800325218 -0.0767067854478 -0.21085 -0.0648776947482 -0.0768115731596 -0.2109 -0.0647754770344 -0.0768722968178 -0.21095 -0.0646728269457 -0.0769079030708 -0.211 -0.0645703181585 -0.0769289952236 -0.21105 -0.0644673990445 -0.0769415683779 -0.2111 -0.0643646416412 -0.0769490508448 -0.21115 -0.0642614951664 -0.0769534399613 -0.2112 -0.0641585300546 -0.076955911978 -0.21125 -0.0640551963914 -0.076957176668 -0.2113 -0.0639520630295 -0.0769576634512 -0.21135 -0.0638485809331 -0.0769576413987 -0.2114 -0.0637453173853 -0.0769572764412 -0.21145 -0.0636417242334 -0.0769566771133 -0.2115 -0.0635383671986 -0.0769559106578 -0.21155 -0.0634346990116 -0.0769550235405 -0.2116 -0.0633312838366 -0.076954043943 -0.21165 -0.0632275752849 -0.0769529929393 -0.2117 -0.0631241359641 -0.0769518824597 -0.21175 -0.0630204203589 -0.0769507226133 -0.2118 -0.0629169895163 -0.0769495182668 -0.21185 -0.0628132987825 -0.0769482745348 -0.2119 -0.0627099076347 -0.0769469930992 -0.21195 -0.0626062722644 -0.076945676671 -0.212 -0.0625029505676 -0.0769443254545 -0.21205 -0.0623993995619 -0.0769429409326 -0.2121 -0.0622961755463 -0.0769415226112 -0.21215 -0.0621927363436 -0.0769400713011 -0.2122 -0.0620896366403 -0.0769385861761 -0.21225 -0.0619863350427 -0.0769370676483 -0.2123 -0.0618833846085 -0.0769355147349 -0.21235 -0.0617802447061 -0.0769339275897 -0.2124 -0.0616774667485 -0.0769323051574 -0.21245 -0.0615745108455 -0.0769306474082 -0.2125 -0.0614719267501 -0.0769289532543 -0.21255 -0.0613691752936 -0.0769272225231 -0.2126 -0.0612668045553 -0.076925454112 -0.21265 -0.0611642760685 -0.076923647729 -0.2127 -0.0610621362253 -0.0769218022629 -0.21275 -0.0609598472432 -0.076919917316 -0.2128 -0.0608579538143 -0.0769179917688 -0.21285 -0.0607559188225 -0.0769160251263 -0.2129 -0.0606542852482 -0.076914016258 -0.21295 -0.0605525166252 -0.0769119645767 -0.213 -0.0604511542112 -0.0769098689367 -0.21305 -0.0603496621738 -0.0769077286619 -0.2131 -0.0602485800375 -0.0769055425866 -0.21315 -0.0601473725887 -0.076903309948 -0.2132 -0.060046577609 -0.0769010295552 -0.21325 -0.0599456604884 -0.0768987005602 -0.2133 -0.0598451572555 -0.0768963217421 -0.21335 -0.0597445338893 -0.0768938921685 -0.2134 -0.0596443246558 -0.0768914105842 -0.21345 -0.0595439961081 -0.0768888759732 -0.2135 -0.0594440807399 -0.0768862870421 -0.21355 -0.0593440456632 -0.0768836426916 -0.2136 -0.0592444215901 -0.0768809415866 -0.21365 -0.0591446761764 -0.0768781825454 -0.2137 -0.0590453383413 -0.0768753641879 -0.21375 -0.0589458762684 -0.0768724852512 -0.2138 -0.0588468170724 -0.0768695443075 -0.21385 -0.0587476294467 -0.0768665400138 -0.2139 -0.0586488386886 -0.0768634708931 -0.21395 -0.0585499139836 -0.0768603355234 -0.214 -0.058451378797 -0.0768571323772 -0.21405 -0.0583527027852 -0.0768538599554 -0.2141 -0.058254407565 -0.0768505166795 -0.21415 -0.05815596324 -0.0768471009755 -0.2142 -0.0580578895581 -0.0768436112136 -0.21425 -0.0579596570449 -0.0768400457475 -0.2143 -0.0578617835574 -0.076836402897 -0.21435 -0.0577637400135 -0.0768326809466 -0.2144 -0.0576660423518 -0.076828878167 -0.21445 -0.0575681618476 -0.0768249927769 -0.2145 -0.0574706124891 -0.076821023 -0.21455 -0.0573728658708 -0.0768169669928 -0.2146 -0.0572754339943 -0.0768128229343 -0.21465 -0.0571777887277 -0.0768085889234 -0.2147 -0.0570804400411 -0.0768042630974 -0.21475 -0.0569828600225 -0.0767998435023 -0.2148 -0.0568855565594 -0.076795328237 -0.21485 -0.0567880019006 -0.0767907152998 -0.2149 -0.0566907017901 -0.0767860027554 -0.21495 -0.056593128566 -0.0767811885594 -0.215 -0.0564957857562 -0.0767762707473 -0.21505 -0.056398145705 -0.0767712472382 -0.2151 -0.0563007096421 -0.0767661160428 -0.21515 -0.0562029498234 -0.0767608750498 -0.2152 -0.0561053650809 -0.0767555222504 -0.21525 -0.0560074274692 -0.0767500555091 -0.2153 -0.0559096333055 -0.0767444728028 -0.21535 -0.0558114543145 -0.0767387719781 -0.2154 -0.0557133841643 -0.0767329510036 -0.21545 -0.0556148940972 -0.0767270077143 -0.2155 -0.0555164749715 -0.0767209400764 -0.21555 -0.0554175973677 -0.0767147459208 -0.2156 -0.0553187491468 -0.076708423217 -0.21565 -0.0552194000213 -0.0767019697982 -0.2157 -0.0551200346341 -0.0766953836434 -0.21575 -0.0550201215845 -0.0766886625944 -0.2158 -0.0549201420359 -0.0766818046456 -0.21585 -0.0548195631855 -0.0766748076536 -0.2159 -0.0547188624098 -0.0766676696342 -0.21595 -0.0546175051659 -0.076660388466 -0.216 -0.0545159646793 -0.0766529621921 -0.21605 -0.0544137042651 -0.076645388719 -0.2161 -0.0543111925644 -0.0766376661227 -0.21615 -0.054207890273 -0.0766297923431 -0.2162 -0.0541042609317 -0.076621765494 -0.21625 -0.0539997620486 -0.0766135835546 -0.2163 -0.0538948514483 -0.0766052446821 -0.21635 -0.053788982773 -0.0765967469005 -0.2164 -0.053682607391 -0.0765880884153 -0.21645 -0.0535751742622 -0.0765792672996 -0.2165 -0.053467127407 -0.076570281811 -0.21655 -0.0533579101177 -0.0765611300762 -0.2166 -0.0532479579872 -0.0765518104091 -0.21665 -0.0531367074455 -0.0765423209945 -0.2167 -0.0530245843435 -0.0765326602061 -0.21675 -0.0529110167916 -0.0765228262901 -0.2168 -0.0527964192893 -0.0765128176824 -0.21685 -0.0526802098397 -0.0765026326926 -0.2169 -0.0525627896104 -0.0764922698221 -0.21695 -0.0524435642902 -0.0764817274475 -0.217 -0.0523229192614 -0.0764710041366 -0.21705 -0.0522002451538 -0.076460098334 -0.2171 -0.0520759085011 -0.0764490086748 -0.21715 -0.0519492814402 -0.0764377336728 -0.2172 -0.0518207078051 -0.0764262720321 -0.21725 -0.051689536905 -0.0764146223359 -0.2173 -0.0515560849966 -0.0764027833558 -0.21735 -0.0514196730447 -0.0763907537435 -0.2174 -0.0512805834919 -0.0763785323383 -0.21745 -0.051138101881 -0.0763661178598 -0.2175 -0.0509924687913 -0.0763535092125 -0.21755 -0.0508429251685 -0.0763407051805 -0.2176 -0.0506896592434 -0.0763277047313 -0.21765 -0.0505318553396 -0.076314506712 -0.2177 -0.0503696355306 -0.076301110149 -0.21775 -0.0502021115944 -0.0762875139469 -0.2178 -0.0500293210386 -0.0762737171862 -0.21785 -0.0498502817418 -0.0762597188255 -0.2179 -0.0496649218013 -0.0762455179937 -0.21795 -0.0494721361918 -0.076231113695 -0.218 -0.0492717096069 -0.0762165050995 -0.21805 -0.0490623741294 -0.0762016912511 -0.2181 -0.0488437238529 -0.0761866713518 -0.21815 -0.0486142720088 -0.0761714444742 -0.2182 -0.0483733554798 -0.0761560098428 -0.21825 -0.0481191890015 -0.0761403665484 -0.2183 -0.0478507565968 -0.0761245138242 -0.21835 -0.0475658590878 -0.0761084507651 -0.2184 -0.0472629876789 -0.0760921765998 -0.21845 -0.0469393587227 -0.0760756904107 -0.2185 -0.0465927616703 -0.0760589914025 -0.21855 -0.0462195710667 -0.0760420786269 -0.2186 -0.0458165559606 -0.0760249512438 -0.21865 -0.045378852309 -0.0760076082489 -0.2187 -0.0449017119373 -0.0759900487321 -0.21875 -0.0443784067448 -0.0759722716057 -0.2188 -0.0438018797476 -0.0759542758564 -0.21885 -0.0431625320555 -0.0759360602783 -0.2189 -0.0424497121686 -0.0759176237174 -0.21895 -0.0416493032995 -0.0758989648049 -0.219 -0.0407449463728 -0.075880082198 -0.21905 -0.0397152992601 -0.0758609743121 -0.2191 -0.0385348451235 -0.0758416395533 -0.21915 -0.0371706731428 -0.0758220760531 -0.2192 -0.0355827685538 -0.0758022818894 -0.21925 -0.033720371225 -0.07578225482 -0.2193 -0.0315222026298 -0.0757619924947 -0.21935 -0.0289137244783 -0.0757414921814 -0.2194 -0.025810337763 -0.0757207509671 -0.21945 -0.0221216537346 -0.0756997654759 -0.2195 -0.017768626267 -0.0756785320502 -0.21955 -0.0127116912387 -0.0756570464579 -0.2196 -0.00700094560818 -0.0756353040457 -0.21965 -0.000832711946706 -0.0756132994253 -0.2197 0.00541335551124 -0.0755910265905 -0.21975 0.0112169395441 -0.0755684785624 -0.2198 0.0160534166564 -0.0755456474522 -0.21985 0.0195657605804 -0.0755225240382 -0.2199 0.021652717416 -0.0754990977362 -0.21995 0.0224363173843 -0.0754753560608 -0.22 0.0221560879237 -0.0754512844314 -0.22005 0.0210743481477 -0.0754268654269 -0.2201 0.0194200515561 -0.0754020782976 -0.22015 0.0173735351621 -0.0753768978356 -0.2202 0.0150674978754 -0.0753512933558 -0.22025 0.0125983403738 -0.0753252268625 -0.2203 0.0100340385716 -0.0752986510823 -0.22035 0.00742377607499 -0.0752715063934 -0.2204 0.00480180492124 -0.0752437172462 -0.22045 0.00219327709895 -0.0752151870459 -0.2205 -0.000384799862115 -0.0751857919976 -0.22055 -0.00291978642781 -0.0751553728133 -0.2206 -0.00540385213807 -0.0751237246685 -0.22065 -0.0078311560053 -0.075090584199 -0.2207 -0.0101989417131 -0.0750556137639 -0.22075 -0.0125051896766 -0.0750183815718 -0.2208 -0.0147500524336 -0.0749783376312 -0.22085 -0.0169337736771 -0.0749347837939 -0.2209 -0.0190583263955 -0.0748868374144 -0.22095 -0.0211254996216 -0.0748333863828 -0.221 -0.0231386606928 -0.0747730343791 -0.22105 -0.0251009402823 -0.0747040333118 -0.2211 -0.0270170520863 -0.0746242007828 -0.22115 -0.0288915099235 -0.0745308183381 -0.2212 -0.0307304396414 -0.0744205068306 -0.22125 -0.0325397657788 -0.0742890728222 -0.2213 -0.0343269557533 -0.0741313200585 -0.22135 -0.0360991186244 -0.0739408171264 -0.2214 -0.0378646219557 -0.0737096118074 -0.22145 -0.0396310308405 -0.073427878856 -0.2215 -0.0414065085998 -0.0730834861814 -0.22155 -0.0431974858841 -0.0726614591625 -0.2216 -0.0450097163627 -0.0721433189967 -0.22165 -0.0468455531832 -0.0715062628177 -0.2217 -0.0487045976631 -0.0707221449687 -0.22175 -0.0505806780781 -0.0697562032256 -0.2218 -0.0524624783791 -0.0685654520854 -0.22185 -0.0543310491109 -0.0670966241102 -0.2219 -0.0561617597123 -0.065283466536 -0.22195 -0.0579240403398 -0.0630430481184 -0.222 -0.0595861781641 -0.0602704120176 -0.22205 -0.0611177306719 -0.0568302039887 -0.2221 -0.0624956492601 -0.052542327203 -0.22215 -0.0637057577153 -0.047155207516 -0.2222 -0.0647456537236 -0.0402934849957 -0.22225 -0.0656218236657 -0.0313595138246 -0.2223 -0.0663487002889 -0.0193970808552 -0.22235 -0.0669437034099 -0.00319449289455 -0.2224 -0.0674261933208 0.0170953435224 -0.22245 -0.067813767744 0.0358960761904 -0.2225 -0.0681229422934 0.0450600813367 -0.22255 -0.0683670104242 0.046515317304 -0.2226 -0.0685578231708 0.04624195737 -0.22265 -0.06870429012 0.0456479516679 -0.2227 -0.0688144422213 0.0448417408509 -0.22275 -0.0688940072458 0.0438260066799 -0.2228 -0.068948428334 0.0426171256089 -0.22285 -0.0689813582917 0.0412134415026 -0.2229 -0.0689965812358 0.0396234017307 -0.22295 -0.0689964258608 0.0378614580843 -0.223 -0.0689836124919 0.0359600030236 -0.22305 -0.0689596135235 0.0339298933285 -0.2231 -0.0689264525991 0.0317897488805 -0.22315 -0.06888503474 0.0295552990765 -0.2232 -0.0688369155944 0.0272430739001 -0.22325 -0.0687826150994 0.0248683379861 -0.2233 -0.0687233673366 0.0224453468964 -0.22335 -0.0686594256814 0.0199872059831 -0.2234 -0.0685917992946 0.0175054624182 -0.22345 -0.0685205543204 0.0150104680892 -0.2235 -0.0684465405158 0.012510964676 -0.22355 -0.0683696911764 0.0100145255602 -0.2236 -0.068290742003 0.00752727380506 -0.22365 -0.0682095313969 0.0050542716727 -0.2237 -0.0681267128713 0.00259936600128 -0.22375 -0.0680420567505 0.000165491205095 -0.2238 -0.0679561569856 -0.00224539958521 -0.22385 -0.0678687349361 -0.00463212284891 -0.2239 -0.0677803411686 -0.00699429592661 -0.22395 -0.0676906617768 -0.00933222102691 -0.224 -0.0676002155653 -0.0116469308588 -0.22405 -0.0675086632253 -0.0139401875465 -0.2241 -0.0674165001765 -0.0162146042367 -0.22415 -0.0673233688301 -0.0184737994949 -0.2242 -0.0672297472847 -0.0207226685213 -0.22425 -0.0671352648233 -0.0229677522899 -0.2243 -0.0670403866182 -0.0252177363764 -0.22435 -0.066944732569 -0.0274840944785 -0.2244 -0.066848758115 -0.0297818708673 -0.22445 -0.0667520764906 -0.0321306106663 -0.2245 -0.0666551357278 -0.0345553612348 -0.22455 -0.0665575443804 -0.0370876257338 -0.2246 -0.0664597447721 -0.0397658995287 -0.22465 -0.0663613422209 -0.0426350800669 -0.2247 -0.0662627745809 -0.0457432899016 -0.22475 -0.0661636449922 -0.0491336179593 -0.2248 -0.0660643877486 -0.0528271066579 -0.22485 -0.0659646045868 -0.0567936837343 -0.2249 -0.0658647269049 -0.0609137560365 -0.22495 -0.0657643556002 -0.0649509783124 -0.225 -0.0656639196623 -0.0685811384853 -0.22505 -0.0655630195621 -0.0715099504114 -0.2251 -0.0654620822375 -0.0736169005684 -0.22515 -0.0653607080345 -0.0749886611375 -0.2252 -0.0652593221006 -0.075820509334 -0.22525 -0.0651575248742 -0.0763046684877 -0.2253 -0.0650557399001 -0.0765815905218 -0.22535 -0.0649535678655 -0.0767396814392 -0.2254 -0.0648514308483 -0.0768305662266 -0.22545 -0.0647489298952 -0.076883393309 -0.2255 -0.0646464857128 -0.0769144581218 -0.22555 -0.0645436997825 -0.0769328994289 -0.2256 -0.0644409915056 -0.0769438972727 -0.22565 -0.0643379628472 -0.0769504283628 -0.2257 -0.0642350319442 -0.0769542311427 -0.22575 -0.0641318012737 -0.0769563364212 -0.2258 -0.0640286877329 -0.0769573661352 -0.22585 -0.0639252943257 -0.0769577005164 -0.2259 -0.0638220367241 -0.0769575763666 -0.22595 -0.0637185184657 -0.0769571424426 -0.226 -0.0636151540055 -0.076956494251 -0.22605 -0.0635115474174 -0.0769556931084 -0.2261 -0.0634081119449 -0.0769547795725 -0.22615 -0.0633044521981 -0.0769537800341 -0.2262 -0.0632009802104 -0.0769527124858 -0.22625 -0.0630973011233 -0.0769515886322 -0.2263 -0.0629938257566 -0.0769504167154 -0.22635 -0.0628901597737 -0.0769492019668 -0.2264 -0.0627867127728 -0.0769479482066 -0.22645 -0.0626830909253 -0.0769466576871 -0.2265 -0.0625797025958 -0.0769453321269 -0.22655 -0.0624761544459 -0.0769439723508 -0.2266 -0.0623728535917 -0.0769425790283 -0.22665 -0.0622694071659 -0.0769411522727 -0.2267 -0.0621662210194 -0.0769396922014 -0.22675 -0.0620629027351 -0.0769381985571 -0.2268 -0.0619598568823 -0.0769366711477 -0.22685 -0.0618566914733 -0.0769351095123 -0.2269 -0.061753809779 -0.076933513271 -0.22695 -0.0616508202212 -0.0769318818427 -0.227 -0.061548124756 -0.0769302147227 -0.22705 -0.0614453321947 -0.0769285112508 -0.2271 -0.0613428431632 -0.0769267708309 -0.22715 -0.0612402668439 -0.0769249927441 -0.2272 -0.0611380025176 -0.0769231763201 -0.22725 -0.06103565972 -0.0769213207906 -0.2273 -0.0609336363735 -0.0769194254204 -0.22735 -0.0608315423499 -0.0769174893948 -0.2274 -0.0607297742007 -0.0769155119182 -0.22745 -0.060627942118 -0.07691349213 -0.2275 -0.06052644127 -0.076911429176 -0.22755 -0.0604248821538 -0.0769093221481 -0.2276 -0.0603236585429 -0.0769071701339 -0.22765 -0.0602223812244 -0.0769049721753 -0.2277 -0.060121442566 -0.0769027273016 -0.22775 -0.0600204536306 -0.0769004345022 -0.2278 -0.0599198053694 -0.0768980927468 -0.22785 -0.0598191091068 -0.0768957009695 -0.2279 -0.0597187543677 -0.0768932580795 -0.22795 -0.0596183527241 -0.0768907629533 -0.228 -0.0595182922642 -0.0768882144385 -0.22805 -0.0594181847936 -0.0768856113518 -0.2281 -0.0593184169528 -0.0768829524779 -0.22815 -0.0592186007666 -0.0768802365717 -0.2282 -0.0591191214165 -0.0768774623547 -0.22825 -0.0590195911312 -0.0768746285182 -0.2283 -0.0589203936216 -0.0768717337198 -0.22835 -0.0588211413046 -0.0768687765866 -0.2284 -0.0587222164074 -0.0768657557119 -0.22845 -0.0586232315176 -0.0768626696581 -0.2285 -0.0585245673639 -0.0768595169546 -0.22855 -0.0584258366847 -0.0768562960989 -0.2286 -0.0583274186933 -0.0768530055572 -0.22865 -0.0582289262583 -0.076849643763 -0.2287 -0.0581307370589 -0.0768462091203 -0.22875 -0.0580324640698 -0.0768426999994 -0.2288 -0.0579344834131 -0.0768391147438 -0.22885 -0.0578364081415 -0.0768354516626 -0.2289 -0.0577386127936 -0.0768317090409 -0.22895 -0.057640710469 -0.0768278851292 -0.229 -0.0575430740936 -0.0768239781568 -0.22905 -0.0574453167776 -0.0768199863179 -0.2291 -0.0573478097969 -0.0768159077893 -0.22915 -0.0572501662291 -0.0768117407124 -0.2292 -0.0571527556589 -0.076807483215 -0.22925 -0.0570551910832 -0.0768031333894 -0.2293 -0.0569578403467 -0.0767986893185 -0.22935 -0.0568603163083 -0.07679414905 -0.2294 -0.0567629850131 -0.0767895106261 -0.22945 -0.0566654591153 -0.0767847720546 -0.2295 -0.0565681027939 -0.0767799313419 -0.22955 -0.0564705284227 -0.0767749864614 -0.2296 -0.0563730982338 -0.0767699353891 -0.22965 -0.0562754242295 -0.0767647760694 -0.2297 -0.0561778666007 -0.0767595064533 -0.22975 -0.0560800368741 -0.0767541244619 -0.2298 -0.0559822930913 -0.0767486280269 -0.22985 -0.0558842461815 -0.0767430150521 -0.2299 -0.0557862519066 -0.0767372834559 -0.22995 -0.0556879204539 -0.0767314311307 -0.23 -0.0555896051553 -0.0767254559877 -0.23005 -0.0554909152905 -0.0767193559146 -0.2301 -0.0553922015842 -0.0767131288222 -0.23015 -0.055293072213 -0.0767067725998 -0.2302 -0.0551938750841 -0.0767002851636 -0.23025 -0.05509421704 -0.0766936644107 -0.2303 -0.0549944429257 -0.0766869082691 -0.23035 -0.0548941579809 -0.0766800146501 -0.2304 -0.0547937036989 -0.0766729814992 -0.23045 -0.0546926833974 -0.076665806748 -0.2305 -0.054591434874 -0.0766584883665 -0.23055 -0.0544895591476 -0.0766510243131 -0.2306 -0.054387389913 -0.0766434125874 -0.23065 -0.0542845254445 -0.0766356511804 -0.2307 -0.0541812948517 -0.0766277381269 -0.23075 -0.0540772931329 -0.0766196714553 -0.2308 -0.0539728442347 -0.0766114492412 -0.23085 -0.0538675392442 -0.0766030695567 -0.2309 -0.0537616962532 -0.0765945305233 -0.23095 -0.0536549016761 -0.0765858302612 -0.231 -0.0535474669178 -0.0765769669423 -0.23105 -0.0534389728027 -0.076567938739 -0.2311 -0.0533297230426 -0.0765587438774 -0.23115 -0.0532192917612 -0.0765493805868 -0.2312 -0.0531079737557 -0.0765398471519 -0.23125 -0.0529953350966 -0.0765301418623 -0.2313 -0.0528816601755 -0.0765202630641 -0.23135 -0.0527665053542 -0.0765102091096 -0.2314 -0.0526501427843 -0.0764999784086 -0.23145 -0.0525321170809 -0.0764895693797 -0.2315 -0.0524126858894 -0.0764789804991 -0.23155 -0.0522913795485 -0.0764682102528 -0.2316 -0.0521684383798 -0.0764572571844 -0.23165 -0.0520433752898 -0.0764461198477 -0.2317 -0.0519164097399 -0.0764347968555 -0.23175 -0.0517870332339 -0.0764232868312 -0.2318 -0.0516554399089 -0.0764115884558 -0.23185 -0.0515210948264 -0.076399700421 -0.2319 -0.0513841611107 -0.0763876214757 -0.23195 -0.0512440709361 -0.0763753503798 -0.232 -0.0511009491011 -0.0763628859489 -0.23205 -0.0509541865703 -0.0763502270086 -0.2321 -0.0508038603202 -0.0763373724381 -0.23215 -0.0506493092441 -0.0763243211265 -0.2322 -0.0504905500448 -0.0763110720143 -0.23225 -0.0503268552152 -0.0762976240499 -0.2323 -0.0501581646633 -0.0762839762297 -0.23235 -0.0499836653601 -0.076270127557 -0.2324 -0.049803198224 -0.0762560770802 -0.23245 -0.0496158388508 -0.0762418238507 -0.2325 -0.0494212989632 -0.0762273669607 -0.23255 -0.0492185073509 -0.0762127055034 -0.2326 -0.0490070048238 -0.0761978386081 -0.23265 -0.0487855240649 -0.0761827653996 -0.2327 -0.048553376464 -0.0761674850335 -0.23275 -0.0483090288733 -0.076151996657 -0.2328 -0.048051479807 -0.0761362994409 -0.23285 -0.0477788299291 -0.0761203925404 -0.2329 -0.047489643637 -0.0761042751276 -0.23295 -0.0471815082 -0.0760879463522 -0.233 -0.0468523742617 -0.0760714053697 -0.23305 -0.0464990953388 -0.0760546513051 -0.2331 -0.0461187365513 -0.0760376832792 -0.23315 -0.0457070806411 -0.07602050037 -0.2332 -0.0452598869618 -0.0760031016379 -0.23325 -0.0447713405332 -0.0759854860886 -0.2333 -0.0442352306219 -0.0759676526932 -0.23335 -0.043643302667 -0.0759496003511 -0.2334 -0.0429863039547 -0.0759313279094 -0.23345 -0.0422521701426 -0.0759128341217 -0.2335 -0.0414268502098 -0.0758941176648 -0.23355 -0.0404922168918 -0.0758751770982 -0.2336 -0.0394265366099 -0.075856010873 -0.23365 -0.0382019523469 -0.0758366172903 -0.2337 -0.036784453687 -0.0758169945061 -0.23375 -0.0351308552724 -0.0757971404823 -0.2338 -0.0331883962921 -0.0757770529872 -0.23385 -0.0308918363006 -0.0757567295406 -0.2339 -0.0281643482858 -0.0757361674021 -0.23395 -0.0249184078792 -0.0757153635101 -0.234 -0.0210651690028 -0.0756943144547 -0.23405 -0.016531613647 -0.0756730164034 -0.2341 -0.0112965423134 -0.0756514650561 -0.23415 -0.00544171920101 -0.0756296555463 -0.2342 0.00078994493583 -0.07560758237 -0.23425 0.00697506420843 -0.0755852392513 -0.2343 0.012575259128 -0.0755626190254 -0.23435 0.0170948169049 -0.0755397134493 -0.2344 0.0202386405748 -0.0755165130072 -0.23445 0.0219711982609 -0.0754930066279 -0.2345 0.0224550366099 -0.0754691813591 -0.23455 0.0219438652439 -0.0754450219147 -0.2346 0.0206942634959 -0.0754205101189 -0.23465 0.0189237419334 -0.075395624142 -0.2347 0.0167990813394 -0.0753703375237 -0.23475 0.0144431907725 -0.0753446178398 -0.2348 0.011943714611 -0.0753184249624 -0.23485 0.00936368130565 -0.0752917087126 -0.2349 0.00674739886137 -0.075264405791 -0.23495 0.00412700156187 -0.0752364357157 -0.235 0.00152475851066 -0.0752076955751 -0.23505 -0.001043054944 -0.0751780532471 -0.2351 -0.00356570780403 -0.0751473387994 -0.23515 -0.00603541239813 -0.0751153336242 -0.2352 -0.00844773650133 -0.0750817568875 -0.23525 -0.010799605804 -0.075046248691 -0.2353 -0.0130901437334 -0.0750083493051 -0.23535 -0.0153189969814 -0.0749674735967 -0.2354 -0.0174874190445 -0.0749228796541 -0.23545 -0.0195967930564 -0.0748736302806 -0.2355 -0.0216498667699 -0.0748185457982 -0.23555 -0.0236493976274 -0.0747561461417 -0.2356 -0.025599470559 -0.0746845798303 -0.23565 -0.0275041985552 -0.0746015367517 -0.2357 -0.0293690577107 -0.0745041410571 -0.23575 -0.031199578497 -0.0743888195233 -0.2358 -0.033002635805 -0.0742511397314 -0.23585 -0.034785072367 -0.074085611006 -0.2359 -0.0365548863936 -0.0738854394757 -0.23595 -0.0383197246774 -0.0736422264818 -0.236 -0.0400878926333 -0.0733455970419 -0.23605 -0.0418666228836 -0.0729827417298 -0.2361 -0.0436627919551 -0.0725378511942 -0.23615 -0.0454808329321 -0.0719914169654 -0.2362 -0.0473230453269 -0.0713193647893 -0.23625 -0.0491871208021 -0.0704919760788 -0.2363 -0.0510662001048 -0.0694725370701 -0.23635 -0.0529465003523 -0.0682156289791 -0.2364 -0.0548080814301 -0.0666649258998 -0.23645 -0.0566240369777 -0.0647502778115 -0.2365 -0.0583636923978 -0.0623836735865 -0.23655 -0.0599946971366 -0.0594532872387 -0.2366 -0.0614886569874 -0.0558139429219 -0.23665 -0.062824038181 -0.0512703920159 -0.2367 -0.0639902229358 -0.045545601387 -0.23675 -0.0649867553135 -0.038218604208 -0.2368 -0.0658230027998 -0.0286118407047 -0.23685 -0.0665139383486 -0.0156669291133 -0.2369 -0.0670782528519 0.00174276941676 -0.23695 -0.0675344691785 0.0224701158673 -0.237 -0.0679005081769 0.0393383806748 -0.23705 -0.0681915395669 0.0458606404547 -0.2371 -0.0684210002966 0.0464864036989 -0.23715 -0.0685994245835 0.0461079754904 -0.2372 -0.0687359931949 0.0454527669105 -0.23725 -0.0688375852441 0.0445929885771 -0.2373 -0.0689103582986 0.0435251027916 -0.23735 -0.0689587459693 0.0422659334342 -0.2374 -0.0689869457568 0.0408124226804 -0.23745 -0.0689978273589 0.0391749956214 -0.2375 -0.0689943363645 0.0373749496447 -0.23755 -0.0689783382012 0.0354388675292 -0.2376 -0.0689519659746 0.0333782487515 -0.23765 -0.068916425818 0.0312123119355 -0.2377 -0.0688733102071 0.028956051747 -0.23775 -0.0688233815182 0.0266263989381 -0.2378 -0.0687678637482 0.0242378816667 -0.23785 -0.0687072140699 0.0218048018421 -0.2379 -0.0686424003721 0.0193396367125 -0.23795 -0.0685736664132 0.0168537655852 -0.238 -0.0685017994472 0.0143570249436 -0.23805 -0.0684268922287 0.0118578944244 -0.2381 -0.0683496032495 0.00936353526944 -0.23815 -0.0682699175602 0.00687978933216 -0.2382 -0.0681884011641 0.004411396902 -0.23825 -0.0681049618774 0.0019619435252 -0.2383 -0.0680200988815 -0.000465884100302 -0.23835 -0.067933664415 -0.00287036073092 -0.2384 -0.0678461091456 -0.00525049692164 -0.23845 -0.0677572452272 -0.00760611090141 -0.2385 -0.0676674879474 -0.00993767488159 -0.23855 -0.0675766205104 -0.0122464228916 -0.2386 -0.0674850322813 -0.0145343093326 -0.23865 -0.0673924855511 -0.0168042026133 -0.2387 -0.0672993505921 -0.0190600092381 -0.23875 -0.0672053745917 -0.0213070213017 -0.2388 -0.0671109136827 -0.0235522708946 -0.23885 -0.0670157041621 -0.0258051063737 -0.2389 -0.0669200916139 -0.0280778356789 -0.23895 -0.0668238045076 -0.0303865802297 -0.239 -0.0667271804964 -0.0327522040726 -0.23905 -0.0666299424512 -0.0352013457509 -0.2391 -0.0665324219995 -0.0377672874948 -0.23915 -0.066434338039 -0.0404903102872 -0.2392 -0.0663360175661 -0.0434165940155 -0.23925 -0.0662371766953 -0.0465940300865 -0.2393 -0.0661381388093 -0.0500620711773 -0.23935 -0.0660386181075 -0.0538318314028 -0.2394 -0.0659389351043 -0.0578538642071 -0.23945 -0.0658388027197 -0.0619796606035 -0.2395 -0.0657385391474 -0.0659439255498 -0.23955 -0.0656378564937 -0.0694157095919 -0.2396 -0.0655370710314 -0.072134125975 -0.23965 -0.0654358943905 -0.07403565996 -0.2397 -0.065334641215 -0.0752474617409 -0.23975 -0.0652330229055 -0.0759725840418 -0.2398 -0.0651313526889 -0.0763919116975 -0.23985 -0.0650293419144 -0.0766313487499 -0.2399 -0.0649273025459 -0.0767682007905 -0.23995 -0.064824946008 -0.0768470814366 -0.24 -0.0647225831098 -0.0768930714415 -0.24005 -0.0646199254387 -0.0769201902626 -0.2401 -0.0645172827238 -0.0769363176148 -0.24015 -0.0644143667736 -0.0769459349091 -0.2402 -0.0643114862862 -0.0769516276761 -0.24025 -0.064208353327 -0.0769549120526 -0.2403 -0.0641052755932 -0.0769566908843 -0.24035 -0.0640019654267 -0.0769575109967 -0.2404 -0.0638987295407 -0.0769577081311 -0.24045 -0.0637952805642 -0.0769574920441 -0.2405 -0.0636919242357 -0.0769569950903 -0.24055 -0.0635883734756 -0.0769563024085 -0.2406 -0.0634849330535 -0.0769554689447 -0.24065 -0.0633813161822 -0.0769545310264 -0.2407 -0.0632778266648 -0.0769535124624 -0.24075 -0.063174178004 -0.0769524294038 -0.2408 -0.0630706730344 -0.0769512924793 -0.24085 -0.0629670255415 -0.0769501090693 -0.2409 -0.0628635373847 -0.0769488839564 -0.24095 -0.0627599226206 -0.0769476205222 -0.241 -0.0626564821217 -0.0769463208419 -0.24105 -0.0625529302003 -0.0769449863863 -0.2411 -0.0624495667282 -0.0769436179253 -0.24115 -0.0623461062547 -0.076942215971 -0.2412 -0.0622428476341 -0.0769407806385 -0.24125 -0.0621395056327 -0.0769393119316 -0.2413 -0.0620363780696 -0.0769378096224 -0.24135 -0.0619331799085 -0.0769362734265 -0.2414 -0.0618302079155 -0.0769347029266 -0.24145 -0.0617271772313 -0.0769330976612 -0.2415 -0.0616243835526 -0.0769314571003 -0.24155 -0.0615215421777 -0.0769297806621 -0.2416 -0.0614189477173 -0.0769280677428 -0.24165 -0.0613163156092 -0.0769263176701 -0.2417 -0.0612139393631 -0.0769245297853 -0.24175 -0.0611115345385 -0.076922703341 -0.2418 -0.0610093935295 -0.0769208376326 -0.24185 -0.0609072320008 -0.0769189318457 -0.2419 -0.0608053412171 -0.0769169852325 -0.24195 -0.0607034369322 -0.0769149969154 -0.242 -0.0606018092686 -0.0769129661037 -0.24205 -0.060500174054 -0.0769108918581 -0.2421 -0.0603988202565 -0.0769087733434 -0.24215 -0.0602974637631 -0.0769066095589 -0.2422 -0.0601963923761 -0.0769043996225 -0.24225 -0.0600953220282 -0.0769021424716 -0.2423 -0.0599945393447 -0.0768998371743 -0.24235 -0.0598937602902 -0.0768974826054 -0.2424 -0.0597932703018 -0.0768950777804 -0.24245 -0.0596927853628 -0.0768926215105 -0.2425 -0.0595925897109 -0.0768901127561 -0.24255 -0.0594923993346 -0.0768875502639 -0.2426 -0.0593924972612 -0.0768849329368 -0.24265 -0.0592925994705 -0.0768822594562 -0.2427 -0.0591929877688 -0.0768795286652 -0.24275 -0.0590933781126 -0.0768767391797 -0.2428 -0.0589940510748 -0.076873889781 -0.24285 -0.0588947225741 -0.0768709790195 -0.2429 -0.0587956719358 -0.0768680056136 -0.24295 -0.058696615024 -0.076864968048 -0.243 -0.0585978299027 -0.0768618649776 -0.24305 -0.0584990323638 -0.0768586948223 -0.2431 -0.0584004991937 -0.0768554561729 -0.24315 -0.0583019460918 -0.0768521473858 -0.2432 -0.058203648548 -0.0768487669881 -0.24325 -0.0581053221461 -0.0768453132739 -0.2433 -0.0580072410574 -0.0768417847076 -0.24335 -0.0579091207254 -0.076838179523 -0.2434 -0.0578112339786 -0.0768344961233 -0.24345 -0.0577132960904 -0.0768307326849 -0.2435 -0.0576155785163 -0.0768268875517 -0.24355 -0.0575177963248 -0.0768229588456 -0.2436 -0.0574202195643 -0.0768189448539 -0.24365 -0.0573225630601 -0.0768148436473 -0.2437 -0.0572250954141 -0.0768106534596 -0.24375 -0.0571275311621 -0.0768063723142 -0.2438 -0.0570301374112 -0.0768019983951 -0.24385 -0.0569326283535 -0.0767975296828 -0.2439 -0.0568352695474 -0.0767929643156 -0.24395 -0.0567377747808 -0.0767883002357 -0.244 -0.0566404079985 -0.0767835355403 -0.24405 -0.0565428825102 -0.0767786681384 -0.2441 -0.0564454605703 -0.0767736960915 -0.24415 -0.0563478549271 -0.0767686172811 -0.2442 -0.0562503260572 -0.0767634297379 -0.24425 -0.056152586049 -0.0767581313219 -0.2443 -0.0560548934966 -0.0767527200384 -0.24435 -0.0559569597121 -0.0767471937315 -0.2444 -0.0558590412851 -0.0767415503876 -0.24445 -0.0557608486188 -0.0767357878407 -0.2445 -0.055662636156 -0.0767299040639 -0.24455 -0.0555641132337 -0.0767238968877 -0.2446 -0.0554655319788 -0.0767177642786 -0.24465 -0.0553666004767 -0.0767115040701 -0.2447 -0.0552675683427 -0.0767051142284 -0.24475 -0.0551681421964 -0.0766985925962 -0.2448 -0.0550685689096 -0.0766919371453 -0.24485 -0.0549685533817 -0.0766851457338 -0.2449 -0.0548683394669 -0.0766782163456 -0.24495 -0.054767630044 -0.07667114686 -0.245 -0.0546666656283 -0.0766639352794 -0.24505 -0.0545651467264 -0.0766565795111 -0.2451 -0.054463310132 -0.076649077582 -0.24515 -0.0543608535608 -0.076641427433 -0.2452 -0.0542580096309 -0.076633627121 -0.24525 -0.054154472769 -0.0766256746258 -0.2453 -0.0540504708762 -0.0766175680396 -0.24535 -0.0539456944964 -0.0766093053866 -0.2454 -0.0538403661679 -0.0766008848004 -0.24545 -0.0537341718417 -0.0765923043548 -0.2455 -0.0536273279156 -0.0765835622291 -0.24555 -0.0535195148927 -0.0765746565507 -0.2456 -0.0534109420926 -0.0765655855488 -0.24565 -0.0533012835364 -0.0765563474085 -0.2457 -0.0531907403297 -0.0765469404137 -0.24575 -0.0530789787558 -0.0765373628114 -0.2458 -0.0529661903207 -0.0765276129433 -0.24585 -0.0528520320351 -0.0765176891207 -0.2459 -0.0527366841085 -0.0765075897456 -0.24595 -0.0526197923934 -0.0764973131964 -0.246 -0.0525015237101 -0.0764868579388 -0.24605 -0.0523815104212 -0.0764762224206 -0.2461 -0.0522599033598 -0.0764654051723 -0.24615 -0.0521363184948 -0.0764544047116 -0.2462 -0.0520108874231 -0.0764432196348 -0.24625 -0.0518832060762 -0.0764318485313 -0.2463 -0.0517533827229 -0.0764202900643 -0.24635 -0.0516209886533 -0.076408542894 -0.2464 -0.0514861036138 -0.0763966057492 -0.24645 -0.0513482683738 -0.0763844773603 -0.2465 -0.0512075275024 -0.0763721565221 -0.24655 -0.0510633836899 -0.0763596420334 -0.2466 -0.0509158377193 -0.0763469327521 -0.24665 -0.0507643443709 -0.0763340275425 -0.2467 -0.0506088493981 -0.0763209253237 -0.24675 -0.0504487467613 -0.0763076250228 -0.2468 -0.0502839123244 -0.0762941256151 -0.24685 -0.0501136620728 -0.0762804260854 -0.2469 -0.0499377821205 -0.0762665254615 -0.24695 -0.0497554874004 -0.0762524227809 -0.247 -0.0495664473737 -0.0762381171167 -0.24705 -0.0493697444528 -0.0762236075513 -0.2471 -0.0491648945043 -0.0762088931969 -0.24715 -0.0489508038875 -0.0761939731735 -0.2472 -0.048726783369 -0.0761788466213 -0.24725 -0.0484915020608 -0.0761635126876 -0.2473 -0.048243992631 -0.0761479705319 -0.24735 -0.0479825994577 -0.0761322193161 -0.2474 -0.0477059717855 -0.0761162582045 -0.24745 -0.0474120018624 -0.0761000863602 -0.2475 -0.0470988006239 -0.0760837029381 -0.24755 -0.0467636189216 -0.0760671070836 -0.2476 -0.0464037968962 -0.0760502979231 -0.24765 -0.0460156568745 -0.0760332745658 -0.2477 -0.0455954116348 -0.0760160360862 -0.24775 -0.0451380097097 -0.0759985815315 -0.2478 -0.044637977416 -0.0759809098988 -0.24785 -0.044088183657 -0.0759630201425 -0.2479 -0.0434805726898 -0.0759449111479 -0.24795 -0.0428047922128 -0.0759265817414 -0.248 -0.0420487439007 -0.0759080306553 -0.24805 -0.0411969813405 -0.0758892565406 -0.2481 -0.0402309614553 -0.075870257927 -0.24815 -0.0391270724568 -0.0758510332325 -0.2482 -0.0378564331083 -0.0758315807184 -0.24825 -0.0363824152902 -0.075811898498 -0.2483 -0.0346599497758 -0.0757919844802 -0.24835 -0.0326327642284 -0.0757718363784 -0.2484 -0.0302330195798 -0.0757514516425 -0.24845 -0.0273803332202 -0.0757308274597 -0.2485 -0.0239861635043 -0.0757099606768 -0.24855 -0.0199630083277 -0.0756888477875 -0.2486 -0.0152475612639 -0.0756674848377 -0.24865 -0.00983914391438 -0.0756458673974 -0.2487 -0.00385657797336 -0.0756239904368 -0.24875 0.00241033906448 -0.0756018482735 -0.2488 0.00849749280922 -0.0755794344073 -0.24885 0.0138607338403 -0.0755567414224 -0.2489 0.0180431083915 -0.0755337607603 -0.24895 0.0208167415313 -0.0755104825419 -0.249 0.0222060011425 -0.075486895237 -0.24905 0.0224077398977 -0.0754629853477 -0.2491 0.0216825852379 -0.0754387368938 -0.24915 0.020279953634 -0.075414130847 -0.2492 0.0184039434812 -0.0753891442795 -0.24925 0.0162095819479 -0.0753637493446 -0.2493 0.013809298153 -0.0753379118091 -0.24935 0.0112839798433 -0.0753115892135 -0.2494 0.00869081527658 -0.0752847283137 -0.24945 0.00607095235025 -0.0752572618212 -0.2495 0.00345327750376 -0.0752291040158 -0.24955 0.000858712512877 -0.075200145179 -0.2496 -0.00169844926616 -0.0751702443315 -0.24965 -0.00420793606597 -0.075139220137 -0.2497 -0.00666330667742 -0.0751068393444 -0.24975 -0.00906013068632 -0.0750728024952 -0.2498 -0.0113963448917 -0.0750367260944 -0.24985 -0.0136708329041 -0.0749981207409 -0.2499 -0.0158840780115 -0.074956364116 -0.24995 -0.0180369763345 -0.0749106679554 -0.25 -0.0201316710708 -0.0748600374168 diff --git a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/data/moose_sim_dt_1us.dat b/tests/python/Rallpacks/moose_vs_neuron/rallpack3/data/moose_sim_dt_1us.dat deleted file mode 100644 index 92868c37..00000000 --- a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/data/moose_sim_dt_1us.dat +++ /dev/null @@ -1,5001 +0,0 @@ -0.0 -0.06 -0.06 -5e-05 -0.065 -0.065 -0.0001 -0.0651573982953 -0.0651573982953 -0.00015 -0.0591036424217 -0.0653121196769 -0.0002 -0.0591822194374 -0.0654646787991 -0.00025 -0.0563278891296 -0.0656154571713 -0.0003 -0.0564020853705 -0.0657647265834 -0.00035 -0.0543239207478 -0.0659126704885 -0.0004 -0.0543666828076 -0.0660594026542 -0.00045 -0.0526408309359 -0.0662049829289 -0.0005 -0.0526255431122 -0.0663494302985 -0.00055 -0.051074964079 -0.0664927334942 -0.0006 -0.0509711862006 -0.0666348594917 -0.00065 -0.0494875544992 -0.0667757602443 -0.0007 -0.049256372403 -0.066915377962 -0.00075 -0.0477504279954 -0.067053649171 -0.0008 -0.0473361389888 -0.0671905078005 -0.00085 -0.0457107665285 -0.0673258874742 -0.0009 -0.0450251256872 -0.0674597231382 -0.00095 -0.0431465334028 -0.0675919521986 -0.001 -0.042037548584 -0.0677225152247 -0.00105 -0.0396871645011 -0.0678513563734 -0.0011 -0.037874494303 -0.0679784235619 -0.00115 -0.0346536868784 -0.0681036685078 -0.0012 -0.0315954296151 -0.0682270466542 -0.00125 -0.0267426444001 -0.0683485170344 -0.0013 -0.0214149617158 -0.0684680421148 -0.00135 -0.0136234046287 -0.0685855876177 -0.0014 -0.00464302916227 -0.0687011223374 -0.00145 0.00686694262419 -0.0688146179656 -0.0015 0.0182604857943 -0.068926048914 -0.00155 0.0289210834088 -0.0690353921308 -0.0016 0.035762336258 -0.0691426269066 -0.00165 0.040024674026 -0.0692477346577 -0.0017 0.0412493105396 -0.0693506986768 -0.00175 0.0416985139673 -0.069451503832 -0.0018 0.0406519936586 -0.0695501361922 -0.00185 0.039698721961 -0.069646582548 -0.0019 0.0377610445579 -0.0697408297831 -0.00195 0.0361709789292 -0.0698328640318 -0.002 0.0337834093539 -0.069922669551 -0.00205 0.0318321782489 -0.0700102271848 -0.0021 0.0291848138249 -0.0700955122886 -0.00215 0.027018553543 -0.0701784919637 -0.0022 0.024228186541 -0.0702591214285 -0.00225 0.0219458831725 -0.0703373393262 -0.0023 0.0190954356876 -0.0704130618006 -0.00235 0.0167689029044 -0.0704861750935 -0.0024 0.0139182412842 -0.0705565264471 -0.00245 0.0115987714138 -0.0706239129837 -0.0025 0.00878947118745 -0.0706880681828 -0.00255 0.00651182530842 -0.0707486454594 -0.0026 0.00377080520548 -0.0708051981847 -0.00265 0.00155669053545 -0.0708571553388 -0.0027 -0.00110046622333 -0.0709037917609 -0.00275 -0.00323922833141 -0.070944191714 -0.0028 -0.00580533148831 -0.0709772041726 -0.00285 -0.00786411705272 -0.0710013878686 -0.0029 -0.0103380088604 -0.0710149436723 -0.00295 -0.0123173919891 -0.0710156313335 -0.003 -0.0147023809745 -0.0710006668947 -0.00305 -0.0166070380364 -0.070966596264 -0.0031 -0.0189103388592 -0.0709091393554 -0.00315 -0.0207490508594 -0.0708229979162 -0.0032 -0.0229823817638 -0.070701618527 -0.00325 -0.0247692043642 -0.0705369002411 -0.0033 -0.0269504831874 -0.0703188337978 -0.00335 -0.0287068503117 -0.0700350561112 -0.0034 -0.030862541673 -0.0696702996104 -0.00345 -0.0326196124376 -0.0692057105205 -0.0035 -0.0347867681623 -0.0686180026913 -0.00355 -0.0365867352173 -0.0678784027528 -0.0036 -0.038812995704 -0.0669513257234 -0.00365 -0.0407069210879 -0.06579269252 -0.0037 -0.0430449248854 -0.0643477513545 -0.00375 -0.0450818499873 -0.0625481705299 -0.0038 -0.0475705078166 -0.0603079802575 -0.00385 -0.0497678254975 -0.0575175451192 -0.0039 -0.0523891213806 -0.0540339073639 -0.00395 -0.0546755657356 -0.0496640673696 -0.004 -0.0572897385072 -0.044134277283 -0.00405 -0.0594494988938 -0.0370332164499 -0.0041 -0.0617775135413 -0.0277189692028 -0.00415 -0.0635057211943 -0.0152470901678 -0.0042 -0.0652765939586 0.00126419291625 -0.00425 -0.0663951448434 0.0206125044677 -0.0043 -0.0675580472995 0.036690861629 -0.00435 -0.0681363573481 0.0438018186689 -0.0044 -0.0688430931172 0.0449617354689 -0.00445 -0.0690666506643 0.0446182642931 -0.0045 -0.0694984336858 0.0438661256791 -0.00455 -0.0695224334429 0.0428521204893 -0.0046 -0.0698022758855 0.041598240057 -0.00465 -0.0697191932418 0.0401269884479 -0.0047 -0.0699149767617 0.0384496499752 -0.00475 -0.0697736956061 0.0366078990803 -0.0048 -0.0699207943195 0.0346165154838 -0.00485 -0.0697467451962 0.032496368128 -0.0049 -0.069863854269 0.030266321406 -0.00495 -0.0696706696752 0.0279452878307 -0.005 -0.0697680992038 0.0255511277641 -0.00505 -0.0695634194131 0.0231002727771 -0.0051 -0.0696471404296 0.0206078821515 -0.00515 -0.0694354394478 0.0180872570807 -0.0052 -0.0695090728485 0.015550275006 -0.00525 -0.069293071359 0.0130069598369 -0.0053 -0.0693589039405 0.010465942874 -0.00535 -0.0691403079343 0.00793420306424 -0.0054 -0.0691998365428 0.00541748113028 -0.00545 -0.0689797421478 0.00292013813106 -0.0055 -0.0690339788578 0.000445501371589 -0.00555 -0.0688131040897 -0.00200421206454 -0.0056 -0.0688627545081 -0.00442762589985 -0.00565 -0.068641577027 -0.00682426261539 -0.0057 -0.0686871481679 -0.00919436223288 -0.00575 -0.0684659897852 -0.0115389687928 -0.0058 -0.0685078572671 -0.013859863884 -0.00585 -0.0682869371558 -0.0161597378686 -0.0059 -0.0683253880879 -0.0184422846073 -0.00595 -0.0681048570191 -0.0207125270677 -0.006 -0.0681401179389 -0.0229771349524 -0.00605 -0.0679200807085 -0.0252449767342 -0.0061 -0.0679523361102 -0.0275277172715 -0.00615 -0.0677328664525 -0.029840642352 -0.0062 -0.067762271247 -0.0322035353552 -0.00625 -0.0675434218759 -0.0346416886105 -0.0063 -0.0675701098968 -0.0371867661237 -0.00635 -0.0673519193368 -0.0398772744974 -0.0064 -0.0673760092003 -0.0427577881413 -0.00645 -0.0671585064737 -0.0458755748162 -0.0065 -0.0671801056711 -0.0492720508268 -0.00655 -0.0669633135275 -0.052965610545 -0.0066 -0.0669825212915 -0.0569228011003 -0.00665 -0.0667664584492 -0.0610212064633 -0.0067 -0.0667833677925 -0.0650248675279 -0.00675 -0.0665680504873 -0.068615790602 -0.0068 -0.0665827496479 -0.0715102806702 -0.00685 -0.0663681926987 -0.0735958948838 -0.0069 -0.0663807661706 -0.0749597487563 -0.00695 -0.0661669837101 -0.075792394812 -0.007 -0.0661775129835 -0.0762810981783 -0.00705 -0.065964518947 -0.0765632636745 -0.0071 -0.0659730830307 -0.0767259690664 -0.00715 -0.0657608914667 -0.0768204775849 -0.0072 -0.065767567254 -0.0768759915196 -0.00725 -0.0655561925105 -0.0769089869429 -0.0073 -0.0655610550285 -0.076928792807 -0.00735 -0.0653505118442 -0.0769407457773 -0.0074 -0.0653536344149 -0.0769479431568 -0.00745 -0.0651439379405 -0.0769522088213 -0.0075 -0.0651453922729 -0.0769546359574 -0.00755 -0.0649365580367 -0.0769558879428 -0.0076 -0.0649364142678 -0.0769563759239 -0.00765 -0.0647284581086 -0.0769563558941 -0.0077 -0.064726784815 -0.0769559922008 -0.00775 -0.0645197227989 -0.0769553888835 -0.0078 -0.0645165869952 -0.0769546155715 -0.00785 -0.0643104353284 -0.076953716296 -0.0079 -0.0643059024576 -0.0769527222857 -0.00795 -0.0641006773963 -0.0769516525884 -0.008 -0.0640948113107 -0.0769505220511 -0.00805 -0.0638905290621 -0.0769493388037 -0.0081 -0.0638833919881 -0.0769481103634 -0.00815 -0.063680068599 -0.0769468398739 -0.0082 -0.0636717210852 -0.0769455314184 -0.00825 -0.0634693723172 -0.0769441857714 -0.0083 -0.0634598731672 -0.0769428053297 -0.00835 -0.0632585143625 -0.0769413897026 -0.0084 -0.063247920556 -0.0769399404141 -0.00845 -0.0630475664973 -0.0769384564829 -0.0085 -0.0630359331047 -0.0769369389516 -0.00855 -0.062836597873 -0.0769353865326 -0.0086 -0.0628239779671 -0.0769337999803 -0.00865 -0.0626256748016 -0.0769321778449 -0.0087 -0.0626121193696 -0.0769305206909 -0.00875 -0.0624148605314 -0.0769288269815 -0.0088 -0.0624004183885 -0.0769270971409 -0.00885 -0.0622042150298 -0.0769253295848 -0.0089 -0.0621889327356 -0.0769235246231 -0.00895 -0.0619937947735 -0.0769216806445 -0.009 -0.061977716553 -0.0769197978578 -0.00905 -0.0617836525498 -0.076917874635 -0.0091 -0.0617668202166 -0.0769159110901 -0.00915 -0.061573837266 -0.0769139055828 -0.0092 -0.0615562901497 -0.0769118581353 -0.00925 -0.0613643937685 -0.0769097670959 -0.0093 -0.0613461686468 -0.0769076323959 -0.00935 -0.0611553626719 -0.0769054523716 -0.0094 -0.0611364937049 -0.0769032268632 -0.00945 -0.0609467801959 -0.0769009541928 -0.0095 -0.0609272988646 -0.0768986341094 -0.00955 -0.0607386780115 -0.0768962649179 -0.0096 -0.0607186130597 -0.0768938462754 -0.00965 -0.0605310830948 -0.076891376467 -0.0097 -0.0605104604737 -0.0768888550571 -0.00975 -0.060324017588 -0.0768862803083 -0.0098 -0.0603028604024 -0.0768836516919 -0.00985 -0.0601174986649 -0.0768809674446 -0.0099 -0.0600958271219 -0.0768782269447 -0.00995 -0.0599115384012 -0.0768754284004 -0.01 -0.0598893697594 -0.0768725710967 -0.01005 -0.059706143648 -0.0768696532113 -0.0101 -0.0596834921669 -0.0768666739365 -0.01015 -0.0595013159057 -0.076863631417 -0.0102 -0.0594781927944 -0.0768605247535 -0.01025 -0.0592970511968 -0.0768573520564 -0.0103 -0.0592734645604 -0.076854112336 -0.01035 -0.0590933399353 -0.0768508036672 -0.0104 -0.0590692947186 -0.0768474249715 -0.01045 -0.0588901667902 -0.0768439742879 -0.0105 -0.058865664716 -0.0768404504515 -0.01055 -0.0586875105376 -0.076836851465 -0.0106 -0.0586625500366 -0.07683317608 -0.01065 -0.0584853438974 -0.076829422264 -0.0107 -0.05845992003 -0.0768255886881 -0.01075 -0.0582836333515 -0.0768216732854 -0.0108 -0.0582577377176 -0.0768176746501 -0.01085 -0.0580823389409 -0.0768135906826 -0.0109 -0.0580559595782 -0.0768094199046 -0.01095 -0.0578814140357 -0.0768051601856 -0.011 -0.0578545352986 -0.0768008099794 -0.01105 -0.0576808050665 -0.0767963671277 -0.0111 -0.0576534074841 -0.0767918300209 -0.01115 -0.0574804512112 -0.076787196476 -0.0112 -0.05745251132 -0.0767824648256 -0.01125 -0.0572802840343 -0.0767776328658 -0.0113 -0.0572517741857 -0.0767726988773 -0.01135 -0.0570802270699 -0.0767676606394 -0.0114 -0.057051115201 -0.076762516387 -0.01145 -0.056880195329 -0.0767572638869 -0.0115 -0.0568504446911 -0.0767519013341 -0.01155 -0.0566800947191 -0.0767464264881 -0.0116 -0.0566496635602 -0.0767408375105 -0.01165 -0.0564798213737 -0.076735132158 -0.0117 -0.0564486625685 -0.0767293085657 -0.01175 -0.0562792608653 -0.0767233644928 -0.0118 -0.0562473214762 -0.0767172980551 -0.01185 -0.0560782872781 -0.0767111070202 -0.0119 -0.0560455080369 -0.0767047894911 -0.01195 -0.0558767621181 -0.076698343249 -0.012 -0.0558430768223 -0.0766917663911 -0.01205 -0.0556745330439 -0.0766850567178 -0.0121 -0.0556398678447 -0.076678212327 -0.01215 -0.0554714323702 -0.0766712310438 -0.0122 -0.0554357049312 -0.0766641109737 -0.01225 -0.0552672753016 -0.0766568499728 -0.0123 -0.0552303938052 -0.0766494461608 -0.01235 -0.0550618578513 -0.0766418974297 -0.0124 -0.055023719829 -0.0766342019199 -0.01245 -0.0548549543899 -0.0766263575643 -0.0125 -0.0548154453354 -0.0766183625294 -0.01255 -0.054646314737 -0.0766102147944 -0.0126 -0.0546053064575 -0.0766019125587 -0.01265 -0.0544356607064 -0.0765934538525 -0.0127 -0.05439300936 -0.0765848369135 -0.01275 -0.0542226819896 -0.0765760598269 -0.0128 -0.0541782257395 -0.076567120873 -0.01285 -0.054007031235 -0.0765580181963 -0.0129 -0.0539605874366 -0.0765487501251 -0.01295 -0.0537883181421 -0.0765393148673 -0.013 -0.0537396799543 -0.0765297108033 -0.01305 -0.0535661023402 -0.0765199362071 -0.0131 -0.053515034626 -0.0765099895142 -0.01315 -0.0533398847635 -0.0764998690673 -0.0132 -0.0532861191027 -0.0764895733615 -0.01325 -0.0531090971468 -0.0764791008108 -0.0133 -0.0530523257388 -0.0764684499717 -0.01335 -0.0528730891669 -0.0764576193307 -0.0134 -0.0528129573362 -0.0764466075073 -0.01345 -0.0526311126052 -0.0764354130625 -0.0135 -0.0525672095116 -0.076424034681 -0.01355 -0.052382301701 -0.0764124709981 -0.0136 -0.0523141487849 -0.0764007207635 -0.01365 -0.0521256486434 -0.0763887826865 -0.0137 -0.0520526850939 -0.076376655583 -0.01375 -0.0518599727181 -0.076364338236 -0.0138 -0.0517815371024 -0.0763518295258 -0.01385 -0.051583881192 -0.0763391283066 -0.0139 -0.0514991879997 -0.0763262335224 -0.01395 -0.0512957192687 -0.0763131440972 -0.014 -0.0512038286988 -0.076299859036 -0.01405 -0.0509935054525 -0.0762863773282 -0.0141 -0.0508932841156 -0.0762726980364 -0.01415 -0.0506748472412 -0.0762588202129 -0.0142 -0.0505649164624 -0.0762447429737 -0.01425 -0.0503368298931 -0.0762304654271 -0.0143 -0.0502154969461 -0.0762159867374 -0.01435 -0.0499758679776 -0.0762013060644 -0.0144 -0.0498410334528 -0.0761864226133 -0.01445 -0.0495875046641 -0.0761713355865 -0.0145 -0.0494365359301 -0.0761560442235 -0.01455 -0.0491661365088 -0.0761405477613 -0.0146 -0.04899569235 -0.0761248454628 -0.01465 -0.0487046303964 -0.0761089365884 -0.0147 -0.0485104139866 -0.076092820415 -0.01475 -0.0481937814428 -0.0760764962134 -0.0148 -0.0479701862817 -0.0760599632597 -0.01485 -0.0476215320785 -0.0760432208217 -0.0149 -0.0473611248516 -0.0760262681593 -0.01495 -0.0469718251807 -0.0760091045178 -0.015 -0.0466645748743 -0.0759917291227 -0.01505 -0.0462228844053 -0.0759741411771 -0.0151 -0.0458549880374 -0.0759563398476 -0.01515 -0.0453445782779 -0.07593832427 -0.0152 -0.0448966310813 -0.075920093526 -0.01525 -0.0442942865221 -0.075901646652 -0.0153 -0.0437383648876 -0.0758829826111 -0.01535 -0.0430102698865 -0.0758641003046 -0.0154 -0.0423051822122 -0.0758449985342 -0.01545 -0.0414008228586 -0.0758256760197 -0.0155 -0.0404842596218 -0.0758061313513 -0.01555 -0.0393263159368 -0.075786363008 -0.0156 -0.0381018765636 -0.0757663693039 -0.01565 -0.036569718653 -0.0757461484039 -0.0157 -0.0348862950217 -0.0757256982614 -0.01575 -0.032791106951 -0.0757050166333 -0.0158 -0.0304148135637 -0.0756841010026 -0.01585 -0.0274721872751 -0.075662948592 -0.0159 -0.0240692284809 -0.0756415562708 -0.01595 -0.0199126482646 -0.0756199205574 -0.016 -0.0151314604854 -0.0755980375101 -0.01605 -0.00952443058137 -0.0755759027103 -0.0161 -0.00341386409508 -0.0755535111289 -0.01615 0.00308615255853 -0.0755308570813 -0.0162 0.00928215740455 -0.0755079340522 -0.01625 0.0147924060618 -0.0754847346079 -0.0163 0.0189525916842 -0.0754612501537 -0.01635 0.0217417528642 -0.0754374707708 -0.0164 0.0230190976793 -0.0754133848634 -0.01645 0.0231999004172 -0.0753889788589 -0.0165 0.0223685339488 -0.0753642366643 -0.01655 0.020970820326 -0.0753391391134 -0.0166 0.0190196006653 -0.075313663078 -0.01665 0.0168564625658 -0.0752877804486 -0.0167 0.0144010824961 -0.0752614566131 -0.01675 0.0119198527682 -0.0752346485905 -0.0168 0.00927976681523 -0.0752073023861 -0.01685 0.00670765225375 -0.0751793496576 -0.0169 0.00404466916042 -0.0751507031817 -0.01695 0.00149710181316 -0.0751212511348 -0.017 -0.00110657796119 -0.0750908495873 -0.01705 -0.0035715081144 -0.0750593131335 -0.0171 -0.006075531256 -0.0750264029352 -0.01715 -0.00843064404989 -0.0749918119664 -0.0172 -0.0108177174422 -0.0749551465424 -0.01725 -0.0130531862104 -0.0749159036816 -0.0173 -0.0153192023212 -0.074873443069 -0.01735 -0.017435369033 -0.0748269527661 -0.0174 -0.0195842645126 -0.0747754069341 -0.01745 -0.0215881012428 -0.0747175140909 -0.0175 -0.023629594926 -0.0746516533908 -0.01755 -0.0255334485035 -0.0745757965002 -0.0176 -0.0274825443629 -0.07448741139 -0.01765 -0.029304151597 -0.074383344177 -0.0177 -0.0311814174379 -0.0742596735635 -0.01775 -0.0329441993914 -0.0741115318204 -0.0178 -0.034775833643 -0.0739328841483 -0.01785 -0.0365084973725 -0.0737162569917 -0.0179 -0.0383252238594 -0.0734524029337 -0.01795 -0.0400596812811 -0.0731298874609 -0.018 -0.0418933684152 -0.0727345785318 -0.01805 -0.0436596514474 -0.0722490156314 -0.0181 -0.0455360325309 -0.0716516279458 -0.01815 -0.0473522861713 -0.070915762998 -0.0182 -0.0492777975347 -0.0700084735192 -0.01825 -0.0511339236083 -0.0688889906557 -0.0183 -0.0530769585272 -0.0675067766234 -0.01835 -0.0549157106318 -0.0657989872352 -0.0184 -0.0567917143734 -0.0636870489514 -0.01845 -0.0585038253883 -0.0610717933165 -0.0185 -0.0601871411557 -0.0578260174649 -0.01855 -0.0616444958053 -0.0537820560709 -0.0186 -0.0630217973541 -0.0487090939611 -0.01865 -0.0641419782334 -0.0422690787462 -0.0187 -0.0651720517615 -0.0339315912752 -0.01875 -0.0659566296934 -0.0228386090574 -0.0188 -0.0666772314424 -0.00777905747478 -0.01885 -0.0671885465205 0.0117739479452 -0.0189 -0.0676741217799 0.0319127292868 -0.01895 -0.067988387603 0.0438696165674 -0.019 -0.0683100819595 0.0465538656178 -0.01905 -0.0684898515372 0.0464319676521 -0.0191 -0.0687005821071 0.045908442843 -0.01915 -0.0687895498785 0.0451601014871 -0.0192 -0.0689249209701 0.044206490896 -0.01925 -0.0689519177194 0.0430567126776 -0.0193 -0.0690352618329 0.0417141359729 -0.01935 -0.0690192069769 0.040182772823 -0.0194 -0.0690659375521 0.038470865124 -0.01945 -0.0690194449409 0.0366131335136 -0.0195 -0.0690399476582 0.0346231151434 -0.01955 -0.0689716052906 0.0325168956116 -0.0196 -0.068973023362 0.0303118374349 -0.01965 -0.0688887909566 0.0280234202881 -0.0197 -0.0688761232412 0.0256679965115 -0.01975 -0.0687802003423 0.0232595691766 -0.0198 -0.0687569926953 0.0208120680354 -0.01985 -0.068652373568 0.0183371721779 -0.0199 -0.0686211676599 0.0158459015608 -0.01995 -0.0685100069526 0.0133472861944 -0.02 -0.0684726401613 0.0108494486451 -0.02005 -0.0683565003028 0.00835883654928 -0.0201 -0.0683143108362 0.00588095891011 -0.02015 -0.068194332829 0.0034199659733 -0.0202 -0.0681483024526 0.000979150640468 -0.02025 -0.0680253255053 -0.00143927119675 -0.0203 -0.0679761800652 -0.00383382614548 -0.02035 -0.0678508262331 -0.0062039023957 -0.0204 -0.0677991070501 -0.0085495488449 -0.02045 -0.067671841541 -0.0108715702538 -0.0205 -0.0676179564153 -0.0131714580225 -0.02055 -0.0674891307797 -0.0154515332149 -0.0206 -0.0674333905994 -0.0177150374537 -0.02065 -0.0673032737782 -0.0199664017844 -0.0207 -0.0672459188805 -0.0222115498831 -0.02075 -0.0671147196041 -0.0244583740277 -0.0208 -0.0670559388156 -0.0267173107863 -0.02085 -0.066923821803 -0.0290020885409 -0.0209 -0.0668637662337 -0.0313306015441 -0.02095 -0.0667308639378 -0.0337259028916 -0.021 -0.0666696569891 -0.0362171975653 -0.02105 -0.066536078132 -0.0388405798575 -0.0211 -0.066473822783 -0.0416389483603 -0.02115 -0.0663396585755 -0.0446599302751 -0.0212 -0.0662764426893 -0.0479497215303 -0.02125 -0.0661417713585 -0.0515395011039 -0.0213 -0.0660776715566 -0.0554206595609 -0.02135 -0.0659425616611 -0.0595084413324 -0.0214 -0.0658776461555 -0.0636069660636 -0.02145 -0.0657421590041 -0.0674131524028 -0.0215 -0.0656764896633 -0.0706049297219 -0.02155 -0.0655406810775 -0.0729909132952 -0.0216 -0.0654743149349 -0.0745935020897 -0.02165 -0.0653382365369 -0.0755855733137 -0.0217 -0.06527122689 -0.0761692994743 -0.02175 -0.0651349270392 -0.076504419978 -0.0218 -0.0650673242439 -0.0766955971021 -0.02185 -0.0649308487075 -0.0768051577849 -0.0219 -0.0648627007448 -0.076868582071 -0.02195 -0.0647260931742 -0.0769057296636 -0.022 -0.0646574460497 -0.076927717622 -0.02205 -0.0645207483104 -0.0769408169165 -0.0221 -0.0644516463255 -0.0769486168081 -0.02215 -0.0643148987157 -0.0769531979302 -0.0222 -0.064245384641 -0.0769557910812 -0.02225 -0.0641086260252 -0.0769571308885 -0.0223 -0.0640387412005 -0.0769576679044 -0.02235 -0.0639020090816 -0.0769576775529 -0.0224 -0.0638317934693 -0.0769573356536 -0.02245 -0.0636951240269 -0.0769567510095 -0.0225 -0.0636246162392 -0.0769559966226 -0.02255 -0.0634880443485 -0.0769551172195 -0.0226 -0.0634172816601 -0.0769541450376 -0.02265 -0.0632808408965 -0.076953098813 -0.0227 -0.0632098592425 -0.0769519937118 -0.02275 -0.0630735818706 -0.0769508374125 -0.0228 -0.0630024158275 -0.076949637543 -0.02285 -0.0628663327725 -0.0769483968797 -0.0229 -0.0627950155198 -0.0769471195391 -0.02295 -0.0626591563189 -0.0769458060508 -0.023 -0.0625877195832 -0.0769444587986 -0.02305 -0.0624521123229 -0.0769430772589 -0.0231 -0.0623805863106 -0.0769416629016 -0.02315 -0.0622452575549 -0.0769402147055 -0.0232 -0.0621736708784 -0.0769387336187 -0.02325 -0.0620386455925 -0.0769372183885 -0.0233 -0.0619670251924 -0.0769356696355 -0.02335 -0.0618323266647 -0.0769340860052 -0.0234 -0.061760697734 -0.0769324678911 -0.02345 -0.0616263475009 -0.0769308139002 -0.0235 -0.0615547334109 -0.076929124252 -0.02355 -0.0614207511833 -0.0769273975454 -0.0236 -0.0613491734124 -0.0769256338554 -0.02365 -0.0612155770055 -0.0769238317854 -0.0237 -0.0611440550708 -0.0769219912832 -0.02375 -0.0610108603373 -0.0769201109606 -0.0238 -0.0609394117309 -0.0769181906481 -0.02385 -0.0608066324981 -0.0769162289653 -0.0239 -0.0607352726255 -0.0769142256318 -0.02395 -0.0606029206361 -0.0769121792712 -0.024 -0.0605316627593 -0.0769100894967 -0.02405 -0.0603997476149 -0.0769079549314 -0.0241 -0.0603286027982 -0.0769057750844 -0.02415 -0.0601971319055 -0.0769035485733 -0.0242 -0.0601261089625 -0.0769012748055 -0.02425 -0.059995087481 -0.0768989523873 -0.0243 -0.0599241929234 -0.0768965806261 -0.02435 -0.0597936237146 -0.0768941581117 -0.0244 -0.0597228617026 -0.0768916840528 -0.02445 -0.0595927452799 -0.076889157018 -0.0245 -0.0595221175726 -0.0768865761188 -0.02455 -0.0593924520522 -0.0768839398976 -0.0246 -0.0593219579587 -0.0768812473703 -0.02465 -0.0591927390082 -0.0768784970489 -0.0247 -0.0591223753353 -0.0768756878552 -0.02475 -0.0589935961203 -0.0768728182671 -0.0248 -0.0589233571172 -0.0768698871142 -0.02485 -0.0587950082437 -0.0768668928373 -0.0249 -0.0587248855442 -0.0768638341758 -0.02495 -0.0585969549989 -0.0768607095309 -0.025 -0.0585269375582 -0.076857517554 -0.02505 -0.0583994106395 -0.0768542566052 -0.0251 -0.0583294846613 -0.0768509252506 -0.02515 -0.0582023439025 -0.0768475218078 -0.0252 -0.0581324927573 -0.0768440447606 -0.02525 -0.0580057178401 -0.0768404923838 -0.0253 -0.0579359219754 -0.0768368630822 -0.02535 -0.057809489632 -0.0768331550883 -0.0254 -0.0577397264643 -0.0768293667319 -0.02545 -0.0576136103594 -0.0768254962037 -0.0255 -0.0575438541491 -0.076821541763 -0.02555 -0.0574180247495 -0.0768175015602 -0.0256 -0.0573482464614 -0.0768133737883 -0.02565 -0.0572226708804 -0.0768091565598 -0.0257 -0.0571528380142 -0.0768048480064 -0.02575 -0.0570274798289 -0.0768004462052 -0.0258 -0.0569575562232 -0.0767959492322 -0.02585 -0.0568323752657 -0.0767913551321 -0.0259 -0.0567623208741 -0.0767866619309 -0.02595 -0.0566372729851 -0.0767818676446 -0.026 -0.0565670436055 -0.0767769702553 -0.02605 -0.0564420803428 -0.0767719677551 -0.0261 -0.0563716273084 -0.0767668580882 -0.02615 -0.056246695615 -0.0767616392273 -0.0262 -0.0561759654325 -0.0767563090852 -0.02625 -0.0560510072394 -0.07675086562 -0.0263 -0.0559799411584 -0.0767453067198 -0.02635 -0.0558548929245 -0.0767396303332 -0.0264 -0.0557834264446 -0.0767338343305 -0.02645 -0.0556582186202 -0.0767279166559 -0.0265 -0.0555862809063 -0.076721875169 -0.02655 -0.0554608372981 -0.0767157078159 -0.0266 -0.0553883504941 -0.0767094124523 -0.02665 -0.0552625875263 -0.0767029870318 -0.0267 -0.055189465958 -0.0766964294129 -0.02675 -0.0550632918043 -0.0766897375625 -0.0268 -0.0549894410334 -0.0766829093484 -0.02685 -0.0548627545899 -0.0766759427565 -0.0269 -0.0547880703007 -0.0766688356706 -0.02695 -0.0546607599801 -0.0766615861014 -0.027 -0.0545851266721 -0.0766541919559 -0.02705 -0.0544570689778 -0.0766466512752 -0.0271 -0.0543803584109 -0.0766389619951 -0.02715 -0.0542514162432 -0.0766311221923 -0.0272 -0.0541734855909 -0.0766231298374 -0.02725 -0.0540435062321 -0.0766149830473 -0.0273 -0.0539641958823 -0.0766066798334 -0.02735 -0.0538330085946 -0.0765982183586 -0.0274 -0.0537521395217 -0.0765895966803 -0.02745 -0.0536195526667 -0.0765808130111 -0.0275 -0.0535369232717 -0.0765718654591 -0.02755 -0.05340272084 -0.0765627522904 -0.0276 -0.0533181031367 -0.0765534716679 -0.02765 -0.0531820405528 -0.0765440219163 -0.0277 -0.053095175544 -0.0765344012574 -0.02775 -0.0529569745628 -0.0765246080766 -0.0278 -0.0528675666032 -0.0765146406576 -0.02785 -0.0527269090734 -0.0765044974489 -0.0279 -0.0526346189586 -0.0764941767994 -0.02795 -0.0524911391481 -0.0764836772237 -0.028 -0.0523955755847 -0.0764729971377 -0.02805 -0.0522488506907 -0.076462135123 -0.0281 -0.0521495597058 -0.0764510896634 -0.02815 -0.0519990980139 -0.0764398594084 -0.0282 -0.0518955497044 -0.076428442912 -0.02825 -0.0517407757307 -0.0764168388918 -0.0283 -0.0516323475623 -0.0764050459709 -0.02835 -0.0514725832401 -0.0763930629339 -0.0284 -0.051358538813 -0.0763808884728 -0.02845 -0.0511929794774 -0.0763685214392 -0.0285 -0.0510724413041 -0.0763559605922 -0.02855 -0.0509001247594 -0.0763432048467 -0.0286 -0.0507720390222 -0.0763302530265 -0.02865 -0.0505918052772 -0.0763171041083 -0.0287 -0.0504548957087 -0.0763037569773 -0.02875 -0.0502653340253 -0.0762902106666 -0.0288 -0.0501180409242 -0.0762764641181 -0.02885 -0.0499174193514 -0.0762625164177 -0.0289 -0.0497578179194 -0.0762483665585 -0.02895 -0.0495439883567 -0.0762340136713 -0.029 -0.0493696779386 -0.0762194567935 -0.02905 -0.0491399464565 -0.0762046950946 -0.0291 -0.0489478981626 -0.0761897276479 -0.02915 -0.0486988452585 -0.0761745536508 -0.0292 -0.0484851890816 -0.0761591722027 -0.02925 -0.0482124165362 -0.0761435825193 -0.0293 -0.0479721389998 -0.0761277837131 -0.02935 -0.0476699070949 -0.0761117750037 -0.0294 -0.0473964139762 -0.0760955555039 -0.02945 -0.0470571118738 -0.0760791244215 -0.0295 -0.046741583478 -0.0760624808507 -0.02955 -0.0463549403012 -0.0760456239693 -0.0296 -0.0459853609352 -0.0760285528334 -0.02965 -0.0455372453569 -0.0760112665663 -0.0297 -0.0450969103341 -0.0759937641607 -0.02975 -0.0445674633275 -0.0759760446599 -0.0298 -0.044032630813 -0.075958106961 -0.02985 -0.0433932969781 -0.0759399499927 -0.0299 -0.0427294161761 -0.0759215725217 -0.02995 -0.0419381308355 -0.0759029733189 -0.03 -0.0410936803368 -0.075884150973 -0.03005 -0.0400869678597 -0.0758651040474 -0.0301 -0.038983331128 -0.0758458308931 -0.03015 -0.0376633945912 -0.0758263297998 -0.0302 -0.0361785805586 -0.0758065988076 -0.03025 -0.0343932181799 -0.0757866358466 -0.0303 -0.0323380813121 -0.0757664385502 -0.03035 -0.0298546975966 -0.0757460043788 -0.0304 -0.0269492500645 -0.0757253304306 -0.03045 -0.0234439695111 -0.0757044135502 -0.0305 -0.019340565507 -0.0756832501281 -0.03055 -0.0144936832438 -0.0756618361916 -0.0306 -0.00900340004497 -0.075640167188 -0.03065 -0.00292355682868 -0.0756182380447 -0.0307 0.00334076037271 -0.0755960429297 -0.03075 0.00939035322735 -0.0755735752641 -0.0308 0.0145936742637 -0.0755508274421 -0.03085 0.0186057297164 -0.0755277907729 -0.0309 0.0211510511226 -0.0755044551231 -0.03095 0.0223731346668 -0.0754808087468 -0.031 0.0224000918328 -0.0754568377865 -0.03105 0.0215812088551 -0.0754325259081 -0.0311 0.0200754648479 -0.0754078535445 -0.03115 0.0181649993342 -0.0753827971762 -0.0312 0.0159128716651 -0.0753573281021 -0.03125 0.0135110236418 -0.0753314110753 -0.0313 0.0109515855981 -0.0753050022206 -0.03135 0.00837342616351 -0.0752780465315 -0.0314 0.00573129637533 -0.0752504743164 -0.03145 0.00313679588763 -0.0752221967965 -0.0315 0.000525832275584 -0.0751931001705 -0.03155 -0.00200427726536 -0.0751630382436 -0.0316 -0.0045274011897 -0.0751318228599 -0.03165 -0.00695410898185 -0.0750992121081 -0.0317 -0.0093634768276 -0.0750648954165 -0.03175 -0.0116706515571 -0.0750284753022 -0.0318 -0.0139575114314 -0.074989444677 -0.03185 -0.016142036232 -0.0749471591423 -0.0319 -0.0183076744629 -0.074900802802 -0.03195 -0.0203744034461 -0.0748493465177 -0.032 -0.0224267263166 -0.0747914965353 -0.03205 -0.0243863443556 -0.074725631637 -0.0321 -0.026338723891 -0.0746497258382 -0.03215 -0.0282073079116 -0.0745612536254 -0.0322 -0.0300785940579 -0.0744570733729 -0.03225 -0.0318778154108 -0.0743332841924 -0.0323 -0.0336924755918 -0.0741850497414 -0.03235 -0.0354494347227 -0.0740063815985 -0.0324 -0.0372368481508 -0.0737898724717 -0.03245 -0.0389825860066 -0.073526367761 -0.0325 -0.0407744992733 -0.0732045606337 -0.03255 -0.0425400643833 -0.0728104926462 -0.0326 -0.0443648569332 -0.0723269367695 -0.03265 -0.046173286614 -0.0717326339289 -0.0327 -0.0480451914872 -0.0710013451472 -0.03275 -0.0498976804468 -0.0701006693536 -0.0328 -0.0518001197865 -0.0689905570575 -0.03285 -0.0536577343796 -0.0676214176077 -0.0329 -0.0555261593608 -0.0659316570706 -0.03295 -0.0572984094819 -0.0638443652916 -0.033 -0.059020687831 -0.0612626221444 -0.03305 -0.0605836595246 -0.0580623525235 -0.0331 -0.0620387824111 -0.0540804518011 -0.03315 -0.0632909381931 -0.0490932185836 -0.0332 -0.0644108560877 -0.0427745723203 -0.03325 -0.0653249922313 -0.0346151292303 -0.0333 -0.0661223223507 -0.0237903586125 -0.03335 -0.0667428198416 -0.00911131003347 -0.0334 -0.0672820946301 0.0100894869334 -0.03345 -0.0676821316789 0.0304238213135 -0.0335 -0.0680362143645 0.0432283523524 -0.03355 -0.0682827128479 0.0464296891564 -0.0336 -0.0685099215072 0.046386038802 -0.03365 -0.0686520047133 0.0458812642007 -0.0337 -0.0687928715434 0.0451420439877 -0.03375 -0.0688636085564 0.044196647625 -0.0338 -0.0689449934793 0.0430519881689 -0.03385 -0.0689661983835 0.0417142199579 -0.0339 -0.0690058683771 0.0401862812231 -0.03395 -0.0689920731218 0.0384774514149 -0.034 -0.0690019757746 0.0366219079906 -0.03405 -0.0689630523008 0.0346337336237 -0.0341 -0.0689513865352 0.0325288089154 -0.03415 -0.0688941735663 0.0303247489264 -0.0342 -0.0688666684355 0.0280369727287 -0.03425 -0.0687959809604 0.025681966874 -0.0343 -0.0687566975824 0.023273728271 -0.03435 -0.0686759686219 0.0208262613978 -0.0344 -0.0686278177178 0.0183512582082 -0.03445 -0.0685395188039 0.0158597809566 -0.0345 -0.0684846047162 0.0133608770715 -0.03455 -0.0683905291483 0.0108626928511 -0.0346 -0.0683303843738 0.00837169218607 -0.03465 -0.0682318423403 0.00589339687029 -0.0347 -0.0681675905247 0.00343197041502 -0.03475 -0.0680655457287 0.000990711881579 -0.0348 -0.067998016513 -0.00142815293405 -0.03485 -0.0678931829322 -0.00382314842738 -0.0349 -0.0678229936301 -0.00619365585377 -0.03495 -0.0677159045727 -0.00853972444229 -0.035 -0.0676435186322 -0.0108621544588 -0.03505 -0.0675345762825 -0.0131624391039 -0.0351 -0.0674603453203 -0.0154428971585 -0.03515 -0.0673498564308 -0.0177067731956 -0.0352 -0.0672740505566 -0.0199584978573 -0.03525 -0.0671622522379 -0.0222039991379 -0.0353 -0.0670850820022 -0.024451171145 -0.03535 -0.0669721604 -0.0267104566707 -0.0354 -0.0668937927046 -0.0289955891282 -0.03545 -0.0667798965718 -0.0313244722026 -0.0355 -0.0667004662427 -0.0337201679741 -0.03555 -0.0665857168041 -0.0362118937918 -0.0356 -0.0665053350141 -0.0388357549805 -0.03565 -0.0663898331673 -0.0416346611174 -0.0357 -0.0663085935895 -0.0446562433639 -0.03575 -0.0661924251602 -0.0479466925614 -0.0358 -0.0661104084582 -0.0515371654562 -0.03585 -0.0659936480401 -0.0554190109747 -0.0359 -0.0659109251563 -0.0595074120607 -0.03595 -0.0657936389279 -0.0636064210142 -0.036 -0.0657102734916 -0.0674129086898 -0.03605 -0.065592521273 -0.0706048096243 -0.0361 -0.0655085713575 -0.0729908013362 -0.03615 -0.0653904081117 -0.0745933614774 -0.0362 -0.0653059275196 -0.0755854143948 -0.03625 -0.0651874044503 -0.0761691433208 -0.0363 -0.0651024436486 -0.0765042808778 -0.03635 -0.0649836089959 -0.0766954806607 -0.0364 -0.0648982157893 -0.0768050636976 -0.03645 -0.0647791153973 -0.0768685074052 -0.0365 -0.0646933354064 -0.0769056706459 -0.03655 -0.0645740131244 -0.0769276707366 -0.0366 -0.064487890118 -0.0769407791491 -0.03665 -0.0643683880719 -0.0769485858057 -0.0367 -0.0642819641876 -0.0769531718554 -0.03675 -0.0641623229554 -0.0769557685772 -0.0368 -0.064075638836 -0.0769571109244 -0.03685 -0.0639558975505 -0.076957649731 -0.0369 -0.0638689924184 -0.0769576606031 -0.03695 -0.063749188822 -0.0769573195124 -0.037 -0.0636621005201 -0.0769567353615 -0.03705 -0.0635422709935 -0.0769559812303 -0.0371 -0.0634550360056 -0.0769551019019 -0.03715 -0.063335215583 -0.0769541296502 -0.0372 -0.063247869042 -0.0769530832465 -0.03725 -0.0631280914107 -0.0769519778701 -0.0373 -0.0630406670899 -0.0769508212243 -0.03735 -0.0629209645729 -0.0769496209372 -0.0374 -0.0628334948601 -0.0769483798051 -0.03745 -0.0627138983806 -0.0769471019364 -0.0375 -0.0626264142325 -0.0769457878788 -0.03755 -0.0625069532596 -0.076944440003 -0.0376 -0.0624194841416 -0.0769430578025 -0.03765 -0.062300186625 -0.0769416427308 -0.0377 -0.0622127604411 -0.0769401937836 -0.03775 -0.0620936527384 -0.0769387118904 -0.0378 -0.0620062957573 -0.0769371958149 -0.03785 -0.0618874025587 -0.0769356461581 -0.0379 -0.061800139338 -0.0769340615815 -0.03795 -0.0616814835911 -0.0769324424578 -0.038 -0.0615943369036 -0.0769307874099 -0.03805 -0.0614759397416 -0.0769290966358 -0.0381 -0.0613889305044 -0.0769273687498 -0.03815 -0.0612708111762 -0.076925603805 -0.0382 -0.0611839583828 -0.0769238004198 -0.03825 -0.0610661341857 -0.0769219585197 -0.0383 -0.060979454841 -0.0769200767309 -0.03835 -0.0608619410589 -0.0769181548615 -0.0384 -0.060775450118 -0.0769161915448 -0.03845 -0.0606582599613 -0.0769141864778 -0.0385 -0.0605719702719 -0.0769121382976 -0.03855 -0.0604551148213 -0.0769100465942 -0.0386 -0.0603690370693 -0.0769079100036 -0.03865 -0.0602525252234 -0.076905728012 -0.0387 -0.0601666678807 -0.076903499249 -0.03875 -0.0600505063036 -0.0769012230991 -0.0388 -0.0599648755774 -0.0768988981801 -0.03885 -0.059849068649 -0.0768965237763 -0.0389 -0.0597636684319 -0.0768940984884 -0.03895 -0.0596482181985 -0.0768916215023 -0.039 -0.0595630500199 -0.0768890913966 -0.03905 -0.059447956146 -0.0768865072602 -0.0391 -0.0593630191238 -0.076883867645 -0.03915 -0.0592482788424 -0.0768811715442 -0.0392 -0.0591635696328 -0.0768784174787 -0.03925 -0.0590491776943 -0.0768756043481 -0.0393 -0.0589646904378 -0.0768727306386 -0.03935 -0.0588506390545 -0.0768697951575 -0.0394 -0.0587663653196 -0.0768667963536 -0.03945 -0.0586526441074 -0.0768637329443 -0.0395 -0.0585685728306 -0.0768606033383 -0.03955 -0.0584551687447 -0.0768574061653 -0.0396 -0.058371286161 -0.0768541397924 -0.03965 -0.0582581834227 -0.0768508027645 -0.0397 -0.0581744729874 -0.0768473934057 -0.03975 -0.0580616530014 -0.0768439101792 -0.0398 -0.0579780953042 -0.0768403513658 -0.03985 -0.0578655365662 -0.0768367153501 -0.0399 -0.0577821092304 -0.0768330003706 -0.03995 -0.0576697872172 -0.0768292047372 -0.04 -0.0575864647803 -0.0768253266465 -0.04005 -0.0574743518238 -0.0768213643383 -0.0401 -0.0573911056048 -0.0768173159688 -0.04015 -0.0572791707476 -0.0768131797123 -0.0402 -0.0571959686888 -0.0768089536867 -0.04025 -0.0570841775107 -0.0768046360059 -0.0403 -0.0570009839903 -0.0768002247521 -0.04035 -0.0568892984113 -0.0767957179843 -0.0404 -0.0568060740327 -0.0767911137524 -0.04045 -0.0566944520807 -0.0767864100659 -0.0405 -0.0566111534178 -0.0767816049462 -0.04055 -0.0564995489533 -0.0767766963596 -0.0406 -0.0564161282569 -0.0767716823038 -0.04065 -0.0563044906596 -0.0767665607079 -0.0407 -0.0562208955166 -0.0767613295502 -0.04075 -0.0561091693117 -0.0767559867294 -0.0408 -0.0560253422387 -0.0767505302093 -0.04085 -0.0559134666607 -0.0767449578648 -0.0409 -0.055829344638 -0.0767392676504 -0.04095 -0.0557172531264 -0.0767334574238 -0.041 -0.0556327670472 -0.0767275251355 -0.04105 -0.0555203866473 -0.0767214686334 -0.0411 -0.0554354606703 -0.0767152858702 -0.04115 -0.0553227113366 -0.0767089746907 -0.0412 -0.0552372621343 -0.0767025330553 -0.04125 -0.0551240559135 -0.0766959588124 -0.0413 -0.0550379917822 -0.0766892499362 -0.04135 -0.0549242318456 -0.0766824042853 -0.0414 -0.0548374516574 -0.0766754198527 -0.04145 -0.0547230311687 -0.0766682945143 -0.0415 -0.0546354231432 -0.0766610262881 -0.04155 -0.0545202239186 -0.0766536130741 -0.0416 -0.0544316641627 -0.0766460529208 -0.04165 -0.054315555081 -0.076638343758 -0.0417 -0.0542259058567 -0.0766304836699 -0.04175 -0.0541087409722 -0.0766224706218 -0.0418 -0.0540178486388 -0.0766143027386 -0.04185 -0.0538994649347 -0.0766059780271 -0.0419 -0.0538071574914 -0.0765974946585 -0.04195 -0.0536873721879 -0.0765888506861 -0.042 -0.0535934563237 -0.0765800443312 -0.04205 -0.0534720636419 -0.0765710736985 -0.0421 -0.0533763211828 -0.0765619370628 -0.04215 -0.0532530884388 -0.0765526325845 -0.0422 -0.0531552720476 -0.0765431585968 -0.04225 -0.0530299349133 -0.0765335133198 -0.0423 -0.052929762858 -0.0765236951476 -0.04235 -0.0528020195797 -0.0765137023626 -0.0424 -0.0526991693335 -0.0765035334221 -0.04245 -0.0525686736341 -0.0764931866742 -0.0425 -0.052462773998 -0.0764826606422 -0.04255 -0.0523291263167 -0.0764719537418 -0.0426 -0.0522197476601 -0.0764610645631 -0.04265 -0.052082484268 -0.07644999159 -0.0427 -0.051969126357 -0.0764387334807 -0.04275 -0.0518277057159 -0.0764272887894 -0.0428 -0.0517097824066 -0.0764156562422 -0.04285 -0.0515635679655 -0.0764038344624 -0.0429 -0.0514403878248 -0.0763918222432 -0.04295 -0.0512886261324 -0.076379618277 -0.043 -0.0511593676618 -0.0763672214233 -0.04305 -0.0510011602624 -0.0763546304417 -0.0431 -0.0508648399402 -0.0763418442548 -0.04315 -0.0506991069417 -0.0763288616866 -0.0432 -0.0505545375882 -0.0763156817211 -0.04325 -0.0503799699546 -0.0763023032437 -0.0433 -0.050225705896 -0.0762887252939 -0.04335 -0.0500407022337 -0.0762749468134 -0.0434 -0.0498749662292 -0.0762609668939 -0.04345 -0.0496775480489 -0.0762467845279 -0.0435 -0.0494981326788 -0.0762323988511 -0.04355 -0.0492858292454 -0.0762178088995 -0.0436 -0.049089961987 -0.0762030138467 -0.04365 -0.0488596516439 -0.0761880127636 -0.0437 -0.0486438075278 -0.0761728048503 -0.04375 -0.0483914956024 -0.0761573892031 -0.0438 -0.0481511328222 -0.0761417650388 -0.04385 -0.0478716355132 -0.0761259314652 -0.0439 -0.0476008157536 -0.0761098877014 -0.04395 -0.0472873019903 -0.0760936328541 -0.044 -0.0469781348653 -0.0760771661282 -0.04405 -0.0466214491816 -0.0760604866097 -0.0441 -0.0462632626776 -0.0760435934713 -0.04415 -0.045850903477 -0.0760264857581 -0.0442 -0.0454289785894 -0.0760091625853 -0.04425 -0.04494352236 -0.0759916229315 -0.0443 -0.04443711989 -0.075973865828 -0.04435 -0.043853736872 -0.0759558901541 -0.0444 -0.0432329531129 -0.075937694822 -0.04445 -0.0425154085557 -0.0759192785752 -0.0445 -0.041736069229 -0.0759006401628 -0.04455 -0.0408301842512 -0.075881778144 -0.0446 -0.039825460663 -0.0758626910529 -0.04465 -0.038648381746 -0.0758433772032 -0.0447 -0.0373151415788 -0.075823834846 -0.04475 -0.0357382104271 -0.0758040619738 -0.0448 -0.0339160649755 -0.0757840564661 -0.04485 -0.0317404003277 -0.075763815895 -0.0449 -0.0291858699222 -0.0757433376541 -0.04495 -0.0261207661749 -0.0757226187622 -0.045 -0.022502524214 -0.0757016559756 -0.04505 -0.0182023041132 -0.0756804455801 -0.0451 -0.0132226049272 -0.0756589834852 -0.04515 -0.00755509206994 -0.0756372649978 -0.0452 -0.00142753060569 -0.0756152848852 -0.04525 0.00484469002488 -0.0755930371239 -0.0453 0.0107025425959 -0.0755705149127 -0.04535 0.0156611822893 -0.0755477103781 -0.0454 0.0192949643588 -0.0755246145115 -0.04545 0.0215252876176 -0.0755012167931 -0.0455 0.0224104293502 -0.0754775050084 -0.04555 0.0222303871172 -0.0754534647205 -0.0456 0.0212017319645 -0.0754290788766 -0.04565 0.0196043492129 -0.0754043270035 -0.0457 0.0175767125295 -0.0753791844325 -0.04575 0.0153020397511 -0.0753536209859 -0.0458 0.0128333700206 -0.07532759951 -0.04585 0.0102872173842 -0.0753010736462 -0.0459 0.00766809834814 -0.075273985149 -0.04595 0.00505753888264 -0.0752462600908 -0.046 0.00243542850004 -0.0752178041697 -0.04605 -0.000134660191505 -0.0751884963999 -0.0461 -0.00268555208611 -0.075158181296 -0.04615 -0.00516328997985 -0.0751266587545 -0.0462 -0.00760751624689 -0.0750936716035 -0.04625 -0.00996965894191 -0.0750588898978 -0.0463 -0.0122931115308 -0.075021891712 -0.04635 -0.01453245546 -0.0749821392775 -0.0464 -0.0167332275675 -0.0749389498686 -0.04645 -0.0188520342773 -0.0748914598837 -0.0465 -0.0209358071784 -0.0748385809952 -0.04655 -0.0229427266713 -0.0747789461824 -0.0466 -0.0249208976821 -0.0747108437114 -0.04665 -0.0268300143409 -0.0746321359217 -0.0467 -0.0287193914841 -0.0745401596681 -0.04675 -0.0305503027867 -0.0744316038283 -0.0468 -0.032373307164 -0.0743023588914 -0.04685 -0.0341511991346 -0.0741473318213 -0.0469 -0.0359355736607 -0.0739602184257 -0.04695 -0.0376903272046 -0.0737332229947 -0.047 -0.0394673935327 -0.0734567131297 -0.04705 -0.0412307071418 -0.0731187941386 -0.0471 -0.0430310023633 -0.0727047840459 -0.04715 -0.0448301095393 -0.0721965647668 -0.0472 -0.0466746950445 -0.0715717788071 -0.04725 -0.0485208175679 -0.0708028310576 -0.0473 -0.0504066835361 -0.0698556419648 -0.04735 -0.0522778158202 -0.0686880760362 -0.0474 -0.0541596091152 -0.0672479323377 -0.04745 -0.0559844034711 -0.0654703127395 -0.0475 -0.05776552663 -0.0632740430053 -0.04755 -0.0594278401903 -0.0605565233918 -0.0476 -0.0609838599534 -0.0571857314878 -0.04765 -0.0623664637395 -0.05298663539 -0.0477 -0.0636036581368 -0.0477160471322 -0.04775 -0.0646488986096 -0.0410135188862 -0.0478 -0.0655508819846 -0.0323079512618 -0.04785 -0.0662805494339 -0.0206808799365 -0.0479 -0.0668979678635 -0.00491530280719 -0.04795 -0.0673796981609 0.0151162612059 -0.048 -0.0677862049049 0.0344621561793 -0.04805 -0.0680915761364 0.0446451174901 -0.0481 -0.06835189664 0.0465092986535 -0.04815 -0.0685367464395 0.0462855571539 -0.0482 -0.0686976249768 0.0457155786276 -0.04825 -0.0688003890022 0.04492834249 -0.0483 -0.068893139227 0.0439320798118 -0.04835 -0.0689392469588 0.0427412886429 -0.0484 -0.0689845374055 0.0413559554984 -0.04845 -0.0689908421537 0.0397832428434 -0.0485 -0.0690024787864 0.0380355041044 -0.04855 -0.0689803473762 0.0361468645679 -0.0486 -0.0689677373987 0.0341281678366 -0.04865 -0.0689249923838 0.0319976948053 -0.0487 -0.0688946699707 0.02977147194 -0.04875 -0.0688367902158 0.0274658754948 -0.0488 -0.0687933658524 0.0250964149832 -0.04885 -0.068724242223 0.0226773500812 -0.0489 -0.0686710087613 0.0202219862466 -0.04895 -0.068593433906 0.0177419544121 -0.049 -0.0685327653085 0.0152477731178 -0.04905 -0.0684487605075 0.0127482963414 -0.0491 -0.0683823814162 0.0102512355744 -0.04915 -0.0682934201062 0.00776282668635 -0.0492 -0.0682225920419 0.00528824439789 -0.04925 -0.0681297555329 0.00283143569458 -0.0493 -0.0680554075435 0.000395425219274 -0.04935 -0.0679594949239 -0.00201774979437 -0.0494 -0.067882316244 -0.00440683264566 -0.04945 -0.0677839226437 -0.00677136915224 -0.0495 -0.0677044288966 -0.00911159641657 -0.04955 -0.0676040015571 -0.0114284779595 -0.0496 -0.0675225822954 -0.0137237035256 -0.04965 -0.0674204609126 -0.0159998000174 -0.0497 -0.0673374138828 -0.018260281312 -0.04975 -0.0672338597364 -0.0205099079882 -0.0498 -0.0671494156532 -0.0227550463202 -0.04985 -0.0670446326876 -0.0250041543251 -0.0499 -0.0669589731913 -0.0272684109494 -0.04995 -0.066853123319 -0.02956248589 -0.05 -0.0667663940165 -0.0319054566897 -0.05005 -0.0666596082411 -0.0343218083745 -0.0501 -0.066571928205 -0.0368424009398 -0.05015 -0.0664643147337 -0.0395050700757 -0.0502 -0.0663757834253 -0.0423541895464 -0.05025 -0.0662674335807 -0.0454378281644 -0.0503 -0.066178135909 -0.0488001112382 -0.05035 -0.0660691284608 -0.0524652071909 -0.0504 -0.0659791384857 -0.0564094447851 -0.05045 -0.0658695428146 -0.0605232947359 -0.0505 -0.0657789264524 -0.0645814792202 -0.05055 -0.0656688048648 -0.0682643819602 -0.0506 -0.0655776218703 -0.0712681179596 -0.05065 -0.0654670312955 -0.0734518030711 -0.0507 -0.0653753367129 -0.0748854006664 -0.05075 -0.0652643299406 -0.0757594297393 -0.0508 -0.0651721751559 -0.0762695367665 -0.05085 -0.0650608017325 -0.0765615528957 -0.0509 -0.0649682352372 -0.0767282126832 -0.05095 -0.0648565421129 -0.0768239382321 -0.051 -0.064763610051 -0.0768795173002 -0.05105 -0.0646516420407 -0.0769121663569 -0.0511 -0.0645583885944 -0.0769315339811 -0.05115 -0.0644461886962 -0.0769430827872 -0.0512 -0.0643526563438 -0.0769499474175 -0.05125 -0.0642402659455 -0.0769539557741 -0.0513 -0.0641464956254 -0.0769561901163 -0.05135 -0.0640339546318 -0.0769573023822 -0.0514 -0.0639399858378 -0.0769576906596 -0.05145 -0.063827332741 -0.0769576024287 -0.0515 -0.063733203574 -0.0769571930626 -0.05155 -0.0636204754913 -0.076956562074 -0.0516 -0.0635262226878 -0.0769557734034 -0.05165 -0.063413455382 -0.0769548691712 -0.0517 -0.0633191143273 -0.0769538768905 -0.05175 -0.0632063422131 -0.0769528151722 -0.0518 -0.0631119469389 -0.0769516962458 -0.05185 -0.0629992030715 -0.0769505285895 -0.0519 -0.062904786236 -0.0769493177081 -0.05195 -0.0627921022819 -0.0769480674977 -0.052 -0.0626976951315 -0.0769467803714 -0.05205 -0.0625851013212 -0.0769454580554 -0.0521 -0.062490733635 -0.0769441014804 -0.05215 -0.062378258702 -0.0769427112962 -0.0522 -0.0622839587261 -0.0769412876922 -0.05225 -0.0621716298367 -0.0769398307563 -0.0523 -0.0620774242113 -0.0769383402897 -0.05235 -0.061965266891 -0.0769368160692 -0.0524 -0.0618711805757 -0.0769352576801 -0.05245 -0.0617592186329 -0.0769336647144 -0.0525 -0.0616652748317 -0.0769320366273 -0.05255 -0.0615535302843 -0.0769303728905 -0.0526 -0.0614597503727 -0.0769286728725 -0.05265 -0.0613482433768 -0.0769269359586 -0.0527 -0.0612546468326 -0.0769251614519 -0.05275 -0.0611433956151 -0.0769233486687 -0.0528 -0.0610499999527 -0.076921496857 -0.05285 -0.0609390207476 -0.0769196052728 -0.0529 -0.0608458414564 -0.076917673113 -0.05295 -0.0607351484448 -0.0769156995779 -0.053 -0.0606421989306 -0.0769136838137 -0.05305 -0.0605318041837 -0.0769116249663 -0.0531 -0.0604390957125 -0.0769095221307 -0.05315 -0.0603290091361 -0.0769073743983 -0.0532 -0.0602365507809 -0.0769051808109 -0.05325 -0.0601267800636 -0.0769029404044 -0.0533 -0.0600345786528 -0.0769006521656 -0.05335 -0.0599251292157 -0.0768983150734 -0.0534 -0.0598331892841 -0.0768959280573 -0.05345 -0.0597240642322 -0.0768934900376 -0.0535 -0.0596323879725 -0.0768909998845 -0.05355 -0.0595235880461 -0.0768884564584 -0.0536 -0.0594321752599 -0.0768858585682 -0.05365 -0.0593236987848 -0.0768832050132 -0.0537 -0.0592325468324 -0.0768804945391 -0.05375 -0.0591243896692 -0.0768777258828 -0.0538 -0.0590334934179 -0.076874897726 -0.05385 -0.0589256489095 -0.0768720087424 -0.0539 -0.0588350006798 -0.0768690575488 -0.05395 -0.0587274595947 -0.076866042755 -0.054 -0.0586370491002 -0.076862962913 -0.05405 -0.0585297995692 -0.0768598165688 -0.0541 -0.0584396138496 -0.0768566022093 -0.05415 -0.0583326412963 -0.0768533183174 -0.0542 -0.0582426646459 -0.0768499633159 -0.05425 -0.0581359517098 -0.0768465356253 -0.0543 -0.0580461655936 -0.0768430336057 -0.05435 -0.0579396920395 -0.0768394556162 -0.0544 -0.0578500749956 -0.0768357999561 -0.05445 -0.0577438176102 -0.0768320649259 -0.0545 -0.0576543451411 -0.0768282487663 -0.05455 -0.0575482776165 -0.0768243497214 -0.0546 -0.0574589220613 -0.0768203659761 -0.05465 -0.0573530148541 -0.0768162957212 -0.0547 -0.0572637452364 -0.0768121370893 -0.05475 -0.0571579654071 -0.0768078882213 -0.0548 -0.0570687472645 -0.0768035472013 -0.05485 -0.0569630582918 -0.0767991121243 -0.0549 -0.0568738534711 -0.0767945810304 -0.05495 -0.0567682150281 -0.0767899519728 -0.055 -0.0566789814464 -0.0767852229522 -0.05505 -0.0565733491479 -0.0767803919852 -0.0551 -0.0564840405189 -0.0767754570385 -0.05515 -0.0563783656202 -0.0767704160973 -0.0552 -0.0562889311257 -0.0767652670997 -0.05525 -0.0561831601696 -0.076760008005 -0.0553 -0.0560935440833 -0.0767546367283 -0.05535 -0.0559876184946 -0.0767491512088 -0.0554 -0.0558977597391 -0.0767435493446 -0.05545 -0.0557916153416 -0.0767378290606 -0.0555 -0.0557014469658 -0.0767319882441 -0.05555 -0.0555950134211 -0.0767260248117 -0.0556 -0.055504461997 -0.0767199366462 -0.05565 -0.0553976621496 -0.0767137216629 -0.0557 -0.0553066470584 -0.0767073777466 -0.05575 -0.0551993961598 -0.0767009028172 -0.0558 -0.0551078287527 -0.0766942947675 -0.05585 -0.0550000335567 -0.0766875515284 -0.0559 -0.0549078161757 -0.076680671007 -0.05595 -0.0547993738722 -0.0766736511508 -0.056 -0.0547063986888 -0.0766664898878 -0.05605 -0.0545971956406 -0.076659185189 -0.0561 -0.0545033432829 -0.0766517350091 -0.05615 -0.0543932535362 -0.0766441373485 -0.0562 -0.0542983914696 -0.0766363901944 -0.05625 -0.0541872749868 -0.0766284915816 -0.0563 -0.0540912555844 -0.0766204395352 -0.05635 -0.053978956137 -0.0766122321299 -0.0564 -0.0538816143773 -0.0766038674347 -0.05645 -0.0537679570287 -0.0765953435696 -0.0565 -0.0536691077396 -0.0765866586517 -0.05655 -0.053553895824 -0.076577810851 -0.0566 -0.0534533303686 -0.0765687983371 -0.05665 -0.0533363418523 -0.0765596193333 -0.0567 -0.0532338241276 -0.0765502720664 -0.05675 -0.0531148072003 -0.076540754818 -0.0568 -0.053010068775 -0.0765310658752 -0.05685 -0.0528887364835 -0.0765212035805 -0.0569 -0.0527814706644 -0.0765111662839 -0.05695 -0.0526574943398 -0.0765009523913 -0.057 -0.0525473488839 -0.076490560319 -0.05705 -0.0524203500504 -0.0764799885392 -0.0571 -0.0523069181587 -0.0764692355354 -0.05715 -0.0521764584906 -0.0764582998472 -0.0572 -0.0520592676024 -0.0764471800263 -0.05725 -0.0519248363974 -0.0764358746808 -0.0573 -0.0518033341475 -0.0764243824321 -0.05735 -0.0516643325574 -0.0764127019569 -0.0574 -0.0515378690371 -0.0764008319449 -0.05745 -0.0513935900706 -0.0763887711403 -0.0575 -0.051261395238 -0.0763765183014 -0.05755 -0.0511109981754 -0.0763640722392 -0.0576 -0.05097215281 -0.0763514317778 -0.05765 -0.0508146301602 -0.0763385957916 -0.0577 -0.050668028172 -0.0763255631687 -0.05775 -0.0505021625674 -0.076312332845 -0.0578 -0.0503464615567 -0.076298903768 -0.05785 -0.0501707688837 -0.0762852749297 -0.0579 -0.0500043245521 -0.0762714453327 -0.05795 -0.0498169780648 -0.0762574140213 -0.058 -0.0496377561263 -0.0762431800466 -0.05805 -0.0494364838614 -0.0762287424971 -0.0581 -0.0492419401498 -0.0762141004661 -0.05815 -0.0490238843123 -0.0761992530793 -0.0582 -0.0488107992461 -0.0761841994623 -0.05825 -0.0485723205502 -0.0761689387678 -0.0583 -0.0483365669429 -0.0761534701439 -0.05835 -0.0480729679213 -0.0761377927594 -0.0584 -0.0478091797844 -0.0761219057711 -0.05845 -0.0475143065123 -0.0761058083496 -0.0585 -0.047215397841 -0.076089499647 -0.05855 -0.0468810556764 -0.0760729788185 -0.0586 -0.0465375074499 -0.0760562449922 -0.05865 -0.0461525863032 -0.0760392972894 -0.0587 -0.0457513675781 -0.0760221347928 -0.05875 -0.0453005039024 -0.0760047565643 -0.0588 -0.0448234032121 -0.0759871616155 -0.05885 -0.0442848876087 -0.0759693489211 -0.0589 -0.0437058749589 -0.0759513173877 -0.05895 -0.0430483091643 -0.0759330658676 -0.059 -0.0423292798787 -0.0759145931242 -0.05905 -0.0415061372505 -0.0758958978419 -0.0591 -0.0405899424423 -0.0758769785921 -0.05915 -0.0395306336025 -0.0758578338369 -0.0592 -0.0383296577388 -0.0758384618924 -0.05925 -0.0369250396025 -0.0758188609294 -0.0593 -0.035303108203 -0.0757990289292 -0.05935 -0.0333835680924 -0.0757789636798 -0.0594 -0.0311308780643 -0.0757586627263 -0.05945 -0.0284408550955 -0.0757381233541 -0.0595 -0.025255134997 -0.0757173425342 -0.05955 -0.0214560859987 -0.0756963168923 -0.0596 -0.0169962571651 -0.0756750426384 -0.05965 -0.0118192944366 -0.0756535155201 -0.0597 -0.00602276736611 -0.0756317307282 -0.05975 0.000195717322253 -0.0756096828241 -0.0598 0.00640061616394 -0.0755873656106 -0.05985 0.01208678307 -0.075564772014 -0.0599 0.0167187363643 -0.0755418939024 -0.05995 0.0200056893233 -0.0755187218911 -0.06 0.0218606797536 -0.0754952450703 -0.06005 0.0224598290366 -0.0754714506832 -0.0601 0.0220247896284 -0.0754473236879 -0.06015 0.0208421424262 -0.0754228462122 -0.0602 0.0191062315342 -0.0753979968116 -0.06025 0.0170162160041 -0.0753727495168 -0.0603 0.0146711493576 -0.0753470725377 -0.06035 0.0121891619476 -0.0753209265687 -0.0604 0.00960775528724 -0.0752942625047 -0.06045 0.00700023640248 -0.0752670184505 -0.0605 0.0043722900274 -0.0752391157611 -0.06055 0.00177438164862 -0.0752104539213 -0.0606 -0.00080406791064 -0.075180903922 -0.06065 -0.00332456996913 -0.0751502998515 -0.0607 -0.00580634834694 -0.0751184282624 -0.06075 -0.0082174821597 -0.0750850148997 -0.0608 -0.0105819483798 -0.0750497082014 -0.06085 -0.0128715666491 -0.075012058938 -0.0609 -0.0151130126483 -0.074971495138 -0.06095 -0.0172803730493 -0.0749272913153 -0.061 -0.0194020003705 -0.0748785307029 -0.06105 -0.0214535825527 -0.0748240589608 -0.0611 -0.0234647640495 -0.0747624273849 -0.06115 -0.0254126601301 -0.0746918232449 -0.0612 -0.0273281784015 -0.074609984254 -0.06125 -0.0291899112223 -0.0745140935369 -0.0613 -0.0310300930712 -0.0744006505466 -0.06135 -0.0328288086314 -0.07426531239 -0.0614 -0.0346195280423 -0.0741026986461 -0.06145 -0.0363835714549 -0.0739061512115 -0.0615 -0.0381551609014 -0.0736674386161 -0.06155 -0.0399160686799 -0.0733763917859 -0.0616 -0.0417000941728 -0.0730204549661 -0.06165 -0.0434877804366 -0.0725841314692 -0.0617 -0.0453101861061 -0.0720482984961 -0.06175 -0.0471435524277 -0.0713893580853 -0.0618 -0.0490123280107 -0.0705781809765 -0.06185 -0.0508839164897 -0.0695787848317 -0.0619 -0.0527714050589 -0.0683466632608 -0.06195 -0.0546293044961 -0.0668266381598 -0.062 -0.0564574022674 -0.0649500241121 -0.06205 -0.0581992121157 -0.0626307234831 -0.0621 -0.0598483656286 -0.0597595072067 -0.06215 -0.0613499409268 -0.0561949323654 -0.0622 -0.062707516833 -0.0517475476763 -0.06225 -0.0638835050003 -0.0461501243168 -0.0623 -0.0649023530609 -0.0389993081372 -0.06235 -0.0657468219191 -0.0296481406797 -0.0624 -0.0664572358547 -0.0170751741431 -0.06245 -0.0670263557279 -0.000108490673115 -0.0625 -0.0674984681968 0.0205099184085 -0.06255 -0.0678659836117 0.0381596402844 -0.0626 -0.0681699272947 0.0456180879914 -0.06265 -0.0683983674229 0.0465029289503 -0.0627 -0.0685875952368 0.0461594981888 -0.06275 -0.0687214569716 0.0455259499574 -0.0628 -0.0688324445434 0.0446861632844 -0.06285 -0.0689014057728 0.0436372072442 -0.0629 -0.0689582525952 0.0423966438547 -0.06295 -0.0689819136486 0.040961344872 -0.063 -0.0690006201626 0.0393413020987 -0.06305 -0.0689921049761 0.0375551108859 -0.0631 -0.0689834914874 0.0356316717681 -0.06315 -0.0689517660996 0.0335821383736 -0.0632 -0.0689232976729 0.0314255634358 -0.06325 -0.0688746038676 0.0291772070167 -0.0633 -0.0688315196117 0.0268538413574 -0.06335 -0.0687702693113 0.0244702930928 -0.0634 -0.068716295682 0.0220408183232 -0.06345 -0.0686456441492 0.0195781568243 -0.0635 -0.0685834590811 0.017093720707 -0.06355 -0.0685056834736 0.0145975622764 -0.0636 -0.0684372272015 0.0120982340228 -0.06365 -0.0683539832957 0.0096030677827 -0.0637 -0.0682806714962 0.00711799180613 -0.06375 -0.068193171437 0.00464787726784 -0.0638 -0.0681160440155 0.00219639455364 -0.06385 -0.0680251812394 -0.000233671310891 -0.0639 -0.0679450074853 -0.0026405176799 -0.06395 -0.0678514454222 -0.00502308031542 -0.064 -0.0677687989592 -0.00738110621855 -0.06405 -0.067673034456 -0.00971500402663 -0.0641 -0.0675883469749 -0.0120259333156 -0.06415 -0.0674907558625 -0.0143157778791 -0.0642 -0.0674043558037 -0.0165873091444 -0.06425 -0.0673052257584 -0.0188443277948 -0.0643 -0.0672173662449 -0.0210919742491 -0.06435 -0.0671169205576 -0.0233370989184 -0.0644 -0.0670277996288 -0.0255887979843 -0.06445 -0.0669262144293 -0.0278590696234 -0.0645 -0.0668359897228 -0.0301636283111 -0.06455 -0.0667334065084 -0.0325228485149 -0.0646 -0.0666422059448 -0.0349627727009 -0.06465 -0.0665387406906 -0.0375160282511 -0.0647 -0.0664466702547 -0.0402222419829 -0.06475 -0.0663424200694 -0.0431271529352 -0.0648 -0.0662495694995 -0.0462788037692 -0.06485 -0.0661446174844 -0.0497181308913 -0.0649 -0.0660510644244 -0.0534601389212 -0.06495 -0.0659454832253 -0.057462825391 -0.065 -0.0658512962668 -0.0615885218606 -0.06505 -0.0657451506801 -0.0655822888832 -0.0651 -0.065650391591 -0.0691145980163 -0.06515 -0.0655437404661 -0.0719111083014 -0.0652 -0.0654484658153 -0.0738872555488 -0.06525 -0.0653413634438 -0.0751562543546 -0.0653 -0.0652456257887 -0.0759191521833 -0.06535 -0.0651381229181 -0.0763612948444 -0.0654 -0.0650419716685 -0.0766138864662 -0.06545 -0.0649341162357 -0.076758185852 -0.0655 -0.0648375982737 -0.0768412764459 -0.06555 -0.064729435927 -0.0768896667365 -0.0656 -0.064632596045 -0.076918172233 -0.06565 -0.0645241705097 -0.076935114133 -0.0657 -0.0644270517119 -0.0769452178371 -0.06575 -0.064318405036 -0.0769512066341 -0.0658 -0.0642210487356 -0.0769546741345 -0.06585 -0.0641122214439 -0.0769565686432 -0.0659 -0.0640146675821 -0.0769574629867 -0.06595 -0.0639056987663 -0.0769577089534 -0.066 -0.0638079858771 -0.0769575255206 -0.06605 -0.0636989132416 -0.0769570511053 -0.0661 -0.0636010784859 -0.0769563742887 -0.06615 -0.063491938374 -0.0769555524516 -0.0662 -0.0633940175579 -0.0769546232803 -0.06625 -0.0632848449624 -0.0769536116026 -0.0663 -0.0631868725409 -0.0769525341541 -0.06635 -0.0630777011003 -0.0769514019838 -0.0664 -0.062979710165 -0.0769502227694 -0.06645 -0.0628705721418 -0.076949001436 -0.0665 -0.0627725943892 -0.0769477415628 -0.06655 -0.0626635206299 -0.0769464452249 -0.0666 -0.0625655863136 -0.0769451140649 -0.06665 -0.0624566061911 -0.0769437487707 -0.0667 -0.0623587440574 -0.0769423500286 -0.06675 -0.0622498854039 -0.0769409178206 -0.0668 -0.062152122621 -0.0769394523368 -0.06685 -0.0620434116541 -0.0769379531814 -0.0669 -0.0619457737374 -0.0769364202709 -0.06695 -0.0618372349845 -0.0769348529955 -0.067 -0.0617397457212 -0.0769332511079 -0.06705 -0.0616314019455 -0.0769316138681 -0.0671 -0.0615340833216 -0.0769299409195 -0.06715 -0.0614259554505 -0.0769282314356 -0.0672 -0.0613288275805 -0.0769264849783 -0.06725 -0.061220934637 -0.0769247006571 -0.0673 -0.0611240156975 -0.0769228779652 -0.06735 -0.0610163747346 -0.0769210159604 -0.0674 -0.0609196808997 -0.0769191140729 -0.06745 -0.0608123069385 -0.076917171314 -0.0675 -0.0607158523204 -0.0769151870529 -0.06755 -0.0606087582917 -0.0769131602568 -0.0676 -0.0605125548831 -0.0769110902334 -0.06765 -0.0604057515716 -0.076908975906 -0.0677 -0.0603098091924 -0.0769068165198 -0.06775 -0.0602033051852 -0.076904610953 -0.0678 -0.0601076314308 -0.0769023583864 -0.06785 -0.0600014330656 -0.076900057652 -0.0679 -0.0599060332568 -0.0768977078642 -0.06795 -0.0598001445727 -0.0768953078065 -0.068 -0.059705021706 -0.0768928565254 -0.06805 -0.0595994443942 -0.0768903527542 -0.0681 -0.0595045990932 -0.0768877954699 -0.06815 -0.0593993324485 -0.0768851833536 -0.0682 -0.0593047629153 -0.0768825153117 -0.06825 -0.0591998037866 -0.0768797899712 -0.0683 -0.0591055057512 -0.0768770061669 -0.06835 -0.0590008484894 -0.0768741624706 -0.0684 -0.0589068151554 -0.076871257645 -0.06845 -0.0588024515571 -0.0768682902056 -0.0685 -0.0587086735433 -0.0768652588428 -0.06855 -0.0586045927913 -0.0768621620153 -0.0686 -0.0585110580707 -0.0768589983418 -0.06865 -0.0584072466679 -0.0768557662241 -0.0687 -0.0583139404964 -0.0768524642099 -0.06875 -0.0582103821901 -0.0768490906446 -0.0688 -0.058117287025 -0.0768456440064 -0.06885 -0.0580139627219 -0.076842122585 -0.0689 -0.0579210581337 -0.0768385247911 -0.06895 -0.0578179458038 -0.0768348488602 -0.069 -0.0577252083708 -0.0768310931384 -0.06905 -0.057622282933 -0.076827255809 -0.0691 -0.0575296861179 -0.0768233351561 -0.06915 -0.0574269193094 -0.0768193293134 -0.0692 -0.0573344333212 -0.0768152365069 -0.06925 -0.0572317935477 -0.0768110548232 -0.0693 -0.0571393851762 -0.0768067824341 -0.06935 -0.0570368373306 -0.0768024173831 -0.0694 -0.0569444697527 -0.0767979577921 -0.06945 -0.0568419750106 -0.0767934016652 -0.0695 -0.0567496075703 -0.0767887470794 -0.06955 -0.0566471231478 -0.0767839920038 -0.0696 -0.0565547110905 -0.0767791344756 -0.06965 -0.0564521899581 -0.0767741724343 -0.0697 -0.056359684126 -0.076769103883 -0.06975 -0.0562570746819 -0.0767639267366 -0.0698 -0.0561644211582 -0.0767586389699 -0.06985 -0.0560616668391 -0.0767532384784 -0.0699 -0.0559688065252 -0.0767477232148 -0.06995 -0.055865845353 -0.0767420910611 -0.07 -0.0557727134838 -0.076736339954 -0.07005 -0.0556694775397 -0.0767304677675 -0.0701 -0.0555760031086 -0.076724472429 -0.07015 -0.0554724179083 -0.076718351811 -0.0702 -0.0553785229936 -0.0767121038383 -0.07025 -0.0552745067629 -0.076705726388 -0.0703 -0.0551801057443 -0.0766992173884 -0.07035 -0.0550755685661 -0.0766925747273 -0.0704 -0.054980567196 -0.0766857963432 -0.07045 -0.0548754100017 -0.0766788801404 -0.0705 -0.0547797043127 -0.0766718240736 -0.07055 -0.0546738177006 -0.0766646260698 -0.0706 -0.0545772927225 -0.0766572841071 -0.07065 -0.0544705555587 -0.076649796141 -0.0707 -0.054373083793 -0.0766421601785 -0.07075 -0.0542653615494 -0.0766343742093 -0.0708 -0.054166801159 -0.0766264362749 -0.07085 -0.0540579439398 -0.0766183444041 -0.0709 -0.0539581365949 -0.0766100966785 -0.07095 -0.0538479767841 -0.0766016911719 -0.071 -0.0537467450881 -0.0765931260112 -0.07105 -0.0536350945277 -0.0765843993199 -0.0711 -0.0535322389235 -0.0765755092746 -0.07115 -0.0534188855193 -0.0765664540519 -0.0712 -0.0533141805589 -0.0765572318824 -0.07125 -0.0531988841761 -0.0765478410007 -0.0713 -0.0530920739999 -0.0765382796959 -0.07135 -0.052974561477 -0.0765285462632 -0.0714 -0.0528653543067 -0.0765186390529 -0.07145 -0.0527453133642 -0.0765085564235 -0.0715 -0.0526333747547 -0.0764982967893 -0.07155 -0.0525104465065 -0.0764878585753 -0.0716 -0.0523953910267 -0.076477240262 -0.07165 -0.0522691607234 -0.0764664403423 -0.0717 -0.0521505416309 -0.0764554573637 -0.07175 -0.0520205271268 -0.0764442898875 -0.0718 -0.0518978234688 -0.0764329365302 -0.07185 -0.0517634607583 -0.0764213959226 -0.0719 -0.0516360611174 -0.0764096667496 -0.07195 -0.0514966860418 -0.07639774771 -0.072 -0.0513638679052 -0.0763856375565 -0.07205 -0.0512186928274 -0.0763733350564 -0.0721 -0.0510795961574 -0.0763608390289 -0.07215 -0.0509276799451 -0.0763481483062 -0.0722 -0.0507812730047 -0.0763352617712 -0.07225 -0.0506214820245 -0.0763221783195 -0.0723 -0.0504665167278 -0.076308896895 -0.07235 -0.0502974735967 -0.0762954164519 -0.0724 -0.0501324265308 -0.0762817359899 -0.07245 -0.0499524420351 -0.0762678545177 -0.0725 -0.0497754356236 -0.0762537710864 -0.07255 -0.049582417133 -0.0762394847521 -0.0726 -0.0493911128725 -0.0762249946093 -0.07265 -0.0491824394566 -0.0762102997552 -0.0727 -0.0489738913178 -0.0761953993207 -0.07275 -0.0487462409883 -0.0761802924335 -0.0728 -0.0485166910071 -0.0761649782504 -0.07285 -0.0482657978808 -0.0761494559203 -0.0729 -0.0480103864609 -0.0761337246142 -0.07295 -0.0477306936003 -0.0761177834876 -0.073 -0.047443041522 -0.076101631712 -0.07305 -0.0471271952595 -0.0760852684358 -0.0731 -0.046798788934 -0.0760686928124 -0.07315 -0.0464368876664 -0.0760519039638 -0.0732 -0.0460561562718 -0.0760349010073 -0.07325 -0.0456346105835 -0.0760176830152 -0.0733 -0.0451855104023 -0.0760002490427 -0.07335 -0.0446852751331 -0.0759825980874 -0.0734 -0.0441450694857 -0.0759647291125 -0.07345 -0.0435388409248 -0.0759466410063 -0.0735 -0.0428745438694 -0.0759283326049 -0.07355 -0.0421222271819 -0.0759098026466 -0.0736 -0.0412848060521 -0.0758910497939 -0.07365 -0.0403260844546 -0.0758720725861 -0.0737 -0.0392409373306 -0.0758528694546 -0.07375 -0.0379831148732 -0.0758334386747 -0.0738 -0.0365346960929 -0.0758137783763 -0.07385 -0.0348336188881 -0.0757938864876 -0.0739 -0.0328425901601 -0.0757737607427 -0.07395 -0.0304770862494 -0.0757533986174 -0.074 -0.0276756323021 -0.0757327973259 -0.07405 -0.0243324044968 -0.0757119537493 -0.0741 -0.0203768122584 -0.075690864417 -0.07415 -0.0157241488232 -0.0756695254207 -0.0742 -0.0103832465007 -0.0756479323783 -0.07425 -0.00444133541767 -0.0756260803215 -0.0743 0.00181174217435 -0.0756039636339 -0.07435 0.00794367576422 -0.0755815758999 -0.0744 0.0133937090269 -0.0755589097966 -0.07445 0.0177067352589 -0.0755359568847 -0.0745 0.020612456506 -0.0755127074196 -0.07455 0.0221310927905 -0.0754891500447 -0.0746 0.0224304460104 -0.075465271465 -0.07465 0.0217864928936 -0.0754410559625 -0.0747 0.0204343340337 -0.0754164848271 -0.07475 0.0186002664196 -0.0753915355458 -0.0748 0.0164264068395 -0.0753661807915 -0.07485 0.0140461256001 -0.0753403870138 -0.0749 0.0115255976026 -0.0753141126293 -0.07495 0.0089412169549 -0.0752873055504 -0.075 0.00631817751086 -0.0752598999893 -0.07505 0.00370359119148 -0.075231812201 -0.0751 0.00110182890163 -0.0752029350275 -0.07515 -0.00145509525289 -0.0751731308255 -0.0752 -0.0039737269408 -0.0751422225459 -0.07525 -0.00643018372932 -0.0751099824459 -0.0753 -0.00883696537098 -0.0750761180628 -0.07535 -0.0111747392716 -0.0750402547671 -0.0754 -0.0134593546361 -0.075001914295 -0.07545 -0.015674139167 -0.0749604882862 -0.0755 -0.0178369450988 -0.0749152058645 -0.07555 -0.0199328383675 -0.0748650938134 -0.0756 -0.0219810881098 -0.0748089278025 -0.07565 -0.0239681740028 -0.0747451725048 -0.0757 -0.0259146520697 -0.0746719081764 -0.07575 -0.0278084135112 -0.0745867404562 -0.0758 -0.0296713609469 -0.0744866896257 -0.07585 -0.0314928539493 -0.074368054456 -0.0759 -0.0332961348309 -0.0742262448591 -0.07595 -0.0350719030325 -0.074055575976 -0.076 -0.0368444319081 -0.0738490148242 -0.07605 -0.0386052072366 -0.0735978682822 -0.0761 -0.0403786589729 -0.073291398702 -0.07615 -0.0421557656473 -0.07291634983 -0.0762 -0.0439592803696 -0.0724563615354 -0.07625 -0.0457771715227 -0.0718912458573 -0.0763 -0.0476272375184 -0.0711960892221 -0.07635 -0.0494903720091 -0.070340134182 -0.0764 -0.0513747681731 -0.0692853769455 -0.07645 -0.053249564892 -0.0679847881027 -0.0765 -0.055109686616 -0.066380012601 -0.07655 -0.0569114016355 -0.0643983048716 -0.0766 -0.0586395128401 -0.0619482491168 -0.07665 -0.0602460145168 -0.0589133695648 -0.0767 -0.0617193337112 -0.0551417461493 -0.07675 -0.0630236365938 -0.0504275398895 -0.0768 -0.0641659049373 -0.0444756240493 -0.07685 -0.0651315470023 -0.036832428993 -0.0769 -0.0659469314961 -0.0267647980707 -0.07695 -0.0666119999196 -0.0131551470581 -0.077 -0.0671613926575 0.00499803569304 -0.07705 -0.0675978298003 0.0257474701955 -0.0771 -0.0679545974682 0.0411131653717 -0.07715 -0.0682308390045 0.0461683344166 -0.0772 -0.0684552305409 0.0464535216656 -0.07725 -0.0686223630231 0.0460214206662 -0.0773 -0.068756698085 0.0453315352359 -0.07735 -0.0688493230188 0.0444375702554 -0.0774 -0.0689217281791 0.043338643345 -0.07745 -0.068962688165 0.0420480029893 -0.0775 -0.0689917566114 0.0405644247197 -0.07755 -0.0689962473646 0.0388979666366 -0.0776 -0.0689944595759 0.0370751920504 -0.07765 -0.0689727843357 0.0351179720269 -0.0777 -0.0689486888767 0.0330391066428 -0.07775 -0.0689079731061 0.0308575514624 -0.0778 -0.0688675341521 0.0285882243295 -0.07785 -0.068812788256 0.0262480593304 -0.0779 -0.0687602286892 0.0238512663989 -0.07795 -0.068695021703 0.0214121008766 -0.078 -0.0686333655534 0.0189426902299 -0.07805 -0.06856026521 0.0164543049057 -0.0781 -0.0684916972218 0.0139564628068 -0.07815 -0.0684125656523 0.011457502588 -0.0782 -0.0683386758633 0.00896431745266 -0.07825 -0.0682548729098 0.00648260309537 -0.0783 -0.0681768263768 0.00401688471837 -0.07835 -0.0680893517778 0.00157061233286 -0.0784 -0.0680080080458 -0.000853695712583 -0.07845 -0.0679176020596 -0.00325443378526 -0.0785 -0.0678336000775 -0.00563074597546 -0.07855 -0.0677408152644 -0.0079825594191 -0.0786 -0.0676546341465 -0.0103104644233 -0.07865 -0.0675598868614 -0.0126158108722 -0.0787 -0.0674718895683 -0.014900686572 -0.07875 -0.067375497043 -0.0171681174504 -0.0788 -0.0672859618937 -0.0194222070427 -0.07885 -0.0671881690344 -0.0216685031364 -0.0789 -0.0670973125005 -0.0239143686073 -0.07895 -0.066998311296 -0.0261695848415 -0.079 -0.0669063045407 -0.0284470140525 -0.07905 -0.0668062481539 -0.030763481395 -0.0791 -0.0667132290443 -0.0331407150042 -0.07915 -0.0666122420664 -0.035606379029 -0.0792 -0.066518323932 -0.0381948883055 -0.07925 -0.0664165098599 -0.0409476113941 -0.0793 -0.0663217878753 -0.0439114051397 -0.07935 -0.0662192345665 -0.0471336935523 -0.0794 -0.0661237904206 -0.0506510057047 -0.07945 -0.0660205740895 -0.0544671567169 -0.0795 -0.0659244794014 -0.058519210006 -0.07955 -0.0658206675388 -0.0626397831911 -0.0796 -0.0657239863548 -0.06654703156 -0.07965 -0.0656196398639 -0.069910598301 -0.0797 -0.0655224304868 -0.072495325517 -0.07975 -0.0654176052498 -0.0742731673151 -0.0798 -0.0653199215765 -0.0753922848421 -0.07985 -0.0652146695937 -0.0760570681874 -0.0799 -0.0651165620841 -0.0764402455938 -0.07995 -0.0650109322989 -0.076658916058 -0.08 -0.0649124486781 -0.0767840249879 -0.08005 -0.0648064875711 -0.0768562633709 -0.0801 -0.0647076733295 -0.0768984622265 -0.08015 -0.0646014253388 -0.076923386246 -0.0802 -0.064502324083 -0.0769382226016 -0.08025 -0.0643958318914 -0.0769470666912 -0.0803 -0.0642964855748 -0.0769522885674 -0.08035 -0.0641897902936 -0.0769552803979 -0.0804 -0.0640902393605 -0.0769568745936 -0.08045 -0.0639833806393 -0.0769575753919 -0.0805 -0.0638836641065 -0.0769576943199 -0.08055 -0.0637766801932 -0.0769574253101 -0.0806 -0.063676835694 -0.076956892115 -0.08065 -0.0635697634673 -0.0769561734248 -0.0807 -0.0634698272757 -0.076955321155 -0.08075 -0.0633627022622 -0.0769543686894 -0.0808 -0.0632627093028 -0.0769533388864 -0.08085 -0.0631555656784 -0.0769522463592 -0.0809 -0.0630555495195 -0.0769511015824 -0.08095 -0.0629484200944 -0.0769499110121 -0.081 -0.0628484129231 -0.0769486795764 -0.08105 -0.0627413291075 -0.0769474100302 -0.0811 -0.062641361687 -0.0769461046931 -0.08115 -0.0625343534393 -0.0769447645746 -0.0812 -0.0624344550503 -0.0769433907038 -0.08125 -0.0623275508141 -0.0769419832375 -0.0813 -0.0622277491861 -0.0769405425295 -0.08135 -0.0621209758176 -0.0769390683053 -0.0814 -0.0620212970561 -0.076937560541 -0.08145 -0.0619146797505 -0.0769360187359 -0.0815 -0.0618151482616 -0.0769344426366 -0.08155 -0.0617087104773 -0.0769328316179 -0.0816 -0.061609348893 -0.0769311852732 -0.08165 -0.0615031122784 -0.0769295029031 -0.0817 -0.0614039413848 -0.0769277839883 -0.08175 -0.061297925708 -0.0769260277796 -0.0818 -0.061198964377 -0.0769242336663 -0.08185 -0.0610931874596 -0.0769224008611 -0.0819 -0.0609944525838 -0.0769205286734 -0.08195 -0.0608889302377 -0.0769186162816 -0.082 -0.0607904366703 -0.0769166629216 -0.08205 -0.0606851826389 -0.0769146677377 -0.0821 -0.0605869431355 -0.0769126298953 -0.08215 -0.0604819690369 -0.0769105485032 -0.0822 -0.0603839942 -0.0769084226575 -0.08225 -0.0602793094731 -0.0769062514285 -0.0823 -0.0601816076994 -0.0769040338438 -0.08235 -0.0600772195518 -0.0769017689317 -0.0824 -0.0599797969814 -0.0768994556512 -0.08245 -0.0598757103398 -0.0768970929853 -0.0825 -0.0597785708072 -0.076894679824 -0.08255 -0.0596747882691 -0.0768922151015 -0.0826 -0.0595779332552 -0.0768896976388 -0.08265 -0.05947445504 -0.0768871263182 -0.0827 -0.0593778836223 -0.0768844998914 -0.08275 -0.0592747075217 -0.0768818171859 -0.0828 -0.0591784163238 -0.0768790768838 -0.08285 -0.0590755376499 -0.0768762777558 -0.0829 -0.0589795207898 -0.0768734184145 -0.08295 -0.0588769323225 -0.0768704975716 -0.083 -0.0587811813572 -0.0768675137707 -0.08305 -0.0586788732858 -0.0768644656635 -0.0831 -0.0585833771496 -0.0768613517254 -0.08315 -0.0584813370074 -0.076858170547 -0.0832 -0.0583860819434 -0.0768549205365 -0.08325 -0.0582842945372 -0.0768516002237 -0.0833 -0.0581892640235 -0.0768482079512 -0.08335 -0.0580877113536 -0.076844742188 -0.0834 -0.0579928860159 -0.0768412012133 -0.08345 -0.0578915471815 -0.0768375834362 -0.0835 -0.0577969046924 -0.0768338870752 -0.08355 -0.0576957557857 -0.0768301104814 -0.0836 -0.0576012707522 -0.0768262518156 -0.08365 -0.0575002847364 -0.0768223093728 -0.0837 -0.0574059285658 -0.0768182812594 -0.08375 -0.0573050751282 -0.0768141657173 -0.0838 -0.057210815871 -0.0768099608023 -0.08385 -0.0571100612575 -0.0768056647065 -0.0839 -0.0570158634296 -0.0768012754392 -0.08395 -0.0569151702496 -0.0767967911467 -0.084 -0.0568209946183 -0.0767922097966 -0.08405 -0.0567203216126 -0.0767875294934 -0.0841 -0.0566261249496 -0.0767827481678 -0.08415 -0.0565254267278 -0.0767778638878 -0.0842 -0.056431161523 -0.076772874553 -0.08425 -0.0563303882486 -0.0767677781997 -0.0843 -0.0562360023682 -0.0767625727022 -0.08435 -0.0561350993925 -0.0767572560703 -0.0844 -0.0560405356881 -0.0767518261588 -0.08445 -0.0559394431276 -0.0767462809572 -0.0845 -0.0558446389735 -0.0767406183065 -0.08455 -0.0557432912055 -0.0767348361816 -0.0846 -0.0556481779559 -0.0767289324161 -0.08465 -0.0555465030365 -0.0767229049765 -0.0847 -0.0554510053964 -0.0767167516959 -0.08475 -0.0553489243761 -0.0767104705387 -0.0848 -0.0552529596566 -0.0767040593436 -0.08485 -0.0551503857719 -0.0766975160793 -0.0849 -0.055053863017 -0.0766908385962 -0.08495 -0.0549507007483 -0.0766840248733 -0.085 -0.0548535197124 -0.076677072779 -0.08505 -0.0547496636697 -0.0766699803087 -0.0851 -0.0546517136052 -0.0766627453553 -0.08515 -0.0545470472102 -0.0766553659373 -0.0852 -0.0544482054344 -0.0766478399777 -0.08525 -0.0543425993646 -0.0766401655238 -0.0853 -0.0542427295675 -0.0766323405345 -0.08535 -0.0541360399079 -0.076624363091 -0.0854 -0.0540349901324 -0.0766162311934 -0.08545 -0.0539270561697 -0.0766079429624 -0.0855 -0.0538246564013 -0.0765994964451 -0.08555 -0.0537152979872 -0.0765908898068 -0.0856 -0.0536113572648 -0.0765821211461 -0.08565 -0.0535003716471 -0.0765731886772 -0.0857 -0.0533946745855 -0.0765640905536 -0.08575 -0.0532818325866 -0.076554825043 -0.0858 -0.0531741351707 -0.0765453903586 -0.08585 -0.0530591765528 -0.0765357848253 -0.0859 -0.0529492010224 -0.0765260067193 -0.08595 -0.0528318288345 -0.0765160544254 -0.086 -0.0527192574313 -0.0765059262846 -0.08605 -0.0525991310818 -0.0764956207449 -0.0861 -0.0524835983568 -0.0764851362154 -0.08615 -0.0523603250608 -0.0764744712092 -0.0862 -0.0522414083519 -0.0764636242047 -0.08625 -0.052114532508 -0.0764525937806 -0.0863 -0.0519917400728 -0.0764413784855 -0.08635 -0.0518607299785 -0.0764299769659 -0.0864 -0.0517334860898 -0.0764183878409 -0.08645 -0.0515977171927 -0.076406609824 -0.0865 -0.0514653432747 -0.0763946416038 -0.08655 -0.0513240768788 -0.07638248196 -0.0866 -0.0511857674241 -0.0763701296508 -0.08665 -0.0510381233853 -0.0763575835209 -0.0867 -0.0508929149236 -0.0763448423942 -0.08675 -0.0507378363013 -0.0763319051775 -0.0868 -0.0505845670156 -0.0763187707592 -0.08685 -0.0504207738118 -0.0763054381052 -0.0869 -0.0502580304213 -0.0762919061629 -0.08695 -0.050083958407 -0.0762781739525 -0.087 -0.0499100054786 -0.0762642404763 -0.08705 -0.0497237242629 -0.0762501048038 -0.0871 -0.0495364089606 -0.0762357659847 -0.08715 -0.0493355108738 -0.0762212231304 -0.0872 -0.0491321328537 -0.0762064753316 -0.08725 -0.0489135800553 -0.0761915217337 -0.0873 -0.0486907111107 -0.0761763614574 -0.08735 -0.0484506219787 -0.0761609936718 -0.0874 -0.0482038520084 -0.0761454175187 -0.08745 -0.0479371977313 -0.0761296321778 -0.0875 -0.0476607706994 -0.0761136367972 -0.08755 -0.0473609364531 -0.0760974305546 -0.0876 -0.0470472188654 -0.0760810125888 -0.08765 -0.0467053567682 -0.0760643820564 -0.0877 -0.0463440459015 -0.0760475380683 -0.08775 -0.0459481009807 -0.0760304797411 -0.0878 -0.0455250201393 -0.0760132061333 -0.08785 -0.0450582319786 -0.0759957162955 -0.0879 -0.044553456576 -0.0759780092084 -0.08795 -0.0439920028678 -0.0759600838251 -0.088 -0.0433768815135 -0.0759419390133 -0.08805 -0.0426860936619 -0.0759235735932 -0.0881 -0.041918419914 -0.0759049862768 -0.08815 -0.0410466030715 -0.0758861757038 -0.0882 -0.0400626926781 -0.0758671403803 -0.08825 -0.0389309784972 -0.0758478787057 -0.0883 -0.0376327377234 -0.0758283889137 -0.08835 -0.0361187919795 -0.0758086690905 -0.0884 -0.0343536440014 -0.0757887171111 -0.08845 -0.032267947564 -0.0757685306519 -0.0885 -0.0298030067778 -0.0757481071191 -0.08855 -0.0268655214893 -0.0757274436505 -0.0886 -0.0233773911999 -0.0757065370368 -0.08865 -0.0192419468793 -0.0756853837042 -0.0887 -0.014414066401 -0.0756639796253 -0.08875 -0.00889726701653 -0.0756423202789 -0.0888 -0.00284641700331 -0.0756204005355 -0.08885 0.00342944033498 -0.0755982145887 -0.0889 0.0094329342876 -0.0755757557998 -0.08895 0.0146329615743 -0.07555301658 -0.089 0.0185916201143 -0.0755299881729 -0.08905 0.0211350191661 -0.0755066604508 -0.0891 0.0223118063726 -0.0754830215915 -0.08915 0.0223472048373 -0.0754590577264 -0.0892 0.0214929673952 -0.0754347524272 -0.08925 0.0200034144145 -0.0754100860888 -0.0893 0.0180635006145 -0.0753850350661 -0.08935 0.0158316304158 -0.0753595705768 -0.0894 0.0134034624031 -0.0753336571945 -0.08945 0.0108664182299 -0.0753072508896 -0.0895 0.00826375057661 -0.0752802963846 -0.08955 0.00564523898141 -0.0752527237113 -0.0896 0.00302738468033 -0.075224443667 -0.08965 0.000440771418807 -0.0751953419759 -0.0897 -0.00211192132618 -0.075165271772 -0.08975 -0.00461026836211 -0.0751340441125 -0.0898 -0.00705903802159 -0.0751014160302 -0.08985 -0.00944340640505 -0.0750670756886 -0.0899 -0.0117722917484 -0.0750306239661 -0.08995 -0.0140340717395 -0.0749915517962 -0.09 -0.0162400791147 -0.0749492122764 -0.09005 -0.0183806659249 -0.0749027864819 -0.0901 -0.0204687515699 -0.0748512415026 -0.09015 -0.0224961505685 -0.0747932790223 -0.0902 -0.0244771011928 -0.0747272722053 -0.09025 -0.0264047894791 -0.0746511882774 -0.0903 -0.0282947926647 -0.0745624934289 -0.09035 -0.0301417332193 -0.0744580360198 -0.0904 -0.0319625738185 -0.0743339029913 -0.09045 -0.0337533406421 -0.074185243331 -0.0905 -0.0355322119938 -0.0740060508607 -0.09055 -0.0372962524509 -0.0737888969163 -0.0906 -0.0390642283711 -0.0735246011094 -0.09065 -0.0408332702006 -0.0732018256116 -0.0907 -0.0426213114361 -0.0728065746683 -0.09075 -0.0444235550478 -0.07232157645 -0.0908 -0.0462544068113 -0.0717255180196 -0.09085 -0.048103655993 -0.070992095699 -0.0909 -0.0499779344937 -0.0700888305057 -0.09095 -0.0518568884171 -0.0689755788883 -0.091 -0.0537348365946 -0.0676026357987 -0.09105 -0.0555781133091 -0.065908266496 -0.0911 -0.0573685500161 -0.0638153835541 -0.09115 -0.0590636501769 -0.0612268352358 -0.0912 -0.0606427919738 -0.0580182255666 -0.09125 -0.06206941285 -0.0540259678817 -0.0913 -0.0633369385732 -0.0490255650379 -0.09135 -0.064428529832 -0.0426895128547 -0.0914 -0.0653587163834 -0.0345058315034 -0.09145 -0.0661290797298 -0.0236459265309 -0.0915 -0.0667670481406 -0.00891903361558 -0.09155 -0.0672810009567 0.0103212350279 -0.0916 -0.0676998582995 0.0306171142726 -0.09165 -0.0680299685771 0.0432991630817 -0.0917 -0.068296242473 0.0464303238185 -0.09175 -0.0685004192487 0.046376647515 -0.0918 -0.0686628605433 0.045868468046 -0.09185 -0.0687813184471 0.0451265240858 -0.0919 -0.0688727388395 0.0441781005562 -0.09195 -0.0689321328163 0.0430305581341 -0.092 -0.0689741872186 0.0416897536033 -0.09205 -0.0689921597868 0.0401588668441 -0.0921 -0.0689992846411 0.0384472465666 -0.09215 -0.0689877082999 0.0365894898939 -0.0922 -0.0689697179394 0.0345991680313 -0.09225 -0.0689367455493 0.0324924310439 -0.0923 -0.0689004433335 0.0302867555215 -0.09235 -0.0688517750106 0.0279976463785 -0.0924 -0.0688019538092 0.025641527265 -0.09245 -0.0687416320574 0.0232324142393 -0.0925 -0.0686817108534 0.0207842749219 -0.09255 -0.0686126341575 0.0183087920033 -0.0926 -0.0685450754973 0.0158170021036 -0.09265 -0.0684693399989 0.0133179320798 -0.0927 -0.0683959314192 0.0108197088983 -0.09275 -0.0683150640135 0.00832877284223 -0.0928 -0.0682371120302 0.00585063093865 -0.09285 -0.06815223246 0.00338942389934 -0.0929 -0.0680706984759 0.000948439649913 -0.09295 -0.0679826336019 -0.00147011650666 -0.093 -0.0678982302026 -0.00386477741132 -0.09305 -0.0678075953071 -0.00623494263363 -0.0931 -0.0677208550125 -0.00858066869605 -0.09315 -0.0676281120141 -0.0109027733628 -0.0932 -0.067539436627 -0.0132027586192 -0.09325 -0.067444935954 -0.0154829631382 -0.0933 -0.0673546321187 -0.0177466461824 -0.09335 -0.0672586429231 -0.0199982661008 -0.0934 -0.0671669478235 -0.0222437783043 -0.09345 -0.0670696798568 -0.0244911206582 -0.0935 -0.0669767798377 -0.0267507850993 -0.09355 -0.0668783993099 -0.0290365747353 -0.0936 -0.0667844434037 -0.0313664746052 -0.09365 -0.0666850845253 -0.0337636514511 -0.0937 -0.0665901942935 -0.0362574386325 -0.09375 -0.0664899676727 -0.0388840700043 -0.0938 -0.0663942443838 -0.041686564042 -0.09385 -0.0662932431653 -0.0447125968092 -0.0939 -0.0661967730399 -0.048008233179 -0.09395 -0.0660950773847 -0.051604170647 -0.094 -0.065997935426 -0.0554907353408 -0.09405 -0.0658956157905 -0.0595813833389 -0.0941 -0.0657978685925 -0.0636780219539 -0.09415 -0.0656949881329 -0.0674761343224 -0.0942 -0.0655966959357 -0.0706546644411 -0.09425 -0.0654933122619 -0.0730258170816 -0.0943 -0.0653945304498 -0.0746156974567 -0.09435 -0.0652906969067 -0.0755987630813 -0.0944 -0.0651914771023 -0.0761768418894 -0.09445 -0.0650872437029 -0.0765086610131 -0.0945 -0.0649876345622 -0.0766979731823 -0.09455 -0.064883048661 -0.0768064932328 -0.0946 -0.0647830964408 -0.076869335951 -0.09465 -0.0646782032113 -0.0769061559327 -0.0947 -0.0645779521683 -0.0769279568381 -0.09475 -0.0644727949338 -0.0769409479206 -0.0948 -0.0643722875966 -0.076948684079 -0.09485 -0.0642669080508 -0.0769532271436 -0.0949 -0.0641661853944 -0.0769557970482 -0.09495 -0.0640606237352 -0.0769571224402 -0.095 -0.0639597252835 -0.0769576502261 -0.09505 -0.063854020291 -0.0769576538343 -0.0951 -0.0637529841723 -0.0769573077912 -0.09515 -0.0636471732473 -0.0769567201927 -0.0952 -0.0635460362231 -0.0769559635718 -0.09525 -0.0634401554088 -0.0769550823728 -0.0953 -0.0633389528882 -0.0769541086795 -0.09535 -0.0632330368778 -0.076953061081 -0.0954 -0.063131802918 -0.0769519547258 -0.09545 -0.0630258850462 -0.0769507971799 -0.0955 -0.0629246523344 -0.0769495961219 -0.09555 -0.0628187645507 -0.0769483542155 -0.0956 -0.0627175643685 -0.0769470756674 -0.09565 -0.062611737193 -0.0769457608832 -0.0957 -0.062510599364 -0.0769444123633 -0.09575 -0.0624048618263 -0.0769430294461 -0.0958 -0.0623038146495 -0.0769416137375 -0.09585 -0.0621981942194 -0.0769401640644 -0.0959 -0.0620972643969 -0.0769386815258 -0.09595 -0.0619917869101 -0.076937164705 -0.096 -0.0618909994719 -0.0769356143851 -0.09605 -0.0617856890544 -0.0769340290376 -0.0961 -0.0616850672834 -0.0769324092271 -0.09615 -0.0615799462777 -0.0769307533787 -0.0962 -0.0614795116374 -0.0769290618898 -0.09625 -0.061374600532 -0.0769273331707 -0.0963 -0.0612743725973 -0.0769255674792 -0.09635 -0.0611696899589 -0.0769237632256 -0.0964 -0.0610696863501 -0.0769219205436 -0.09645 -0.0609652487588 -0.0769200378487 -0.0965 -0.0608654850785 -0.0769181151589 -0.09655 -0.0607613070669 -0.0769161508958 -0.0966 -0.0606617968406 -0.0769141449669 -0.09665 -0.060557890836 -0.0769120957971 -0.0967 -0.0604586454562 -0.0769100031869 -0.09675 -0.0603550217261 -0.076907865561 -0.0968 -0.0602560503992 -0.0769056826143 -0.09685 -0.0601527169994 -0.0769034527673 -0.0969 -0.0600540266945 -0.0769011756105 -0.09695 -0.0599509894188 -0.0768988495554 -0.097 -0.0598525848176 -0.0768964740895 -0.09705 -0.059749847148 -0.0768940476102 -0.0971 -0.0596517305961 -0.0768915695029 -0.09715 -0.0595492936538 -0.0768890381469 -0.0972 -0.0594514651112 -0.0768864528266 -0.09725 -0.0593493276083 -0.0768838118985 -0.0973 -0.0592517846012 -0.076881114547 -0.09735 -0.0591499427904 -0.0768783591025 -0.0974 -0.0590526803594 -0.0768755446505 -0.09745 -0.0589511279812 -0.0768726694918 -0.0975 -0.0588541386262 -0.0768697326147 -0.09755 -0.0587528668512 -0.0768667322876 -0.0976 -0.0586561404723 -0.0768636674034 -0.09765 -0.0585551378411 -0.0768605361961 -0.0977 -0.0584586616753 -0.0768573374655 -0.09775 -0.0583579140298 -0.0768540694093 -0.0978 -0.0582616725774 -0.0768507307369 -0.09785 -0.0581611629824 -0.0768473196089 -0.0979 -0.0580651379233 -0.076843834647 -0.09795 -0.0579648465793 -0.0768402739745 -0.098 -0.0578690166817 -0.0768366361288 -0.09805 -0.0577689208247 -0.0768329191963 -0.0981 -0.0576732618346 -0.0768291216345 -0.09815 -0.0575733356167 -0.0768252414935 -0.0982 -0.0574778201306 -0.0768212771548 -0.09825 -0.0573780344863 -0.076817226634 -0.0983 -0.0572826318076 -0.0768130882416 -0.09835 -0.0571829542954 -0.0768088599603 -0.0984 -0.0570876302613 -0.0768045400347 -0.09845 -0.0569880248762 -0.0768001264178 -0.0985 -0.0568927416573 -0.0767956172934 -0.09855 -0.0567931686185 -0.0767910105879 -0.0986 -0.0566978844892 -0.0767863044303 -0.09865 -0.0565982999866 -0.076781496724 -0.0987 -0.0565029690474 -0.0767765855493 -0.09875 -0.0564033249452 -0.0767715687913 -0.0988 -0.0563078968082 -0.0767664444883 -0.09885 -0.0562081403041 -0.0767612105109 -0.0989 -0.05611255972 -0.076755864862 -0.09895 -0.0560126329388 -0.0767504054029 -0.099 -0.0559168393578 -0.0767448301078 -0.09905 -0.0558166788819 -0.0767391368337 -0.0991 -0.0557206059493 -0.0767333235328 -0.09915 -0.0556201422689 -0.0767273880632 -0.0992 -0.0555237172247 -0.0767213283625 -0.09925 -0.0554228740873 -0.0767151422955 -0.0993 -0.0553260170662 -0.0767088277925 -0.09935 -0.0552247107229 -0.0767023827307 -0.0994 -0.0551273339365 -0.0766958050394 -0.09945 -0.0550254722509 -0.0766890926141 -0.0995 -0.0549274790187 -0.0766822433902 -0.09955 -0.0548249604155 -0.0766752552863 -0.0996 -0.0547262440266 -0.076668126251 -0.09965 -0.0546229562589 -0.0766608542321 -0.0997 -0.054523398631 -0.0766534371983 -0.09975 -0.0544192173179 -0.076645873132 -0.0998 -0.0543186874034 -0.0766381600278 -0.09985 -0.054213474293 -0.0766302959079 -0.0999 -0.0541118261856 -0.0766222787986 -0.09995 -0.0540054270905 -0.0766141067666 -0.1 -0.0539024977718 -0.0766057778762 -0.10005 -0.0537947401051 -0.0765972902439 -0.1001 -0.0536903467457 -0.0765886419771 -0.10015 -0.0535810365625 -0.0765798312461 -0.1002 -0.0534749732773 -0.0765708562061 -0.10025 -0.0533638917116 -0.0765617150844 -0.1003 -0.0532559256415 -0.0765524060888 -0.10035 -0.0531428245927 -0.0765429275083 -0.1004 -0.0530326911502 -0.0765332776071 -0.10045 -0.0529172880364 -0.0765234547383 -0.1005 -0.0528046851064 -0.0765134572255 -0.10055 -0.052686656442 -0.0765032834879 -0.1006 -0.0525712372616 -0.076492931912 -0.10065 -0.0524502107545 -0.0764824009858 -0.1007 -0.0523315751244 -0.0764716891609 -0.10075 -0.0522071198856 -0.0764607949945 -0.1008 -0.0520848032435 -0.0764497170039 -0.10085 -0.0519564175684 -0.0764384538171 -0.1009 -0.0518298773045 -0.076427004019 -0.10095 -0.0516969733157 -0.0764153663082 -0.101 -0.0515655715037 -0.0764035393361 -0.10105 -0.0514274556972 -0.0763915218707 -0.1011 -0.0512904371217 -0.0763793126304 -0.10115 -0.0511462854914 -0.0763669104517 -0.1012 -0.0510027494323 -0.0763543141178 -0.10125 -0.0508515753896 -0.0763415225303 -0.1013 -0.0507004390457 -0.0763285345351 -0.10135 -0.050541051603 -0.0763153490971 -0.1014 -0.0503810021713 -0.0763019651212 -0.10145 -0.0502119508727 -0.0762883816298 -0.1015 -0.0500413820619 -0.0762745975824 -0.10155 -0.049860883577 -0.0762606120552 -0.1016 -0.0496778104642 -0.0762464240566 -0.10165 -0.0494836495005 -0.0762320327083 -0.1017 -0.0492855928331 -0.0762174370606 -0.10175 -0.0490749865581 -0.0762026362747 -0.1018 -0.0488588132707 -0.0761876294337 -0.10185 -0.0486282229792 -0.076172415727 -0.1019 -0.0483899229073 -0.0761569942614 -0.10195 -0.0481347881953 -0.0761413642442 -0.102 -0.0478691562135 -0.0761255247921 -0.10205 -0.0475835131391 -0.076109475116 -0.1021 -0.0472836883073 -0.0760932143295 -0.10215 -0.0469596104773 -0.0760767416308 -0.1022 -0.0466163947607 -0.0760600561111 -0.10225 -0.0462431585407 -0.0760431569372 -0.1023 -0.045843988431 -0.0760260431579 -0.10235 -0.0454067991521 -0.0760087138833 -0.1024 -0.0449341591626 -0.0759911680942 -0.10245 -0.0444121641699 -0.0759734048174 -0.1025 -0.0438410847684 -0.0759554229326 -0.10255 -0.0432042062454 -0.0759372213483 -0.1026 -0.0424982355762 -0.0759187988064 -0.10265 -0.0417020262431 -0.0759001540526 -0.1027 -0.0408066416759 -0.075881285643 -0.10275 -0.0397838379997 -0.0758621921081 -0.1028 -0.0386156366136 -0.0758428717565 -0.10285 -0.0372624134766 -0.0758233228356 -0.1029 -0.0356918718885 -0.0758035433304 -0.10295 -0.0338467790546 -0.0757835311159 -0.103 -0.0316737583405 -0.0757632837544 -0.10305 -0.0290919199657 -0.0757427986337 -0.1031 -0.0260243647903 -0.0757220727595 -0.10315 -0.0223735756317 -0.0757011028802 -0.1032 -0.0180662362902 -0.075679885265 -0.10325 -0.0130518907304 -0.0756584158121 -0.1033 -0.00738035431952 -0.0756366898065 -0.10335 -0.00123000773739 -0.0756147019995 -0.1034 0.00502384153779 -0.0755924463384 -0.10345 0.0108736874014 -0.0755699159989 -0.1035 0.01578278171 -0.0755471030675 -0.10355 0.0193865786555 -0.075523998501 -0.1036 0.0215603719606 -0.0755005917237 -0.10365 0.022421902427 -0.0754768704675 -0.1037 0.0221994257886 -0.0754528202142 -0.10375 0.0211629491421 -0.0754284238254 -0.1038 0.0195373151376 -0.0754036607036 -0.10385 0.0175130131363 -0.075378506039 -0.1039 0.015218486068 -0.0753529294552 -0.10395 0.0127591411726 -0.0753268935589 -0.104 0.0101975018835 -0.0753003516612 -0.10405 0.00759074330241 -0.0752732451043 -0.1041 0.00496694944968 -0.0752454994017 -0.10415 0.00235872681604 -0.0752170195426 -0.1042 -0.000223427413842 -0.0751876835991 -0.10425 -0.00275969075021 -0.0751573348885 -0.1043 -0.00524890350358 -0.0751257717477 -0.10435 -0.00767818932901 -0.0750927350346 -0.1044 -0.0100515376739 -0.0750578922832 -0.10445 -0.012359980518 -0.0750208184101 -0.1045 -0.0146104467066 -0.074980971663 -0.10455 -0.0167962846434 -0.0749376643622 -0.1046 -0.0189262476045 -0.0748900267188 -0.10465 -0.0209952613325 -0.0748369627504 -0.1047 -0.0230134611195 -0.0747770959374 -0.10475 -0.0249771343078 -0.0747087028309 -0.1048 -0.026897742283 -0.074629631289 -0.10485 -0.028772971848 -0.0745372003368 -0.1049 -0.0306156766196 -0.0744280768602 -0.10495 -0.0324249743347 -0.0742981242907 -0.105 -0.034215048489 -0.0741422162579 -0.10505 -0.0359862333032 -0.0739540075624 -0.1051 -0.037753615991 -0.0737256519965 -0.10515 -0.0395180393843 -0.0734474550251 -0.1052 -0.0412944170776 -0.0731074454251 -0.10525 -0.0430825447747 -0.0726908469774 -0.1053 -0.0448949996939 -0.0721794254093 -0.10535 -0.0467276366178 -0.0715506798897 -0.1054 -0.0485870042683 -0.070776838132 -0.10545 -0.0504606058702 -0.0698236010473 -0.1055 -0.052344197594 -0.0686485598692 -0.10555 -0.0542126116636 -0.0671991710628 -0.1056 -0.0560482478769 -0.0654101016163 -0.10565 -0.0578141484041 -0.0631996138945 -0.1057 -0.0594852379347 -0.0604643533726 -0.10575 -0.0610241877067 -0.0570712329057 -0.1058 -0.0624140286579 -0.0528436059182 -0.10585 -0.0636333100509 -0.0475356176135 -0.1059 -0.0646855391847 -0.0407820844548 -0.10595 -0.0655700727423 -0.03200345827 -0.106 -0.0663075611516 -0.0202690769631 -0.10605 -0.0669087084626 -0.0043624667387 -0.1061 -0.0673994278315 0.0157575349179 -0.10615 -0.0677908697786 0.0349364010831 -0.1062 -0.0681062261875 0.0447874264551 -0.10625 -0.0683524156838 0.0465123797185 -0.1063 -0.0685479472253 0.0462716130081 -0.10635 -0.068695344106 0.0456937450293 -0.1064 -0.0688092379216 0.0449003716991 -0.10645 -0.0688889478989 0.0438977574278 -0.1065 -0.0689464647398 0.0427010964838 -0.10655 -0.0689790206907 0.0413097847517 -0.1066 -0.0689969060435 0.0397314313783 -0.10665 -0.0689960276088 0.0379790512821 -0.1067 -0.0689855795899 0.0360862266616 -0.10675 -0.0689606183649 0.0340637949689 -0.1068 -0.0689296148779 0.0319301536626 -0.10685 -0.0688870683273 0.0297012312346 -0.1069 -0.0688409585053 0.0273934550968 -0.10695 -0.068785412263 0.0250222559035 -0.107 -0.068728066735 0.0226018918643 -0.10705 -0.0686627964673 0.020145604237 -0.1071 -0.0685969938736 0.0176649963903 -0.10715 -0.0685243614573 0.0151705331794 -0.1072 -0.0684521132681 0.012671031825 -0.10725 -0.0683738347359 0.01017415908 -0.1073 -0.0682966074664 0.00768611395458 -0.10735 -0.0682139381439 0.00521203455699 -0.1074 -0.0681328082031 0.0027558352406 -0.10745 -0.0680466726417 0.000320511148221 -0.1075 -0.067962435644 -0.00209192792692 -0.10755 -0.0678735197875 -0.00448024916193 -0.1076 -0.067786768406 -0.00684402177861 -0.10765 -0.067695585448 -0.00918350401785 -0.1077 -0.0676067651931 -0.0114996820378 -0.10775 -0.0675137028746 -0.0137942690086 -0.1078 -0.0674231522339 -0.0160698199048 -0.10785 -0.0673285069355 -0.0183298824259 -0.1079 -0.0672364863575 -0.0205792607626 -0.10795 -0.0671404877492 -0.0228243778201 -0.108 -0.0670472006175 -0.0250737651686 -0.10805 -0.066950029529 -0.0273386970921 -0.1081 -0.0668556373933 -0.0296339645571 -0.10815 -0.0667574387897 -0.0319787968485 -0.1082 -0.0666620724325 -0.0343978613927 -0.10825 -0.066562964868 -0.0369222277392 -0.1083 -0.0664667323786 -0.0395899469963 -0.10835 -0.0663668148872 -0.0424455666621 -0.1084 -0.0662698075462 -0.0455371799654 -0.10845 -0.0661691646742 -0.0489085904484 -0.1085 -0.0660714612629 -0.0525829741817 -0.10855 -0.065970166757 -0.056534610576 -0.1086 -0.0658718367072 -0.0606507190517 -0.10865 -0.0657699562064 -0.0647023912854 -0.1087 -0.0656710619053 -0.0683683962097 -0.10875 -0.0655686549125 -0.0713478238192 -0.1088 -0.0654692533894 -0.0735063916804 -0.10885 -0.0653663747161 -0.0749196188973 -0.1089 -0.0652665188759 -0.0757796947905 -0.10895 -0.0651632196906 -0.0762811980803 -0.109 -0.0650629592047 -0.0765682036608 -0.10905 -0.0649592877918 -0.0767320180302 -0.1091 -0.0648586697432 -0.0768261363285 -0.10915 -0.064754672047 -0.0768808020602 -0.1092 -0.0646537413869 -0.0769129256011 -0.10925 -0.0645494613947 -0.0769319861628 -0.1093 -0.0644482612604 -0.0769433524307 -0.10935 -0.0643437412602 -0.0769501066494 -0.1094 -0.0642423131806 -0.0769540469796 -0.10945 -0.0641375939229 -0.0769562386627 -0.1095 -0.0640359779437 -0.0769573236413 -0.10955 -0.0639310987368 -0.0769576941364 -0.1096 -0.0638293334906 -0.0769575940423 -0.10965 -0.0637243322512 -0.0769571765925 -0.1097 -0.0636224549947 -0.0769565399242 -0.10975 -0.0635173682757 -0.076955747161 -0.1098 -0.0634154149104 -0.0769548398563 -0.10985 -0.0633102779142 -0.0769538452032 -0.1099 -0.0632082829922 -0.0769527815578 -0.10995 -0.0631031295688 -0.0769516610273 -0.11 -0.0630011262813 -0.0769504919611 -0.11005 -0.0628959889076 -0.0769492798244 -0.1101 -0.0627940090559 -0.0769480284383 -0.11015 -0.0626889187967 -0.0769467402126 -0.1102 -0.062586992744 -0.0769454168217 -0.11025 -0.0624819791974 -0.0769440592101 -0.1103 -0.0623801358078 -0.0769426679862 -0.11035 -0.0622752270381 -0.0769412433615 -0.1104 -0.0621734936061 -0.0769397853872 -0.11045 -0.0620687160717 -0.076938293891 -0.1105 -0.0619671182482 -0.0769367686148 -0.11055 -0.0618624967265 -0.0769352091731 -0.1106 -0.061761058444 -0.0769336151236 -0.11065 -0.0616566159565 -0.0769319859523 -0.1107 -0.0615553593547 -0.0769303210967 -0.11075 -0.0614511170943 -0.076928619957 -0.1108 -0.0613500624492 -0.0769268818843 -0.11085 -0.0612460397112 -0.0769251062139 -0.1109 -0.0611452053675 -0.0769232922281 -0.11095 -0.0610414194835 -0.0769214392068 -0.111 -0.060940821791 -0.0769195463726 -0.11105 -0.0608372880673 -0.0769176129541 -0.1111 -0.0607369413211 -0.0769156381182 -0.11115 -0.0606336729808 -0.0769136210427 -0.1112 -0.0605335893637 -0.0769115608406 -0.11125 -0.0604305974901 -0.0769094566378 -0.1113 -0.0603307870186 -0.0769073074932 -0.11135 -0.0602280805022 -0.0769051124792 -0.1114 -0.0601285509737 -0.0769028705999 -0.11145 -0.0600261364606 -0.0769005808716 -0.1115 -0.0599268934031 -0.0768982422424 -0.11155 -0.0598247752458 -0.0768958536702 -0.1116 -0.0597258218695 -0.0768934140454 -0.11165 -0.0596240020786 -0.0768909222659 -0.1117 -0.0595253392274 -0.0768883771631 -0.11175 -0.0594238174226 -0.0768857775723 -0.1118 -0.0593254435245 -0.0768831222648 -0.11185 -0.0592242168846 -0.0768804100121 -0.1119 -0.0591261279006 -0.0768776395237 -0.11195 -0.059025191111 -0.0768748095061 -0.112 -0.0589273804826 -0.0768719186067 -0.11205 -0.0588267256823 -0.0768689654661 -0.1121 -0.0587291842747 -0.0768659486689 -0.11215 -0.0586288009957 -0.0768628667896 -0.1122 -0.058531517035 -0.07685971835 -0.11225 -0.0584313921355 -0.0768565018589 -0.1123 -0.0583343511379 -0.0768532157759 -0.11235 -0.05823446873 -0.0768498585444 -0.1124 -0.0581376534259 -0.0768464285628 -0.11245 -0.058037994792 -0.0768429242109 -0.1125 -0.057941385035 -0.0768393438267 -0.11255 -0.05784192853 -0.0768356857281 -0.1126 -0.0577455011925 -0.0768319481957 -0.11265 -0.0576462221349 -0.0768281294879 -0.1127 -0.0575499509919 -0.0768242278296 -0.11275 -0.0574508215353 -0.0768202414228 -0.1128 -0.0573546771237 -0.07681616844 -0.11285 -0.0572556661049 -0.07681200703 -0.1129 -0.0571596155614 -0.0768077553163 -0.11295 -0.0570606883286 -0.0768034113985 -0.113 -0.0569646952043 -0.0767989733553 -0.11305 -0.056865813413 -0.076794439241 -0.1131 -0.0567698374492 -0.0767898070938 -0.11315 -0.0566709588214 -0.076785074928 -0.1132 -0.0565749556948 -0.0767802407457 -0.11325 -0.0564760337456 -0.0767753025266 -0.1133 -0.0563799547688 -0.0767702582425 -0.11335 -0.0562809384773 -0.0767651058435 -0.1134 -0.0561847302429 -0.0767598432764 -0.11345 -0.0560855636734 -0.076754468468 -0.1135 -0.0559891676483 -0.0767489793455 -0.11355 -0.0558897895079 -0.076743373818 -0.1136 -0.0557931415492 -0.0767376497995 -0.11365 -0.0556934846636 -0.0767318051874 -0.1137 -0.0555965144554 -0.0767258378882 -0.11375 -0.0554965051631 -0.0767197457946 -0.1138 -0.0553991355606 -0.0767135268123 -0.11385 -0.0552986929986 -0.0767071788354 -0.1139 -0.0552008392502 -0.076700699775 -0.11395 -0.055099874512 -0.0766940875327 -0.114 -0.0550014433516 -0.0766873400311 -0.11405 -0.0548998585049 -0.076680455186 -0.1141 -0.0548007470835 -0.0766734309371 -0.11415 -0.0546984340069 -0.0766662652205 -0.1142 -0.0545985286267 -0.076658956 -0.11425 -0.054495367633 -0.0766515012383 -0.1143 -0.0543945422515 -0.076643898929 -0.11435 -0.0542904004629 -0.0766361470668 -0.1144 -0.0541885149235 -0.0766282436804 -0.11445 -0.0540832443377 -0.0766201868021 -0.1145 -0.0539801422555 -0.0766119745008 -0.11455 -0.0538735774368 -0.0766036048524 -0.1146 -0.0537690836743 -0.0765950759717 -0.11465 -0.0536610389895 -0.0765863859825 -0.1147 -0.0535549566275 -0.0765775330498 -0.11475 -0.0534452229224 -0.0765685153495 -0.1148 -0.0533373296086 -0.0765593311007 -0.11485 -0.0532256701929 -0.076549978536 -0.1149 -0.0531157137215 -0.0765404559332 -0.11495 -0.0530018594932 -0.0765307615849 -0.115 -0.0528895524193 -0.0765208938302 -0.11505 -0.0527731959111 -0.0765108510243 -0.1151 -0.0526582089608 -0.0765006315702 -0.11515 -0.0525389970296 -0.076490233889 -0.1152 -0.052420950975 -0.0764796564502 -0.11525 -0.0522984757624 -0.0764688977421 -0.1153 -0.0521769313513 -0.0764579563017 -0.11535 -0.0520507190406 -0.0764468306853 -0.1154 -0.0519251644168 -0.0764355194987 -0.11545 -0.0517946611379 -0.0764240213677 -0.1155 -0.051664496021 -0.0764123349668 -0.11555 -0.051529050046 -0.0764004589899 -0.1156 -0.0513935656534 -0.0763883921793 -0.11565 -0.0512524047178 -0.0763761332972 -0.1157 -0.0511107580791 -0.0763636811528 -0.11575 -0.0509629602193 -0.076351034574 -0.1158 -0.050814140997 -0.0763381924337 -0.11585 -0.050658596697 -0.076325153623 -0.1159 -0.0505013838886 -0.0763119170769 -0.11595 -0.0503367464292 -0.0762984817457 -0.116 -0.0501696512536 -0.0762848466203 -0.11605 -0.0499942708169 -0.0762710107059 -0.1161 -0.049815460471 -0.076256973046 -0.11615 -0.0496272956345 -0.0762427326939 -0.1162 -0.049434490201 -0.0762282887373 -0.11625 -0.0492309874467 -0.0762136402713 -0.1163 -0.0490213185585 -0.0761987864211 -0.11635 -0.0487992458649 -0.0761837263138 -0.1164 -0.048569060006 -0.0761684591011 -0.11645 -0.0483242733856 -0.0761529839329 -0.1165 -0.0480688536353 -0.0761372999767 -0.11655 -0.0477959640278 -0.0761214063904 -0.1166 -0.0475091294262 -0.0761053023436 -0.11665 -0.0472010185564 -0.0760889869892 -0.1167 -0.0468745361923 -0.0760724594809 -0.11675 -0.0465216389995 -0.0760557189472 -0.1168 -0.0461443435479 -0.0760387645081 -0.11685 -0.045733562019 -0.0760215952456 -0.1169 -0.0452900084557 -0.0760042102203 -0.11695 -0.0448030311743 -0.0759866084428 -0.117 -0.0442713871835 -0.0759687888855 -0.11705 -0.0436820317176 -0.0759507504538 -0.1171 -0.0430307093029 -0.0759324919971 -0.11715 -0.0423006331553 -0.0759140122766 -0.1172 -0.0414828065245 -0.0758953099733 -0.11725 -0.0405544826837 -0.0758763836554 -0.1173 -0.0394990837519 -0.0758572317807 -0.11735 -0.038284290396 -0.0758378526609 -0.1174 -0.0368814116176 -0.0758182444613 -0.11745 -0.0352430198963 -0.0757984051575 -0.1175 -0.0333218818566 -0.0757783325302 -0.11755 -0.0310487165401 -0.0757580241167 -0.1176 -0.028352261533 -0.0757374771935 -0.11765 -0.025140663884 -0.0757166887211 -0.1177 -0.0213295946656 -0.075695655313 -0.11775 -0.0168393630772 -0.0756743731654 -0.1178 -0.0116489239337 -0.07565283801 -0.11785 -0.00582690525612 -0.0756310450187 -0.1179 0.000390457600968 -0.0756089887311 -0.11795 0.00659515627967 -0.0755866629241 -0.118 0.0122473257722 -0.0755640604937 -0.11805 0.0168480203979 -0.0755411732711 -0.1181 0.0200815245587 -0.0755179918285 -0.11815 0.0219014431337 -0.0754945052025 -0.1182 0.0224561342659 -0.0754707005718 -0.11825 0.0220013232821 -0.0754465628135 -0.1183 0.0207903679837 -0.0754220739553 -0.11835 0.019048575176 -0.0753972124252 -0.1184 0.0169411157486 -0.075371952092 -0.11845 0.0145981425506 -0.0753462609559 -0.1185 0.0121044978021 -0.0753200994402 -0.11855 0.00952926823182 -0.075293418085 -0.1186 0.00691304474137 -0.0752661545322 -0.11865 0.00429333480047 -0.0752382295299 -0.1187 0.00168823029816 -0.0752095417727 -0.11875 -0.000880961451657 -0.0751799612231 -0.1188 -0.00340790549651 -0.0751493206429 -0.11885 -0.00587995870409 -0.0751174048797 -0.1189 -0.00829719137993 -0.0750839375066 -0.11895 -0.010651772186 -0.075048564207 -0.119 -0.0129473778931 -0.0750108322832 -0.11905 -0.0151789553139 -0.0749701654139 -0.1191 -0.0173523302128 -0.0749258326861 -0.11915 -0.0194642180634 -0.0748769105801 -0.1192 -0.0215219382595 -0.0748222363824 -0.11925 -0.0235235973103 -0.0747603510225 -0.1193 -0.0254778400914 -0.074689428963 -0.11935 -0.0273841388473 -0.074607192108 -0.1194 -0.0292525151883 -0.0745108040908 -0.11945 -0.0310838700755 -0.0743967403412 -0.1195 -0.0328896147821 -0.0742606283764 -0.11955 -0.0346719830031 -0.0740970513323 -0.1196 -0.0364435128714 -0.0738993062331 -0.11965 -0.0382072789344 -0.0736591063499 -0.1197 -0.039976151898 -0.0733662145575 -0.11975 -0.041752858108 -0.073007991264 -0.1198 -0.0435489015615 -0.0725688364564 -0.11985 -0.0453643197835 -0.072029499886 -0.1199 -0.0472061525056 -0.0713662262105 -0.11995 -0.0490678548549 -0.0705496914543 -0.12 -0.0509474507661 -0.0695436716528 -0.12005 -0.0528270664997 -0.0683033590717 -0.1201 -0.0546916983298 -0.0667731966537 -0.12015 -0.0565102998297 -0.0648840157207 -0.1202 -0.0582568846005 -0.0625490878715 -0.12025 -0.0598945552893 -0.0596583292725 -0.1203 -0.0613990576876 -0.0560690709823 -0.12035 -0.0627438026037 -0.0515899627991 -0.1204 -0.0639219512746 -0.045950572715 -0.12045 -0.0649279264357 -0.0387417978343 -0.1205 -0.0657750518604 -0.0293066520413 -0.12055 -0.0664735477027 -0.0166112689619 -0.1206 -0.0670464434034 0.000503212908887 -0.12065 -0.0675078506161 0.0211651227243 -0.1207 -0.0678802387013 0.0385634095219 -0.12075 -0.0681744937085 0.0457048743835 -0.1208 -0.068408627001 0.0464979767031 -0.12085 -0.0685888903917 0.0461425636434 -0.1209 -0.0687289943549 0.0455016853845 -0.12095 -0.068831506675 0.0446552834806 -0.121 -0.0689070641417 0.0435999818707 -0.12105 -0.0689557664567 0.0423532355951 -0.1211 -0.0689862508718 0.0409118485892 -0.12115 -0.0689970421097 0.0392860061077 -0.1212 -0.0689954964132 0.0374951753143 -0.12125 -0.0689791317044 0.035567511437 -0.1213 -0.0689544694907 0.0335142660892 -0.12135 -0.0689183711408 0.0313545554501 -0.1214 -0.0688767994039 0.0291035512232 -0.12145 -0.0688261777491 0.0267780748852 -0.1215 -0.0687720847807 0.0243928602351 -0.12155 -0.0687106464764 0.0219621711168 -0.1216 -0.0686471711762 0.0194986679898 -0.12165 -0.0685775802889 0.0170137439022 -0.1217 -0.0685069883236 0.0145173869448 -0.12175 -0.0684311752461 0.0120181179562 -0.1218 -0.0683551142443 0.00952321850285 -0.12185 -0.0682744876012 0.00703858186471 -0.1219 -0.0681941638956 0.00456904082918 -0.12195 -0.0681097585019 0.00211823268946 -0.122 -0.0680260613669 -0.000311086300415 -0.12205 -0.0679386428149 -0.00271714294838 -0.1221 -0.0678522326948 -0.00509889495889 -0.12215 -0.0677623719075 -0.0074561156355 -0.1222 -0.0676737435073 -0.0097892327801 -0.12225 -0.0675818701904 -0.012099432317 -0.1223 -0.067491397805 -0.014388620274 -0.12235 -0.0673978389303 -0.0166596010726 -0.1224 -0.0673058091394 -0.0189162096717 -0.12245 -0.0672108167346 -0.0211636370797 -0.1225 -0.0671174520484 -0.023408793598 -0.12255 -0.067021223329 -0.0256608587556 -0.1226 -0.0669266993278 -0.0279319331664 -0.12265 -0.0668293913037 -0.0302378655949 -0.1227 -0.0667338491016 -0.0325991932261 -0.12275 -0.0666355892099 -0.0350421552517 -0.1228 -0.0665391445217 -0.0375995978741 -0.12285 -0.0664400383678 -0.0403113657354 -0.1229 -0.0663427881294 -0.0432233490871 -0.12295 -0.0662429251495 -0.0463835493077 -0.123 -0.0661449523548 -0.0498324281037 -0.12305 -0.066044409947 -0.0535837251866 -0.1231 -0.065945787182 -0.0575929993576 -0.12315 -0.0658446337324 -0.061718994153 -0.1232 -0.0657454257675 -0.0657032763745 -0.12325 -0.0656437228694 -0.0692157016513 -0.1233 -0.0655439885537 -0.0719862658909 -0.12335 -0.0654417926238 -0.0739374190193 -0.1234 -0.065341586267 -0.0751871463925 -0.12345 -0.0652389497268 -0.075937269046 -0.1235 -0.0651383221069 -0.0763716802884 -0.12355 -0.0650352942412 -0.0766198095634 -0.1236 -0.0649342933352 -0.0767615821755 -0.12365 -0.0648309209104 -0.0768432442888 -0.1237 -0.0647295924133 -0.0768908206701 -0.12375 -0.0646259201124 -0.0769188559157 -0.1238 -0.0645243078007 -0.0769355219725 -0.12385 -0.0644203785229 -0.0769454608015 -0.1239 -0.0643185244979 -0.0769513495426 -0.12395 -0.064214379554 -0.0769547549575 -0.124 -0.0641123243958 -0.0769566104872 -0.12405 -0.0640080036257 -0.0769574796242 -0.1241 -0.0639057864809 -0.0769577092207 -0.12415 -0.0638013283189 -0.0769575146572 -0.1242 -0.0636989869481 -0.0769570327507 -0.12425 -0.0635944284563 -0.0769563504895 -0.1243 -0.0634919992584 -0.076955524837 -0.12435 -0.0633873761445 -0.0769545926364 -0.1244 -0.0632848941675 -0.0769535787335 -0.12445 -0.0631802407888 -0.0769524993251 -0.1245 -0.0630777397261 -0.0769513656394 -0.12455 -0.0629730890762 -0.0769501849522 -0.1246 -0.062870601244 -0.0769489624233 -0.12465 -0.0627659849212 -0.0769477013005 -0.1247 -0.0626635412179 -0.0769464039062 -0.12475 -0.0625589893768 -0.0769450715946 -0.1248 -0.0624566192266 -0.0769437052958 -0.12485 -0.0623521605141 -0.0769423054382 -0.1249 -0.0622498917988 -0.076940872233 -0.12495 -0.0621455532832 -0.0769394056374 -0.125 -0.0620434122684 -0.0769379054687 -0.12505 -0.0619392193641 -0.0769363714322 -0.1251 -0.0618372306238 -0.0769348031143 -0.12515 -0.0617332070164 -0.0769332000757 -0.1252 -0.0616313933588 -0.0769315617558 -0.12525 -0.0615275609316 -0.0769298876242 -0.1253 -0.0614259433272 -0.0769281770175 -0.12535 -0.0613223220916 -0.0769264293399 -0.1254 -0.061220919605 -0.0769246438488 -0.12545 -0.0611175276335 -0.0769228198953 -0.1255 -0.0610163573582 -0.0769209566702 -0.12555 -0.0609132107209 -0.0769190534757 -0.1256 -0.0608122877173 -0.0769171094429 -0.12565 -0.0607094004212 -0.0769151238261 -0.1257 -0.0606087376579 -0.0769130956993 -0.12575 -0.0605061215905 -0.0769110242677 -0.1258 -0.060405729889 -0.0769089085498 -0.12585 -0.0603033947643 -0.0769067476993 -0.1259 -0.0602032827466 -0.076904540679 -0.12595 -0.0601012360537 -0.0769022865884 -0.126 -0.0600014100918 -0.0768999843341 -0.12605 -0.0598996570448 -0.0768976329587 -0.1261 -0.0598001212108 -0.0768952313113 -0.12615 -0.0596986646993 -0.0768927783751 -0.1262 -0.0595994207164 -0.0768902729409 -0.12625 -0.0594982612567 -0.0768877139299 -0.1263 -0.0593993084501 -0.0768851000736 -0.12635 -0.0592984441365 -0.0768824302293 -0.1264 -0.0591997793846 -0.0768797030679 -0.12645 -0.0590992058387 -0.0768769173815 -0.1265 -0.0590008235207 -0.0768740717796 -0.12655 -0.0589005338374 -0.0768711649878 -0.1266 -0.0588024257771 -0.0768681955542 -0.12665 -0.0587024104662 -0.076865162137 -0.1267 -0.0586045658715 -0.0768620632227 -0.12675 -0.0585048127959 -0.0768588974024 -0.1268 -0.0584072181939 -0.0768556631013 -0.12685 -0.0583077124988 -0.0768523588437 -0.1269 -0.0582103516595 -0.0768489829947 -0.12695 -0.0581110756906 -0.0768455340124 -0.127 -0.0580139295409 -0.076842010203 -0.12705 -0.0579148627557 -0.0768384099603 -0.1271 -0.0578179092841 -0.0768347315335 -0.12715 -0.0577190281467 -0.0768309732544 -0.1272 -0.0576222422886 -0.0768271333175 -0.12725 -0.057523520146 -0.0768232099952 -0.1273 -0.0574268736522 -0.0768192014302 -0.12735 -0.0573282805951 -0.0768151058385 -0.1274 -0.0572317418818 -0.0768109213145 -0.12745 -0.0571332445799 -0.0768066460214 -0.1275 -0.0570367785475 -0.0768022780089 -0.12755 -0.0569383400546 -0.0767978153921 -0.1276 -0.0568419078816 -0.0767932561801 -0.12765 -0.0567434874145 -0.076788598444 -0.1277 -0.0566470463161 -0.0767838401571 -0.12775 -0.0565485989898 -0.0767789793518 -0.1278 -0.0564521019301 -0.0767740139711 -0.12785 -0.0563535784509 -0.076768942014 -0.1279 -0.0562569738154 -0.0767637613981 -0.12795 -0.056158320125 -0.0767584700952 -0.128 -0.0560615513313 -0.076753066003 -0.12805 -0.0559627081832 -0.0767475470716 -0.1281 -0.0558657132253 -0.0767419111848 -0.12815 -0.0557666156974 -0.0767361562774 -0.1282 -0.0556693266193 -0.076730280225 -0.12825 -0.05556990354 -0.0767242809531 -0.1283 -0.0554722458098 -0.076718156336 -0.12835 -0.0553724190805 -0.0767119042969 -0.1284 -0.0552743108629 -0.0767055227144 -0.12845 -0.0551739946728 -0.0766990095157 -0.1285 -0.0550753459746 -0.0766923625902 -0.12855 -0.0549744458709 -0.076685579875 -0.1286 -0.0548751575304 -0.0766786592763 -0.12865 -0.054773569322 -0.0766715987475 -0.1287 -0.0546735318226 -0.0766643962178 -0.12875 -0.0545711402931 -0.0766570496637 -0.1288 -0.0544702323618 -0.0766495570433 -0.12885 -0.0543669097412 -0.0766419163621 -0.1289 -0.0542649966825 -0.0766341256124 -0.12895 -0.0541606008312 -0.0766261828341 -0.129 -0.0540575325471 -0.076618086059 -0.12905 -0.0539519047961 -0.0766098333668 -0.1291 -0.0538475134266 -0.0766014228349 -0.12915 -0.0537404759952 -0.0765928525881 -0.1292 -0.0536345730893 -0.0765841207535 -0.12925 -0.0535259259832 -0.0765752255056 -0.1293 -0.053418299094 -0.0765661650251 -0.12935 -0.0533078163634 -0.07655693754 -0.1294 -0.0531982249314 -0.0765475412895 -0.12945 -0.0530856501363 -0.0765379745597 -0.1295 -0.0529738204877 -0.076528235651 -0.12955 -0.0528588611744 -0.0765183229105 -0.1296 -0.0527444804099 -0.0765082347019 -0.12965 -0.0526268013381 -0.0764979694361 -0.1297 -0.0525095098202 -0.076487525544 -0.12975 -0.0523887246171 -0.0764769015021 -0.1298 -0.0522681066809 -0.0764660958095 -0.12985 -0.052143767483 -0.0764551070095 -0.1299 -0.0520193398632 -0.0764439336699 -0.12995 -0.0518909243655 -0.0764325744028 -0.13 -0.0517621216773 -0.0764210278458 -0.13005 -0.0516290168215 -0.076409292679 -0.1301 -0.0514951732007 -0.0763973676082 -0.13015 -0.0513566544652 -0.0763852513812 -0.1302 -0.0512169801514 -0.0763729427725 -0.13025 -0.0510721850165 -0.0763604405958 -0.1303 -0.0509257362137 -0.0763477436912 -0.13035 -0.0507736298401 -0.0763348509355 -0.1304 -0.0506192695391 -0.0763217612325 -0.13045 -0.0504585999305 -0.0763084735198 -0.1305 -0.0502949464417 -0.0762949867598 -0.13055 -0.0501241851988 -0.0762812999456 -0.1306 -0.0499495437556 -0.0762674120941 -0.13065 -0.0497668068671 -0.0762533222498 -0.1307 -0.0495790775973 -0.0762390294769 -0.13075 -0.0493820181545 -0.0762245328631 -0.1308 -0.0491785705682 -0.0762098315138 -0.13085 -0.0489642314031 -0.0761949245526 -0.1309 -0.0487417307182 -0.0761798111155 -0.13095 -0.0485063388969 -0.0761644903515 -0.131 -0.0482605018688 -0.0761489614181 -0.13105 -0.0479991773422 -0.0761332234778 -0.1311 -0.0477244230583 -0.0761172756948 -0.13115 -0.0474307581744 -0.076101117232 -0.1312 -0.0471196993066 -0.0760847472459 -0.13125 -0.0467851402001 -0.076068164881 -0.1313 -0.0464278269233 -0.0760513692673 -0.13135 -0.0460407445254 -0.0760343595126 -0.1314 -0.0456235168971 -0.076017134697 -0.13145 -0.0451677814047 -0.0759996938658 -0.1315 -0.0446714887673 -0.0759820360239 -0.13155 -0.0441242332861 -0.0759641601238 -0.1316 -0.0435214104666 -0.0759460650609 -0.13165 -0.0428494475105 -0.0759277496597 -0.1317 -0.0420997469605 -0.0759092126651 -0.13175 -0.0412537253518 -0.0758904527272 -0.1318 -0.0402964275757 -0.0758714683907 -0.13185 -0.0392012351425 -0.0758522580738 -0.1319 -0.0379429984737 -0.0758328200561 -0.13195 -0.0364822765882 -0.0758131524528 -0.132 -0.0347779363901 -0.0757932531951 -0.13205 -0.0327711202116 -0.0757731200007 -0.1321 -0.0303980828422 -0.0757527503465 -0.13215 -0.0275758505713 -0.0757321414279 -0.1322 -0.0242195215066 -0.0757112901245 -0.13225 -0.0202376996198 -0.0756901929439 -0.1323 -0.0155678975437 -0.0756688459728 -0.13235 -0.0102006187642 -0.0756472448028 -0.1324 -0.00424864420429 -0.0756253844556 -0.13245 0.00201326686011 -0.0756032592825 -0.1325 0.00812708108405 -0.0755808628505 -0.13255 0.0135524126687 -0.0755581877951 -0.1326 0.0178183953633 -0.0755352256482 -0.13265 0.0206838077496 -0.0755119666101 -0.1327 0.0221553918035 -0.0754883992773 -0.13275 0.0224256688728 -0.0754645102769 -0.1328 0.0217506774678 -0.0754402838148 -0.13285 0.020385203006 -0.075415701065 -0.1329 0.0185332900587 -0.075390739388 -0.13295 0.0163561868779 -0.0753653712741 -0.133 0.0139654589191 -0.075339562958 -0.13305 0.0114469691491 -0.075313272556 -0.1331 0.00885593185882 -0.0752864476091 -0.13315 0.00623760386178 -0.0752590218226 -0.1332 0.00361829033502 -0.0752309108098 -0.13325 0.00102258369564 -0.0752020065554 -0.1333 -0.00153809597465 -0.0751721703242 -0.13335 -0.00405002557148 -0.0751412236386 -0.1334 -0.0065097800326 -0.0751089369451 -0.13345 -0.00890959487728 -0.0750750154559 -0.1335 -0.0112504946346 -0.0750390816195 -0.13355 -0.0135280946606 -0.0750006534756 -0.1336 -0.0157459990762 -0.0749591180555 -0.13365 -0.0179018718638 -0.0749136987169 -0.1337 -0.0200009865124 -0.0748634150957 -0.13375 -0.0220424787139 -0.0748070339819 -0.1338 -0.0240329743114 -0.0747430090824 -0.13385 -0.0259729554748 -0.0746694070877 -0.1339 -0.0278704012707 -0.0745838169167 -0.13395 -0.0297272008982 -0.074483238218 -0.134 -0.0315527425501 -0.0743639443568 -0.13405 -0.0333503125266 -0.0742213139327 -0.1341 -0.0351305746876 -0.0740496235432 -0.13415 -0.0368978970538 -0.0738417927252 -0.1342 -0.0386636568832 -0.0735890699048 -0.13425 -0.0404324177819 -0.0732806454213 -0.1343 -0.042214961566 -0.0729031743144 -0.13435 -0.0440141948239 -0.0724401870818 -0.1344 -0.0458377779632 -0.0718713608397 -0.13445 -0.0476836567582 -0.07117161531 -0.1345 -0.0495522828112 -0.0703099866771 -0.13455 -0.0514319788066 -0.0692482147636 -0.1346 -0.0533113207121 -0.0679389498592 -0.13465 -0.0551653998777 -0.0663234329016 -0.1347 -0.0569699103384 -0.0643284005688 -0.13475 -0.058690018357 -0.0618617557632 -0.1348 -0.0602973113439 -0.0588060877281 -0.13485 -0.0617609108035 -0.0550081108532 -0.1349 -0.0630647664595 -0.0502598240486 -0.13495 -0.0641967608788 -0.0442623795315 -0.135 -0.0651620371048 -0.0365554935556 -0.13505 -0.0659678045515 -0.0263947495642 -0.1351 -0.0666334946672 -0.0126519346826 -0.13515 -0.0671744519376 0.00564208574 -0.1352 -0.0676126751448 0.0263694697007 -0.13525 -0.0679621121799 0.041422369651 -0.1353 -0.0682410801748 0.0462139192855 -0.13535 -0.0684589609392 0.0464458106338 -0.1354 -0.0686294713387 0.0460039427953 -0.13545 -0.0687578527537 0.0453075184262 -0.1355 -0.0688542826406 0.0444069047655 -0.13555 -0.0689211061606 0.043302001438 -0.1356 -0.0689661485897 0.0420052465031 -0.13565 -0.0689898875621 0.0405158610845 -0.1357 -0.0689986426115 0.0388438098712 -0.13575 -0.0689917008947 0.0370166840829 -0.1358 -0.0689744102971 0.0350553898072 -0.13585 -0.0689452866391 0.032973036371 -0.1359 -0.0689090354061 0.0307884868854 -0.13595 -0.0688636607726 0.0285166674504 -0.136 -0.0688134320385 0.0261744985295 -0.13605 -0.0687560066416 0.0237761340298 -0.1361 -0.0686953506638 0.0213358180543 -0.13615 -0.0686288827584 0.0188656091045 -0.1362 -0.0685603541283 0.016376758985 -0.13625 -0.0684870173218 0.0138787205504 -0.1363 -0.068412468867 0.0113798088567 -0.13635 -0.0683338452532 0.00888686182043 -0.1364 -0.0682546301785 0.00640555029283 -0.13645 -0.0681718791048 0.00394035502113 -0.1365 -0.0680889923891 0.00149470257857 -0.13655 -0.0680029692727 -0.000928923237152 -0.1366 -0.0679171477496 -0.00332893803195 -0.13665 -0.067828488541 -0.00570451309019 -0.1367 -0.0677402823016 -0.00805559569207 -0.13675 -0.0676494639268 -0.0103827997118 -0.1368 -0.0675592875432 -0.0126874973024 -0.13685 -0.0674666713579 -0.0149718028721 -0.1369 -0.0673748407751 -0.0172387735834 -0.13695 -0.0672807039153 -0.0194925520979 -0.137 -0.0671874631115 -0.0217387374463 -0.13705 -0.0670920211713 -0.0239847582471 -0.1371 -0.066997561466 -0.0262404829356 -0.13715 -0.0669009849529 -0.0285188837281 -0.1372 -0.0668054590301 -0.0308369260914 -0.13725 -0.0667078853173 -0.0332165093083 -0.1373 -0.0666114174257 -0.0356855001438 -0.13735 -0.0665129594663 -0.038278534898 -0.1374 -0.0664156528613 -0.041037190033 -0.13745 -0.0663164055404 -0.0440084412541 -0.1375 -0.0662183479111 -0.0472395888833 -0.13755 -0.0661183926894 -0.0507665289325 -0.1376 -0.0660196601354 -0.0545915522029 -0.13765 -0.0659190684517 -0.0586489723945 -0.1377 -0.0658197283877 -0.0627676814498 -0.13775 -0.0657185641415 -0.0666627943597 -0.1378 -0.065618677424 -0.0700045299691 -0.13785 -0.0655169987955 -0.0725631303574 -0.1379 -0.0654166212798 -0.0743173638172 -0.13795 -0.0653144820613 -0.0754190830558 -0.138 -0.0652136657366 -0.0760726567965 -0.13805 -0.0651111162975 -0.0764491561349 -0.1381 -0.0650099101067 -0.0766639998909 -0.13815 -0.0649069980907 -0.0767869460082 -0.1382 -0.0648054485221 -0.0768579603007 -0.13825 -0.0647022193452 -0.0768994596171 -0.1383 -0.0646003708489 -0.0769239780316 -0.13835 -0.0644968680471 -0.0769385753998 -0.1384 -0.0643947633221 -0.0769472761003 -0.13845 -0.0642910287822 -0.0769524105024 -0.1385 -0.0641887089579 -0.0769553478767 -0.13855 -0.064084783059 -0.0769569076576 -0.1386 -0.0639822878043 -0.0769575861488 -0.13865 -0.0638782094998 -0.0769576904537 -0.1387 -0.0637755770825 -0.0769574114908 -0.13875 -0.0636713839427 -0.0769568715018 -0.1388 -0.0635686512611 -0.0769561478767 -0.13885 -0.0634643794971 -0.0769552920764 -0.1389 -0.0633615820971 -0.0769543368151 -0.13895 -0.0632572665709 -0.076953304903 -0.139 -0.0631544386481 -0.0769522105275 -0.13905 -0.0630501128654 -0.0769510642805 -0.1391 -0.0629472872489 -0.0769498722912 -0.13915 -0.0628429833342 -0.0769486396753 -0.1392 -0.0627401914522 -0.0769473689033 -0.13925 -0.0626359401053 -0.0769460625134 -0.1393 -0.0625332119336 -0.0769447212501 -0.13935 -0.0624290423707 -0.0769433463745 -0.1394 -0.0623264063682 -0.0769419377888 -0.13945 -0.062222346254 -0.076940496083 -0.1395 -0.0621198292912 -0.0769390207358 -0.13955 -0.0620159046646 -0.0769375119589 -0.1396 -0.0619135319492 -0.0769359690111 -0.13965 -0.0618097671489 -0.0769343918717 -0.1397 -0.0617075621509 -0.0769327796811 -0.13975 -0.0616039797406 -0.0769311322608 -0.1398 -0.0615019641185 -0.0769294486834 -0.13985 -0.0613985848154 -0.0769277286517 -0.1399 -0.0612967783464 -0.0769259711957 -0.13995 -0.0611936209525 -0.0769241759201 -0.14 -0.0610920414657 -0.0769223418237 -0.14005 -0.060989122803 -0.0769204684244 -0.1401 -0.0608877861169 -0.0769185546942 -0.14015 -0.0607851209668 -0.07691660007 -0.1402 -0.0606840408299 -0.0769146034971 -0.14025 -0.0605816418757 -0.0769125643345 -0.1403 -0.0604808299105 -0.0769104814994 -0.14035 -0.0603787076819 -0.0769083542741 -0.1404 -0.0602781733305 -0.0769061815449 -0.14045 -0.0601763361508 -0.0769039625178 -0.1405 -0.0600760866231 -0.0769016960447 -0.14055 -0.0599745405584 -0.0768993812554 -0.1406 -0.0598745807825 -0.076897016964 -0.14065 -0.0597733295926 -0.0768946022239 -0.1407 -0.0596736621662 -0.0768921358077 -0.14075 -0.0595727072566 -0.0768896166924 -0.1408 -0.0594733323985 -0.0768870436061 -0.14085 -0.0593726727709 -0.076884415449 -0.1409 -0.0592735882711 -0.0768817309017 -0.14095 -0.0591732204729 -0.0768789887878 -0.141 -0.059074421641 -0.0768761877379 -0.14105 -0.058974339713 -0.0768733264991 -0.1411 -0.0588758193249 -0.0768704036501 -0.14115 -0.058776014746 -0.0768674178623 -0.1412 -0.0586777629861 -0.0768643676606 -0.14125 -0.0585782246122 -0.076861251642 -0.1413 -0.0584802290079 -0.0768580682764 -0.14135 -0.0583809430027 -0.0768548160879 -0.1414 -0.0582831883529 -0.0768514934913 -0.14145 -0.0581841381135 -0.0768480989393 -0.1415 -0.0580866064094 -0.0768446307916 -0.14155 -0.0579877724799 -0.076841087432 -0.1416 -0.0578904428101 -0.0768374671658 -0.14165 -0.0577918027795 -0.0768337683108 -0.1417 -0.0576946512231 -0.0768299891196 -0.14175 -0.057596179613 -0.076826127847 -0.1418 -0.0574991791178 -0.0768221826948 -0.14185 -0.0574008472485 -0.0768181518586 -0.1419 -0.0573039674843 -0.0768140334917 -0.14195 -0.0572057433166 -0.0768098257346 -0.142 -0.0571089505079 -0.0768055266953 -0.14205 -0.0570107984646 -0.0768011344638 -0.1421 -0.0569140551965 -0.0767966471064 -0.14215 -0.0568159359494 -0.0767920626672 -0.1422 -0.0567192009344 -0.0767873791749 -0.14225 -0.0566210711548 -0.0767825946331 -0.1423 -0.0565242989686 -0.0767777070375 -0.14235 -0.0564261110414 -0.0767727143574 -0.1424 -0.0563292518091 -0.0767676145602 -0.14245 -0.0562309534903 -0.0767624055863 -0.1425 -0.0561339525178 -0.0767570853806 -0.14255 -0.0560354865414 -0.0767516518607 -0.1426 -0.0559382838919 -0.076746102954 -0.14265 -0.055839587508 -0.0767404365617 -0.1427 -0.0557421174977 -0.0767346505998 -0.14275 -0.0556431219265 -0.076728742959 -0.1428 -0.0555453125392 -0.0767227115499 -0.14285 -0.0554459423409 -0.0767165542603 -0.1429 -0.0553477145435 -0.0767102690011 -0.14295 -0.0552478868726 -0.0767038536634 -0.143 -0.0551491538039 -0.076697306165 -0.14305 -0.0550487775324 -0.0766906244063 -0.1431 -0.0549494435581 -0.076683806318 -0.14315 -0.0548484182508 -0.0766768498164 -0.1432 -0.0547483778474 -0.0766697528505 -0.14325 -0.0546465925468 -0.0766625133592 -0.1433 -0.0545457289803 -0.076655129317 -0.14335 -0.0544430607697 -0.076647598691 -0.1434 -0.0543412445331 -0.0766399194862 -0.14345 -0.0542375568385 -0.076632089704 -0.1435 -0.054134643801 -0.0766241073852 -0.14355 -0.0540297843671 -0.0766159705707 -0.1436 -0.0539256135614 -0.0766076773426 -0.14365 -0.0538194120336 -0.0765992257873 -0.1437 -0.053713803011 -0.0765906140332 -0.14375 -0.0536060680388 -0.0765818402165 -0.1438 -0.0534988176921 -0.0765729025162 -0.14385 -0.0533893334401 -0.076563799122 -0.1439 -0.0532802121697 -0.0765545282678 -0.14395 -0.0531687340997 -0.076545088202 -0.144 -0.053057481164 -0.0765354772168 -0.14405 -0.0529437309024 -0.0765256936223 -0.1441 -0.0528300487483 -0.076515735772 -0.14415 -0.052713707815 -0.0765056020397 -0.1442 -0.0525972551257 -0.0764952908432 -0.14425 -0.0524779572148 -0.0764848006235 -0.1443 -0.0523583403289 -0.0764741298644 -0.14435 -0.0522356617524 -0.0764632770751 -0.1444 -0.0521124240043 -0.0764522408063 -0.14445 -0.0519858717835 -0.0764410196362 -0.1445 -0.0518584801704 -0.0764296121843 -0.14455 -0.0517274770788 -0.0764180170987 -0.1446 -0.0515953054487 -0.0764062330664 -0.14465 -0.0514591710724 -0.076394258804 -0.1447 -0.0513214787487 -0.0763820930659 -0.14475 -0.0511794053124 -0.0763697346376 -0.1448 -0.0510353096803 -0.0763571823386 -0.14485 -0.0508863308838 -0.0763444350197 -0.1449 -0.0507347718878 -0.0763314915633 -0.14495 -0.0505777223559 -0.0763183508837 -0.145 -0.0504174160482 -0.0763050119234 -0.14505 -0.0502508779718 -0.0762914736544 -0.1451 -0.0500802550517 -0.0762777350742 -0.14515 -0.0499024871751 -0.0762637952093 -0.1452 -0.049719610675 -0.0762496531069 -0.14525 -0.0495284525849 -0.0762353078402 -0.1453 -0.0493309062002 -0.0762207584985 -0.14535 -0.0491236475552 -0.0762060041957 -0.1454 -0.048908381956 -0.0761910440551 -0.14545 -0.0486815811781 -0.0761758772201 -0.1455 -0.0484446992449 -0.0761605028383 -0.14555 -0.0481939280728 -0.0761449200729 -0.1456 -0.0479303797469 -0.076129128083 -0.14565 -0.0476498570566 -0.0761131260371 -0.1457 -0.0473529978777 -0.0760969130924 -0.14575 -0.0470350548806 -0.0760804884075 -0.1458 -0.0466959948324 -0.0760638511187 -0.14585 -0.0463302781489 -0.0760470003561 -0.1459 -0.0459369011455 -0.0760299352156 -0.14595 -0.0455091598178 -0.0760126547743 -0.146 -0.0450446148019 -0.0759951580623 -0.14605 -0.0445348128706 -0.0759774440778 -0.1461 -0.0439751399888 -0.0759595117531 -0.14615 -0.0433544551185 -0.0759413599727 -0.1462 -0.0426647722348 -0.0759229875357 -0.14625 -0.0418907297615 -0.0759043931696 -0.1463 -0.0410190037326 -0.0758855754926 -0.14635 -0.0400274912766 -0.0758665330252 -0.1464 -0.0388943113657 -0.0758472641444 -0.14645 -0.037586549282 -0.0758277670968 -0.1465 -0.0360687198559 -0.0758080399453 -0.14655 -0.0342910654483 -0.0757880805758 -0.1466 -0.0321977858286 -0.0757678866401 -0.14665 -0.0297158936245 -0.075747455553 -0.1467 -0.0267656342292 -0.0757267844256 -0.14675 -0.0232549477203 -0.0757058700538 -0.1468 -0.0191014552497 -0.0756847088348 -0.14685 -0.0142477233834 -0.0756632967423 -0.1469 -0.00871422277141 -0.0756416292213 -0.14695 -0.00264706962954 -0.0756197011385 -0.147 0.00362504674352 -0.0755975066474 -0.14705 0.00961450287943 -0.075575039097 -0.1471 0.0147774294736 -0.0755522908495 -0.14715 0.0186958991208 -0.0755292531239 -0.1472 0.0211907256219 -0.0755059157286 -0.14725 0.0223307835884 -0.075482266798 -0.1473 0.0223307002344 -0.0754582923756 -0.14735 0.0214560371083 -0.0754339759578 -0.1474 0.0199462526297 -0.0754092978111 -0.14745 0.0179982828074 -0.0753842341611 -0.1475 0.0157555277858 -0.0753587560253 -0.14755 0.0133260812635 -0.0753328277524 -0.1476 0.0107830176386 -0.0753064049864 -0.14765 0.00818252112125 -0.0752794320562 -0.1477 0.0055604628052 -0.0752518384461 -0.14775 0.00294652393765 -0.07522353427 -0.1478 0.00035761630299 -0.0751944043304 -0.14785 -0.00219029852002 -0.0751643005987 -0.1479 -0.00469033194446 -0.0751330326038 -0.14795 -0.00713393677499 -0.0751003554541 -0.148 -0.00951973765536 -0.0750659548368 -0.14805 -0.0118433370616 -0.0750294285316 -0.1481 -0.0141064973582 -0.0749902635488 -0.14815 -0.0163072531836 -0.0749478081087 -0.1482 -0.0184492916824 -0.0749012371812 -0.14825 -0.0205322632648 -0.0748495103022 -0.1483 -0.0225612765612 -0.0747913197681 -0.14835 -0.0245373364252 -0.0747250271625 -0.1484 -0.0264668868382 -0.0746485853829 -0.14845 -0.0283523094795 -0.0745594429707 -0.1485 -0.030201448931 -0.0744544265032 -0.14855 -0.0320181086701 -0.0743295961101 -0.1486 -0.0338114976569 -0.0741800677286 -0.14865 -0.0355866660951 -0.0739997945071 -0.1487 -0.0373538147971 -0.073781297669 -0.14875 -0.0391186033509 -0.0735153351389 -0.1488 -0.0408912395764 -0.0731904930786 -0.14885 -0.042676555514 -0.0727926820978 -0.1489 -0.0444827522756 -0.0723045148915 -0.14895 -0.0463111152676 -0.0717045360341 -0.149 -0.0481643271621 -0.0709662657094 -0.14905 -0.0500358593562 -0.0700570067351 -0.1491 -0.0519181399504 -0.0689363441425 -0.14915 -0.0537923095654 -0.0675542331306 -0.1492 -0.0556374413912 -0.0658485089626 -0.14925 -0.0574222945126 -0.063741530062 -0.1493 -0.059117237458 -0.0611354088048 -0.14935 -0.0606888552731 -0.0579047250779 -0.1494 -0.062113688759 -0.0538843672093 -0.14945 -0.0633726354238 -0.0488473689144 -0.1495 -0.0644620379285 -0.0424618999831 -0.14955 -0.0653839060719 -0.0342081897947 -0.1496 -0.0661528260563 -0.0232453822295 -0.14965 -0.0667835466725 -0.00837638997681 -0.1497 -0.0672972300987 0.0109855984211 -0.14975 -0.0677100114103 0.0311808432288 -0.1498 -0.0680409019345 0.0435174896342 -0.14985 -0.0683020247287 0.0464480748396 -0.1499 -0.0685077412521 0.0463651629182 -0.14995 -0.0686656721783 0.0458480907799 -0.15 -0.0687861759732 0.0450998547974 -0.15005 -0.0688735125764 0.0441447268748 -0.1501 -0.0689352831908 0.0429911929841 -0.15015 -0.0689735390151 0.0416441837727 -0.1502 -0.0689941059464 0.0401074748414 -0.15025 -0.0689976270931 0.0383904468437 -0.1503 -0.068988790524 0.0365284537686 -0.15035 -0.0689673330636 0.0345340793292 -0.1504 -0.0689371987175 0.032424011899 -0.15045 -0.0688975275413 0.0302154071396 -0.1505 -0.0688517640335 0.0279239589208 -0.15055 -0.0687986459768 0.0255659277875 -0.1506 -0.0687412742705 0.0231553841818 -0.15065 -0.0686781103226 0.0207061951126 -0.1507 -0.0686120139025 0.0182300385748 -0.15075 -0.0685412539736 0.0157378815267 -0.1508 -0.0684685183963 0.0132387215249 -0.15085 -0.0683919410463 0.0107406348241 -0.1509 -0.068314085669 0.00825002462863 -0.15095 -0.0682329909837 0.00577236072448 -0.151 -0.0681511301466 0.00331174688582 -0.15105 -0.0680664748953 0.000871444075892 -0.1511 -0.0679814315706 -0.00154637599116 -0.15115 -0.0678939249838 -0.00394026580967 -0.1512 -0.0678063116465 -0.00630965516475 -0.15125 -0.0677164838048 -0.0086546161961 -0.1513 -0.0676267603428 -0.0109759962341 -0.15135 -0.0675350112684 -0.0132753141657 -0.1514 -0.0674435266375 -0.0155549431262 -0.15145 -0.0673501616703 -0.0178181686459 -0.1515 -0.0672571839551 -0.0200694983846 -0.15155 -0.0671624393178 -0.0223149355448 -0.1516 -0.0670681774952 -0.0245624961662 -0.15165 -0.0669722388223 -0.0268227583532 -0.1517 -0.0668768585405 -0.0291096503103 -0.15175 -0.0667798743345 -0.0314412993347 -0.1518 -0.0666835093967 -0.0338410589377 -0.15185 -0.0665856008229 -0.0363384672558 -0.1519 -0.0664883615433 -0.0389699875274 -0.15195 -0.0663896295693 -0.0417788280573 -0.152 -0.0662916088803 -0.0448127456737 -0.15205 -0.0661921394974 -0.0481175737788 -0.1521 -0.0660934174089 -0.0517231862202 -0.15215 -0.0659932854426 -0.0556180730864 -0.1522 -0.0658939323035 -0.0597126062952 -0.15225 -0.0657932042076 -0.0638048815231 -0.1523 -0.0656932830985 -0.067587972392 -0.15235 -0.0655920190008 -0.0707427039486 -0.1524 -0.06549158748 -0.0730875848155 -0.15245 -0.0653898426732 -0.0746550966346 -0.1525 -0.0652889540515 -0.0756223375554 -0.15255 -0.0651867800813 -0.0761904687378 -0.1526 -0.0650854843489 -0.0765164393799 -0.15265 -0.0649829298042 -0.0767024169135 -0.1527 -0.0648812743024 -0.0768090544048 -0.15275 -0.0647783853811 -0.0768708284657 -0.1528 -0.0646764152761 -0.0769070364436 -0.15285 -0.0645732361816 -0.0769284801282 -0.1529 -0.0644709947941 -0.0769412605495 -0.15295 -0.0643675680054 -0.0769488689613 -0.153 -0.0642650970283 -0.0769533344227 -0.15305 -0.0641614634726 -0.076955855116 -0.1531 -0.0640588031051 -0.0769571498733 -0.15315 -0.0639550022595 -0.0769576571136 -0.1532 -0.0638521912831 -0.0769576477233 -0.15325 -0.0637482612301 -0.076957292265 -0.1533 -0.0636453370481 -0.0769566986722 -0.15335 -0.063541314504 -0.0769559372133 -0.1534 -0.063438313162 -0.0769550529373 -0.15345 -0.0633342334908 -0.0769540763892 -0.1535 -0.0632311896843 -0.0769530269726 -0.15355 -0.0631270868982 -0.0769519186624 -0.1536 -0.063024033964 -0.0769507598501 -0.15365 -0.0629199407049 -0.0769495572607 -0.1537 -0.0628169105937 -0.076948314324 -0.15375 -0.0627128580971 -0.0769470344485 -0.1538 -0.0626098813285 -0.0769457187236 -0.15385 -0.0625058993708 -0.0769443689739 -0.1539 -0.0624030049738 -0.0769429851348 -0.15395 -0.0622991218061 -0.0769415682393 -0.154 -0.0621963372483 -0.076940117628 -0.15405 -0.0620925795238 -0.0769386339159 -0.1541 -0.0619899306374 -0.0769371161221 -0.15415 -0.0618863233362 -0.0769355646248 -0.1542 -0.0617838342427 -0.0769339782598 -0.15425 -0.0616804005966 -0.076932357257 -0.1543 -0.0615780936326 -0.0769307003406 -0.15435 -0.0614748550529 -0.0769290076365 -0.1544 -0.0613727506995 -0.0769272777953 -0.15445 -0.0612697267079 -0.0769255108596 -0.1545 -0.061167843523 -0.0769237054273 -0.15455 -0.0610650516856 -0.0769218614668 -0.1546 -0.06096340624 -0.076919977534 -0.15465 -0.0608608621046 -0.0769180535269 -0.1547 -0.0607594689204 -0.0769160879645 -0.15475 -0.060657185957 -0.0769140806749 -0.1548 -0.0605560574501 -0.0769120301423 -0.15485 -0.0604540469948 -0.0769099361237 -0.1549 -0.0603531934202 -0.0769077970689 -0.15495 -0.060251464622 -0.0769056126617 -0.155 -0.060150894022 -0.0769033813173 -0.15505 -0.060049453792 -0.0769011026436 -0.1551 -0.0599491719461 -0.0768987750197 -0.15515 -0.0598480249077 -0.076896397976 -0.1552 -0.0597480352828 -0.0768939698536 -0.15525 -0.0596471837224 -0.0768914901033 -0.1553 -0.0595474874237 -0.0768889570269 -0.15535 -0.0594469312415 -0.0768863699936 -0.1554 -0.0593475269639 -0.0768837272644 -0.15545 -0.0592472636254 -0.0768810281256 -0.1555 -0.0591481476038 -0.0768782707959 -0.15555 -0.0590481720883 -0.0768754544777 -0.1556 -0.0589493380444 -0.076872577346 -0.15565 -0.0588496427898 -0.0768696385193 -0.1557 -0.0587510818746 -0.076866636128 -0.15575 -0.0586516567182 -0.0768635692063 -0.1558 -0.0585533574509 -0.0768604358398 -0.15585 -0.0584541895656 -0.0768572349793 -0.1559 -0.0583561377658 -0.0768539646652 -0.15595 -0.058257211587 -0.0768506237661 -0.156 -0.0581593902961 -0.0768472102778 -0.15605 -0.0580606874375 -0.0768437229883 -0.1561 -0.0579630768304 -0.0768401598496 -0.15615 -0.057864575992 -0.0768365195711 -0.1562 -0.0577671532777 -0.076832800063 -0.15625 -0.0576688301361 -0.0768289999592 -0.1563 -0.0575715694379 -0.0768251171296 -0.15635 -0.0574733965181 -0.0768211501361 -0.1564 -0.0573762687382 -0.0768170968108 -0.15645 -0.0572782152694 -0.076812955647 -0.1565 -0.0571811879319 -0.0768087244423 -0.15655 -0.0570832196749 -0.0768044016257 -0.1566 -0.0569862567372 -0.0767999849635 -0.15665 -0.0568883357822 -0.0767954728254 -0.1567 -0.0567913974218 -0.0767908629503 -0.15675 -0.0566934819588 -0.0767861536536 -0.1568 -0.0565965243199 -0.0767813426512 -0.15685 -0.0564985683614 -0.0767764282098 -0.1569 -0.0564015432569 -0.0767714080273 -0.15695 -0.0563034963206 -0.0767662803278 -0.157 -0.0562063508907 -0.0767610427959 -0.15705 -0.0561081576273 -0.0767556936192 -0.1571 -0.0560108339334 -0.0767502304745 -0.15715 -0.0559124336857 -0.0767446515192 -0.1572 -0.0558148682373 -0.0767389544274 -0.15725 -0.055716194534 -0.076733137333 -0.1573 -0.0556183177394 -0.0767271979132 -0.15735 -0.0555192976946 -0.0767211342852 -0.1574 -0.0554210332086 -0.0767149441355 -0.15745 -0.0553215868186 -0.0767086255714 -0.1575 -0.0552228507855 -0.0767021762947 -0.15755 -0.0551228901093 -0.0766955944091 -0.1576 -0.0550235902713 -0.0766888776373 -0.15765 -0.0549230184602 -0.0766820240866 -0.1577 -0.0548230531023 -0.0766750315058 -0.15775 -0.054721763257 -0.0766678980123 -0.1578 -0.0546210199709 -0.0766606213876 -0.15785 -0.0545188937974 -0.0766531997659 -0.1579 -0.0544172480154 -0.0766456309667 -0.15795 -0.0543141542278 -0.0766379131469 -0.158 -0.0542114674819 -0.0766300441693 -0.15805 -0.0541072599028 -0.076622022219 -0.1581 -0.0540033777532 -0.076613845207 -0.15815 -0.0538978930539 -0.0766055113528 -0.1582 -0.0537926426179 -0.076597018621 -0.15825 -0.0536856976119 -0.0765883652708 -0.1583 -0.0535788845978 -0.076579549324 -0.15835 -0.0534702729865 -0.0765705690841 -0.1584 -0.0533616781189 -0.0765614226338 -0.15845 -0.0532511665618 -0.0765521083254 -0.1585 -0.0531405412558 -0.0765426243071 -0.15855 -0.0530278646011 -0.076532968984 -0.1586 -0.052914925698 -0.076523140572 -0.15865 -0.0527997811645 -0.0765131375321 -0.1587 -0.0526842044895 -0.0765029581501 -0.15875 -0.0525662445226 -0.076492600946 -0.1588 -0.0524476569549 -0.0764820642784 -0.15885 -0.0523264804096 -0.0764713467284 -0.1589 -0.0522044500574 -0.0764604467279 -0.15895 -0.0520795912322 -0.0764493629197 -0.159 -0.051953615173 -0.0764380938103 -0.15905 -0.0518245300759 -0.0764266381066 -0.1591 -0.0516940189402 -0.0764149943891 -0.15915 -0.0515600679553 -0.0764031614276 -0.1592 -0.0514243263977 -0.0763911378758 -0.15925 -0.051284752225 -0.0763789225666 -0.1593 -0.051142953954 -0.0763665142259 -0.15935 -0.0509968532822 -0.0763539117478 -0.1594 -0.0508480088408 -0.076341113927 -0.15945 -0.0506942956151 -0.0763281197164 -0.1595 -0.0505372103926 -0.0763149279775 -0.15955 -0.0503745676875 -0.0763015377187 -0.1596 -0.0502077865987 -0.0762879478625 -0.15965 -0.0500346028362 -0.0762741574683 -0.1597 -0.0498563365724 -0.0762601655158 -0.15975 -0.0496706199783 -0.0762459711095 -0.1598 -0.0494786454432 -0.0762315732782 -0.15985 -0.0492779077713 -0.0762169711648 -0.1599 -0.0490694318035 -0.0762021638405 -0.15995 -0.0488505280171 -0.0761871504779 -0.16 -0.0486219980573 -0.0761719301793 -0.16005 -0.0483809018246 -0.0761565021375 -0.1601 -0.048127738594 -0.076140865476 -0.16015 -0.0478592225892 -0.0761250193939 -0.1602 -0.0475754359921 -0.0761089630212 -0.16025 -0.0472726082576 -0.0760926955508 -0.1603 -0.0469502350028 -0.0760762161024 -0.16035 -0.0466038533207 -0.0760595238434 -0.1604 -0.0462321166555 -0.0760426178648 -0.16045 -0.0458295532557 -0.0760254972879 -0.1605 -0.0453935804017 -0.0760081611499 -0.16055 -0.0449172242416 -0.0759906085008 -0.1606 -0.0443960450222 -0.0759728382965 -0.16065 -0.0438207811415 -0.0759548494828 -0.1607 -0.0431841368058 -0.0759366408996 -0.16075 -0.0424732869524 -0.0759182113511 -0.1608 -0.0416764455777 -0.0758995595165 -0.16085 -0.0407751276997 -0.0758806840108 -0.1609 -0.0397503706951 -0.0758615832995 -0.16095 -0.0385746053935 -0.0758422557466 -0.161 -0.0372173795542 -0.0758226995358 -0.16105 -0.0356367316642 -0.0758029127033 -0.1611 -0.0337844650733 -0.0757828930617 -0.16115 -0.0315974614622 -0.0757626382201 -0.1612 -0.0290037898209 -0.0757421455042 -0.16125 -0.0259169224259 -0.0757214119617 -0.1613 -0.0222486672351 -0.0757004342783 -0.16135 -0.0179170680326 -0.0756792087596 -0.1614 -0.0128828433726 -0.0756577312397 -0.16145 -0.00719017357054 -0.0756359970328 -0.1615 -0.0010321269124 -0.0756140008228 -0.16155 0.00521952818372 -0.0755917365773 -0.1616 0.0110450866101 -0.0755691973985 -0.16165 0.0159194862738 -0.0755463753809 -0.1617 0.0194761842741 -0.0755232613973 -0.16175 0.021607919072 -0.0754998448623 -0.1618 0.0224289387915 -0.0754761134054 -0.16185 0.0221788710524 -0.0754520524707 -0.1619 0.0211182283098 -0.0754276447863 -0.16195 0.0194795878475 -0.075402869671 -0.162 0.0174426973046 -0.0753777021252 -0.16205 0.0151437791006 -0.0753521116097 -0.1621 0.0126780829416 -0.0753260604408 -0.16215 0.0101164965922 -0.0752995016286 -0.1622 0.00750656166523 -0.0752723760457 -0.16225 0.0048850718583 -0.0752446086656 -0.1623 0.00227528451206 -0.0752161037 -0.16235 -0.000303435679957 -0.0751867382797 -0.1624 -0.00284046451568 -0.0751563544366 -0.16245 -0.00532570849084 -0.0751247489207 -0.1625 -0.00775540107191 -0.0750916604997 -0.16255 -0.0101245745437 -0.0750567541165 -0.1626 -0.0124333126564 -0.0750196013595 -0.16265 -0.0146795860022 -0.0749796563575 -0.1627 -0.0168657538337 -0.0749362262291 -0.16275 -0.0189916233338 -0.0748884347645 -0.1628 -0.0210611007946 -0.0748351779597 -0.16285 -0.0230753957265 -0.0747750694131 -0.1629 -0.0250397518146 -0.0747063734112 -0.16295 -0.0269567290891 -0.0746269227181 -0.163 -0.0288329482469 -0.0745340176978 -0.16305 -0.0306723857291 -0.0744243022789 -0.1631 -0.0324830688949 -0.0742936115685 -0.16315 -0.0342703242032 -0.0741367843521 -0.1632 -0.0360433652553 -0.0739474324824 -0.16325 -0.037808434787 -0.0737176569031 -0.1633 -0.0395752146752 -0.0734376979566 -0.16335 -0.0413497730048 -0.0730955042333 -0.1634 -0.0431406868398 -0.0726762006588 -0.16345 -0.044951665723 -0.072161431083 -0.1635 -0.0467872634225 -0.0715285441803 -0.16355 -0.0486451134243 -0.0707495815898 -0.1636 -0.050521317186 -0.0697900134673 -0.16365 -0.0524026671646 -0.0686071436739 -0.1637 -0.0542725255979 -0.0671480680702 -0.16375 -0.0561043625382 -0.0653469955526 -0.1638 -0.0578698193926 -0.0631215942924 -0.16385 -0.0595351002353 -0.0603677126064 -0.1639 -0.0610717098936 -0.0569511366397 -0.16395 -0.0624542520112 -0.0526935072833 -0.164 -0.0636702913969 -0.0473461348236 -0.16405 -0.0647150091802 -0.0405387954492 -0.1641 -0.0655966933241 -0.031682967389 -0.16415 -0.0663275289009 -0.0198352171445 -0.1642 -0.0669269305907 -0.00378080067718 -0.16425 -0.0674121916644 0.0164267935201 -0.1643 -0.0678030243926 0.0354216141649 -0.16435 -0.0681139519291 0.0449279428122 -0.1644 -0.0683604042563 0.0465144987135 -0.16445 -0.0685522440805 0.0462569648319 -0.1645 -0.0687004980556 0.0456709764767 -0.16455 -0.0688111936959 0.0448711987214 -0.1646 -0.0688921511862 0.0438620120372 -0.16465 -0.0689467972605 0.0426592489302 -0.1647 -0.0689808576694 0.0412617470865 -0.16475 -0.0689960929636 0.0396775507955 -0.1648 -0.068996890686 0.0379203806655 -0.16485 -0.0689839449276 0.0360232359043 -0.1649 -0.0689607764555 0.0339969572476 -0.16495 -0.0689273828203 0.031860056946 -0.165 -0.0688867091316 0.0296283628069 -0.16505 -0.0688382867518 0.0273183542206 -0.1651 -0.0687846687265 0.0249453789864 -0.16515 -0.0687250676492 0.0225236939932 -0.1652 -0.0686617638189 0.0200664728386 -0.16525 -0.0685937483116 0.017585290677 -0.1653 -0.068523108512 0.0150905560642 -0.16535 -0.0684486798763 0.0125910483616 -0.1654 -0.0683724115872 0.0100943876896 -0.16545 -0.0682930290769 0.00760673508037 -0.1655 -0.0682123815039 0.00513319067376 -0.16555 -0.0681291163091 0.00267763505451 -0.1656 -0.0680450096015 0.00024303291922 -0.16565 -0.0679586535667 -0.00216863421459 -0.1657 -0.0678717704906 -0.00455615831393 -0.16575 -0.0677829135547 -0.00691913254281 -0.1658 -0.0676937650033 -0.00925783722022 -0.16585 -0.0676028506866 -0.0115732816876 -0.1659 -0.0675118227324 -0.0138672036806 -0.16595 -0.0674191880691 -0.0161421870148 -0.166 -0.0673265758794 -0.0184018147035 -0.16605 -0.0672324802524 -0.0206509364126 -0.1661 -0.0671385126148 -0.0228960336551 -0.16615 -0.0670431586232 -0.0251457147423 -0.1662 -0.0669480157236 -0.0274113530705 -0.16625 -0.0668515643375 -0.0297078661678 -0.1663 -0.0667553906726 -0.0320546404238 -0.16635 -0.0666579722431 -0.0344765329114 -0.1664 -0.0665608860242 -0.03700482943 -0.16645 -0.0664626083179 -0.0396778035045 -0.1665 -0.06636470833 -0.0425401791552 -0.16655 -0.0662656623847 -0.0456400681373 -0.1666 -0.0661670329927 -0.0490209252024 -0.16665 -0.0660672974034 -0.0527048741811 -0.1667 -0.0659680122214 -0.0566640390758 -0.16675 -0.0658676562778 -0.0607822493265 -0.1668 -0.0657677808491 -0.0648268675828 -0.16685 -0.0656668668267 -0.0684751117448 -0.1669 -0.0655664605849 -0.0714293018851 -0.16695 -0.0654650454241 -0.0735620187182 -0.167 -0.0653641631302 -0.0749544119373 -0.16705 -0.0652622996631 -0.0758002759518 -0.1671 -0.0651609924498 -0.0762930363199 -0.16715 -0.065058730288 -0.0765749560107 -0.1672 -0.0649570464135 -0.0767358829637 -0.16725 -0.0648544325882 -0.0768283701055 -0.1673 -0.0647524179785 -0.0768821084196 -0.16735 -0.0646494973955 -0.0769136981074 -0.1674 -0.0645471960231 -0.0769324464544 -0.16745 -0.0644440117777 -0.0769436270621 -0.1675 -0.0643414659201 -0.0769502688349 -0.16755 -0.0642380595023 -0.0769541398999 -0.1676 -0.0641353099013 -0.0769562880548 -0.16765 -0.0640317213194 -0.0769573452297 -0.1677 -0.0639288072756 -0.0769576975353 -0.16775 -0.0638250751258 -0.0769575853539 -0.1678 -0.0637220345488 -0.0769571596066 -0.16785 -0.0636181960521 -0.0769565171585 -0.1679 -0.0635150654875 -0.0769557201742 -0.16795 -0.0634111565093 -0.0769548097513 -0.168 -0.0633079711522 -0.0769538126369 -0.16805 -0.0632040262086 -0.0769527470433 -0.1681 -0.0631008199017 -0.0769516248387 -0.16815 -0.0629968721481 -0.0769504543524 -0.1682 -0.0628936773606 -0.0769492409005 -0.16825 -0.0627897585615 -0.076947988333 -0.1683 -0.0626866063499 -0.0769466989532 -0.16835 -0.0625827468314 -0.0769453744831 -0.1684 -0.062479666784 -0.0769440157834 -0.16845 -0.0623758953718 -0.0769426235152 -0.1685 -0.0622729155425 -0.0769411978201 -0.16855 -0.0621692594917 -0.0769397388019 -0.1686 -0.0620664063266 -0.0769382462275 -0.16865 -0.0619628912474 -0.0769367198889 -0.1687 -0.0618601895101 -0.0769351593468 -0.16875 -0.061756839293 -0.0769335642051 -0.1688 -0.0616543119907 -0.0769319339022 -0.16885 -0.0615511487327 -0.0769302679178 -0.1689 -0.0614488170426 -0.0769285656093 -0.16895 -0.0613458609757 -0.0769268263661 -0.169 -0.0612437441763 -0.0769250494852 -0.16905 -0.0611410136008 -0.0769232342831 -0.1691 -0.0610391290059 -0.0769213800057 -0.16915 -0.0609366402256 -0.076919485906 -0.1692 -0.0608350031227 -0.0769175511822 -0.16925 -0.0607327703859 -0.0769155750284 -0.1693 -0.0606313939778 -0.076913556595 -0.16935 -0.0605294294201 -0.0769114950192 -0.1694 -0.0604283247694 -0.0769093894025 -0.16945 -0.0603266383589 -0.0769072388252 -0.1695 -0.0602258143342 -0.0769050423378 -0.16955 -0.0601244138195 -0.0769027989632 -0.1696 -0.0600238770446 -0.0769005076984 -0.16965 -0.059922767904 -0.0768981675079 -0.1697 -0.0598225227078 -0.0768957773324 -0.16975 -0.059721708101 -0.0768933360768 -0.1698 -0.0596217564699 -0.0768908426233 -0.16985 -0.0595212371896 -0.0768882958161 -0.1699 -0.0594215787181 -0.0768856944769 -0.16995 -0.0593213531406 -0.0768830373878 -0.17 -0.0592219849816 -0.076880323308 -0.17005 -0.0591220490154 -0.0768775509568 -0.1701 -0.0590229658277 -0.0768747190295 -0.17015 -0.0589233128607 -0.0768718261821 -0.1702 -0.0588245067551 -0.076868871045 -0.17025 -0.0587251275983 -0.0768658522105 -0.1703 -0.0586265880779 -0.0768627682439 -0.17035 -0.0585274709021 -0.0768596176738 -0.1704 -0.0584291847954 -0.0768563990005 -0.17045 -0.0583303150607 -0.0768531106895 -0.1705 -0.0582322664479 -0.0768497511768 -0.17055 -0.0581336268267 -0.076846318866 -0.1706 -0.0580357969576 -0.0768428121298 -0.17065 -0.0579373672446 -0.0768392293112 -0.1707 -0.0578397344399 -0.0768355687216 -0.17075 -0.0577414914468 -0.0768318286459 -0.1708 -0.0576440309881 -0.0768280073365 -0.17085 -0.0575459484269 -0.0768241030224 -0.1709 -0.0574486324291 -0.0768201139 -0.17095 -0.0573506807721 -0.0768160381456 -0.171 -0.0572534780307 -0.0768118739027 -0.17105 -0.0571556243466 -0.0768076192984 -0.1711 -0.0570585001653 -0.0768032724273 -0.17115 -0.0569607079339 -0.0767988313714 -0.1712 -0.0568636239203 -0.0767942941807 -0.17125 -0.0567658528089 -0.0767896588964 -0.1713 -0.0566687666329 -0.0767849235284 -0.17135 -0.0565709722389 -0.0767800860821 -0.1714 -0.0564738373582 -0.076775144533 -0.17145 -0.0563759709101 -0.0767700968559 -0.1715 -0.0562787362419 -0.0767649409974 -0.17155 -0.0561807442426 -0.076759674907 -0.1716 -0.0560833537815 -0.0767542965079 -0.17165 -0.0559851776003 -0.0767488037303 -0.1717 -0.0558875699768 -0.0767431944799 -0.17175 -0.0557891453664 -0.0767374666737 -0.1718 -0.0556912533204 -0.0767316182059 -0.17185 -0.0555925098498 -0.0767256469859 -0.1719 -0.0554942596232 -0.0767195509035 -0.17195 -0.0553951200212 -0.0767133278672 -0.172 -0.0552964306425 -0.0767069757685 -0.17205 -0.055196810019 -0.0767004925211 -0.1721 -0.0550975924586 -0.0766938760245 -0.17215 -0.0549973973922 -0.0766871242039 -0.1722 -0.0548975535775 -0.0766802349728 -0.17225 -0.0547966810458 -0.0766732062739 -0.1723 -0.0546961026948 -0.0766660360409 -0.17235 -0.0545944388056 -0.0766587222409 -0.1724 -0.0544930060478 -0.0766512628343 -0.17245 -0.0543904245381 -0.0766436558177 -0.1725 -0.0542880042829 -0.076635899184 -0.17255 -0.0541843647445 -0.0766279909649 -0.1726 -0.0540808087439 -0.0766199291909 -0.17265 -0.0539759545043 -0.0766117119341 -0.1727 -0.0538710970367 -0.0766033372685 -0.17275 -0.053764852627 -0.0765948033123 -0.1728 -0.0536585077254 -0.0765861081875 -0.17285 -0.0535506758426 -0.0765772500625 -0.1729 -0.0534426339613 -0.0765682271116 -0.17295 -0.053332991806 -0.0765590375571 -0.173 -0.0532230157931 -0.0765496796303 -0.17305 -0.0531113106348 -0.0765401516122 -0.1731 -0.0529991308407 -0.076530451794 -0.17315 -0.0528850746158 -0.0765205785183 -0.1732 -0.0527703829223 -0.0765105301389 -0.17325 -0.0526536456219 -0.0765003050619 -0.1733 -0.0525360881048 -0.0764899017076 -0.17335 -0.0524162896237 -0.0764793185485 -0.1734 -0.0522954574838 -0.0764685540721 -0.17345 -0.052172157513 -0.0764576068182 -0.1735 -0.0520475757944 -0.0764464753424 -0.17355 -0.0519202611998 -0.0764351582535 -0.1736 -0.0517913746427 -0.0764236541765 -0.17365 -0.0516594435827 -0.0764119617889 -0.1737 -0.0515255987522 -0.0764000797836 -0.17375 -0.0513883405254 -0.0763880069061 -0.1738 -0.051248763041 -0.0763757419177 -0.17385 -0.0511053322962 -0.0763632836305 -0.1739 -0.0509590975545 -0.0763506308715 -0.17395 -0.0508084809738 -0.0763377825165 -0.174 -0.0506544761347 -0.0763247374559 -0.17405 -0.0504954489507 -0.0763114946271 -0.1741 -0.0503323230641 -0.0762980529798 -0.17415 -0.0501633916884 -0.0762844115073 -0.1742 -0.0499894895033 -0.0762705692143 -0.17425 -0.0498088149268 -0.0762565251462 -0.1743 -0.0496220879547 -0.0762422783558 -0.17435 -0.049427382145 -0.0762278279328 -0.1744 -0.0492252675656 -0.0762131729716 -0.17445 -0.0490136514158 -0.0761983125992 -0.1745 -0.0487929048008 -0.0761832459417 -0.17455 -0.0485607103653 -0.0761679721526 -0.1746 -0.0483171709279 -0.0761524903806 -0.17465 -0.0480596615943 -0.0761367997947 -0.1747 -0.0477879171399 -0.0761208995517 -0.17475 -0.0474988846146 -0.0761047888222 -0.1748 -0.0471917844617 -0.0760884667576 -0.17485 -0.0468629571851 -0.0760719325126 -0.1749 -0.0465108899811 -0.0760551852138 -0.17495 -0.0461310468544 -0.0760382239817 -0.175 -0.0457208470554 -0.0760210478963 -0.17505 -0.0452744607982 -0.076003656018 -0.1751 -0.0447877162615 -0.075986047355 -0.17515 -0.0442528304569 -0.0759682208791 -0.1752 -0.0436632049981 -0.0759501754927 -0.17525 -0.0430080400399 -0.0759319100441 -0.1753 -0.0422769511196 -0.0759134232905 -0.17535 -0.0414543790135 -0.0758947139111 -0.1754 -0.040523917735 -0.0758757804695 -0.17545 -0.0394623866897 -0.0758566214204 -0.1755 -0.0382437187042 -0.07583723507 -0.17555 -0.0368325487276 -0.075817619579 -0.1756 -0.0351875812644 -0.0757977729162 -0.17565 -0.0332548151127 -0.0757776928562 -0.1757 -0.0309709896952 -0.0757573769275 -0.17575 -0.0282580646727 -0.0757368223981 -0.1758 -0.0250303372522 -0.0757160262174 -0.17585 -0.021197226637 -0.0756949849876 -0.1759 -0.0166863408619 -0.0756736948901 -0.17595 -0.0114725567314 -0.0756521516413 -0.176 -0.00563500915811 -0.0756303503933 -0.17605 0.000590706855479 -0.0756082856645 -0.1761 0.0067849036401 -0.075585951205 -0.17615 0.0124123315976 -0.075563339881 -0.1762 0.0169716262259 -0.0755404434862 -0.17625 0.0201612937831 -0.0755172525494 -0.1763 0.0219364636631 -0.075493756053 -0.17635 0.0224565802412 -0.0754699411109 -0.1764 0.0219724765345 -0.0754457925184 -0.17645 0.0207430676944 -0.0754212922023 -0.1765 0.0189858472274 -0.0753964184617 -0.17655 0.0168707029938 -0.0753711450021 -0.1766 0.0145202504432 -0.0753454396117 -0.17665 0.0120246336254 -0.0753192624401 -0.1767 0.00944600574847 -0.0752925636687 -0.17675 0.00683070957584 -0.0752652804715 -0.1768 0.00420967299916 -0.0752373329833 -0.17685 0.00160696159957 -0.0752086190998 -0.1769 -0.000962515773331 -0.0751790077448 -0.17695 -0.00348634997076 -0.0751483303392 -0.177 -0.00595819810582 -0.0751163700087 -0.17705 -0.00837201223383 -0.0750828481321 -0.1771 -0.0107262023652 -0.0750474076114 -0.17715 -0.0130183109425 -0.0750095922465 -0.1772 -0.0152494878947 -0.0749688213249 -0.17725 -0.0174194246257 -0.0749243584542 -0.1773 -0.0195310139824 -0.0748752732988 -0.17735 -0.0215854508956 -0.0748203946925 -0.1774 -0.0235870012359 -0.0747582531018 -0.17745 -0.0255382007622 -0.0746870100618 -0.1775 -0.0274446664844 -0.0746043715205 -0.17755 -0.0293103275163 -0.0745074814365 -0.1776 -0.0311422146454 -0.0743927909923 -0.17765 -0.0329456606621 -0.0742558978367 -0.1777 -0.0347290093707 -0.0740913483204 -0.17775 -0.0364987282803 -0.0738923941704 -0.1778 -0.0382639742549 -0.073650692876 -0.17785 -0.0400315442414 -0.0733559386117 -0.1779 -0.0418102045702 -0.0729954071473 -0.17795 -0.043605364064 -0.0725533941487 -0.178 -0.0454230356118 -0.0720105206845 -0.17805 -0.04726411711 -0.0713428724924 -0.1781 -0.049127950276 -0.0705209289576 -0.17815 -0.0510063549932 -0.0695082220626 -0.1782 -0.0528872614264 -0.0682596396323 -0.17825 -0.0547494440568 -0.0667192416193 -0.1783 -0.0565676742364 -0.0648173706428 -0.17835 -0.0583098757994 -0.062466659822 -0.1784 -0.0599451618634 -0.0595561588143 -0.17845 -0.0614434713372 -0.0559419531608 -0.1785 -0.0627844714065 -0.0514307584078 -0.17855 -0.0639557080454 -0.0457488714946 -0.1786 -0.0649578862893 -0.0384813133144 -0.17865 -0.0657986370637 -0.0289608866198 -0.1787 -0.0664942701889 -0.0161413923219 -0.17875 -0.0670619401081 0.00112096146173 -0.1788 -0.0675216674533 0.0218193229554 -0.17885 -0.0678899498228 0.038956776383 -0.1789 -0.0681835086062 0.0457857131318 -0.17895 -0.0684143790621 0.0464924301103 -0.179 -0.0685946383668 0.0461253580086 -0.17905 -0.0687320522071 0.0454772487677 -0.1791 -0.0688350191237 0.0446241777207 -0.17915 -0.0689082654296 0.0435625562559 -0.1792 -0.0689577238911 0.0423096023467 -0.17925 -0.0689861500804 0.0408621357891 -0.1793 -0.0689978983548 0.0392304927274 -0.17935 -0.0689944668499 0.0374350375095 -0.1794 -0.0689791954364 0.0355031553778 -0.17945 -0.068952767628 0.0334462105754 -0.1795 -0.0689178564336 0.0312833765936 -0.17955 -0.0688746046277 0.0290297353209 -0.1796 -0.0688252354707 0.0267021617063 -0.17965 -0.0687695243506 0.0243152898366 -0.1797 -0.0687093842796 0.0218833984721 -0.17975 -0.0686443363585 0.0194190611209 -0.1798 -0.0685760757291 0.0169336589187 -0.17985 -0.0685039451326 0.0144371090753 -0.1799 -0.0684294846312 0.0119379068123 -0.17995 -0.0683519107732 0.00944327808286 -0.18 -0.0682726520943 0.00695908593718 -0.18005 -0.068190835418 0.0044901209809 -0.1801 -0.0681078083986 0.00203999064547 -0.18015 -0.0680226339329 -0.000388580148182 -0.1802 -0.0679366005746 -0.00279384546273 -0.18025 -0.0678487256912 -0.00517478656515 -0.1803 -0.0677602543187 -0.00753120195839 -0.18035 -0.0676701714901 -0.00986353924809 -0.1804 -0.067579689924 -0.0121730104887 -0.18045 -0.0674877718185 -0.0144615439989 -0.1805 -0.0673956056598 -0.0167319778022 -0.18055 -0.067302137668 -0.0189881810137 -0.1806 -0.0672085379451 -0.021235396408 -0.18065 -0.0671137417043 -0.0234805937711 -0.1807 -0.0670189049042 -0.0257330376875 -0.18075 -0.0669229553525 -0.0280049311442 -0.1808 -0.0668270379517 -0.0303122598408 -0.18085 -0.0667300757275 -0.0326757231707 -0.1809 -0.0666332047727 -0.035121760081 -0.18095 -0.0665353452381 -0.0376834344226 -0.181 -0.066437626049 -0.0404008097347 -0.18105 -0.0663389658752 -0.0433199232852 -0.1811 -0.0662404876774 -0.0464887261768 -0.18115 -0.0661411096594 -0.049947184885 -0.1812 -0.066041949697 -0.0537077414269 -0.18125 -0.0659419262698 -0.0577234710382 -0.1813 -0.0658421528153 -0.061849500094 -0.18135 -0.0657415486321 -0.0658239386599 -0.1814 -0.0656412231946 -0.0693161683482 -0.18145 -0.0655400970137 -0.0720606742607 -0.1815 -0.0654392759478 -0.0739869316204 -0.18155 -0.0653376820068 -0.0752175752344 -0.1816 -0.0652364176882 -0.0759550949173 -0.18165 -0.0651344067063 -0.0763818945526 -0.1817 -0.0650327483845 -0.0766256353238 -0.18175 -0.0649303682894 -0.0767649233516 -0.1818 -0.064828362704 -0.0768451810018 -0.18185 -0.0647256591485 -0.076891956574 -0.1819 -0.0646233509617 -0.0769195292195 -0.18195 -0.0645203676851 -0.0769359235039 -0.182 -0.0644177997789 -0.0769457000658 -0.18205 -0.0643145788485 -0.0769514900325 -0.1821 -0.0642117925189 -0.0769548343553 -0.18215 -0.0641083744822 -0.0769566512892 -0.1822 -0.0640054095553 -0.0769574956576 -0.18225 -0.0639018335272 -0.0769577089662 -0.1823 -0.0637987284244 -0.0769575035005 -0.18235 -0.0636950321347 -0.0769570140835 -0.1824 -0.0635918239056 -0.0769563265178 -0.18245 -0.0634880437227 -0.076955496999 -0.1825 -0.0633847680629 -0.0769545618659 -0.18255 -0.0632809390046 -0.0769535456811 -0.1826 -0.0631776302589 -0.0769524643846 -0.18265 -0.0630737859879 -0.0769513291302 -0.1827 -0.0629704771374 -0.0769501470254 -0.18275 -0.0628666499391 -0.0769489232542 -0.1828 -0.0627633725685 -0.0769476609248 -0.18285 -0.0626595933092 -0.0769463624347 -0.1829 -0.062556377558 -0.0769450290046 -0.18295 -0.0624526756292 -0.0769436616688 -0.183 -0.062349550129 -0.0769422607206 -0.18305 -0.0622459533784 -0.0769408264924 -0.1831 -0.0621429451806 -0.0769393588028 -0.18315 -0.0620394798389 -0.0769378576009 -0.1832 -0.0619366143401 -0.0769363224502 -0.18325 -0.0618333049453 -0.0769347530749 -0.1833 -0.061730605812 -0.076933148892 -0.18335 -0.0616274751351 -0.0769315094817 -0.1834 -0.0615249642302 -0.0769298341695 -0.18345 -0.0614220332032 -0.0769281224332 -0.1835 -0.0613197305164 -0.0769263735341 -0.18355 -0.0612170181644 -0.0769245868697 -0.1836 -0.0611149417455 -0.07692276165 -0.18365 -0.0610124651216 -0.0769208972038 -0.1837 -0.060910631017 -0.0769189926953 -0.18375 -0.0608084051402 -0.0769170473899 -0.1838 -0.0607068273325 -0.076915060408 -0.18385 -0.0606048651295 -0.0769130309536 -0.1839 -0.060503555481 -0.0769109581028 -0.18395 -0.0604018677303 -0.0769088409989 -0.184 -0.0603008359283 -0.0769066786716 -0.18405 -0.0601994312083 -0.0769044702033 -0.1841 -0.0600986847146 -0.076902214575 -0.18415 -0.0599975693526 -0.0768999108072 -0.1842 -0.0598971133533 -0.0768975578296 -0.18425 -0.0597962913762 -0.0768951545993 -0.1843 -0.059696128732 -0.0768926999928 -0.18435 -0.0595956018172 -0.0768901929026 -0.1844 -0.0594957330151 -0.0768876321494 -0.18445 -0.059395500441 -0.0768850165601 -0.1845 -0.0592959235444 -0.0768823448976 -0.18455 -0.0591959821418 -0.0768796159224 -0.1846 -0.059096692741 -0.0768768283379 -0.18465 -0.0589970368409 -0.0768739808373 -0.1847 -0.0588980279987 -0.0768710720633 -0.18475 -0.0587986493758 -0.076868100642 -0.1848 -0.0586999115688 -0.0768650651546 -0.18485 -0.0586007993808 -0.0768619641596 -0.1849 -0.0585023204372 -0.0768587961768 -0.18495 -0.05840346116 -0.0768555596981 -0.185 -0.0583052261894 -0.0768522531816 -0.18505 -0.0582066035407 -0.0768488750539 -0.1851 -0.0581085948523 -0.0768454237124 -0.18515 -0.0580101897052 -0.0768418975195 -0.1852 -0.0579123867175 -0.0768382948133 -0.18525 -0.0578141770049 -0.0768346138944 -0.1853 -0.0577165561417 -0.0768308530436 -0.18535 -0.057618516742 -0.0768270105025 -0.1854 -0.0575210513079 -0.0768230844968 -0.18545 -0.0574231539121 -0.0768190732119 -0.1855 -0.0573258139527 -0.0768149748217 -0.18555 -0.0572280269146 -0.0768107874589 -0.1856 -0.0571307790518 -0.0768065092489 -0.18565 -0.0570330672074 -0.076802138276 -0.1857 -0.056935874444 -0.076797672621 -0.18575 -0.0568381989027 -0.076793110324 -0.1858 -0.0567410203999 -0.0767884494259 -0.18585 -0.0566433383042 -0.0767836879271 -0.1859 -0.0565461291183 -0.0767788238336 -0.18595 -0.0564483933549 -0.076773855112 -0.186 -0.0563511041267 -0.0767687797384 -0.18605 -0.0562532629976 -0.0767635956512 -0.1861 -0.0561558395978 -0.0767583008018 -0.18615 -0.0560578364312 -0.0767528931063 -0.1862 -0.0559602195353 -0.0767473704972 -0.18625 -0.0558619922273 -0.0767417308742 -0.1863 -0.0557641168262 -0.0767359721571 -0.18635 -0.055665597314 -0.0767300922349 -0.1864 -0.0555673921393 -0.0767240890208 -0.18645 -0.0554685057744 -0.0767179604002 -0.1865 -0.0553698926195 -0.0767117042862 -0.18655 -0.0552705574362 -0.0767053185669 -0.1866 -0.0551714503682 -0.076698801161 -0.18665 -0.0550715762288 -0.0766921499657 -0.1867 -0.0549718806574 -0.0766853629118 -0.18675 -0.0548713682392 -0.0766784379114 -0.1868 -0.0547709798163 -0.0766713729134 -0.18685 -0.0546697194204 -0.0766641658515 -0.1869 -0.0545685227505 -0.0766568146993 -0.18695 -0.0544663928972 -0.076649317418 -0.187 -0.0543642600048 -0.0766416720116 -0.18705 -0.0542611257641 -0.0766338764744 -0.1871 -0.0541579142735 -0.0766259288461 -0.18715 -0.0540536252782 -0.0766178271594 -0.1872 -0.0539491762459 -0.076609569495 -0.18725 -0.0538435643259 -0.0766011539301 -0.1873 -0.0537376996518 -0.0765925785917 -0.18735 -0.0536305759969 -0.076583841606 -0.1874 -0.0535230953133 -0.0765749411504 -0.18745 -0.053414247058 -0.0765658754039 -0.1875 -0.0533049239768 -0.0765566425984 -0.18755 -0.0531941100714 -0.0765472409707 -0.1876 -0.053082687635 -0.0765376688115 -0.18765 -0.0529696338285 -0.0765279244183 -0.1877 -0.0528558189683 -0.0765180061433 -0.18775 -0.0527402116761 -0.076507912347 -0.1878 -0.0526236684184 -0.0764976414457 -0.18785 -0.0525051471862 -0.0764871918666 -0.1879 -0.0523854882774 -0.0764765620924 -0.18795 -0.0522636364597 -0.076465750618 -0.188 -0.0521404129728 -0.0764547559931 -0.18805 -0.0520147461184 -0.0764435767812 -0.1881 -0.0518874344543 -0.0764322116011 -0.18815 -0.0517573857336 -0.0764206590857 -0.1882 -0.0516253712487 -0.0764089179219 -0.18825 -0.051490273026 -0.076396986811 -0.1883 -0.0513528292431 -0.0763848645075 -0.18835 -0.0512118895653 -0.0763725497811 -0.1884 -0.0510681515323 -0.0763600414526 -0.18845 -0.0509204238689 -0.076347338357 -0.1885 -0.0507693536931 -0.0763344393782 -0.18855 -0.0506136975904 -0.0763213434149 -0.1886 -0.0504540394093 -0.0763080494116 -0.18865 -0.0502890687962 -0.0762945563256 -0.1887 -0.050119289261 -0.0762808631569 -0.18875 -0.0499433037356 -0.0762669689173 -0.1888 -0.0497615124296 -0.0762528726578 -0.18885 -0.049572404789 -0.0762385734375 -0.1889 -0.0493762464143 -0.0762240703506 -0.18895 -0.0491713765083 -0.0762093624973 -0.189 -0.0489578827623 -0.0761944490073 -0.18905 -0.0487339029033 -0.0761793290115 -0.1891 -0.0484992858604 -0.0761640016647 -0.18915 -0.0482518952934 -0.0761484661192 -0.1892 -0.0479912543973 -0.076132721543 -0.18925 -0.0477148480637 -0.076116767095 -0.1893 -0.0474217471274 -0.0761006019431 -0.18935 -0.0471089037923 -0.0760842252385 -0.1894 -0.0467747484867 -0.0760676361301 -0.18945 -0.0464154697632 -0.0760508337427 -0.1895 -0.0460285724651 -0.076033817188 -0.18955 -0.0456091273882 -0.0760165855404 -0.1896 -0.0451532716848 -0.0759991378484 -0.18965 -0.0446544033506 -0.0759814731113 -0.1897 -0.0441065912728 -0.075963590284 -0.18975 -0.0435006718503 -0.0759454882557 -0.1898 -0.0428275129358 -0.0759271658527 -0.18985 -0.0420739402408 -0.0759086218131 -0.1899 -0.0412257624132 -0.0758898547874 -0.18995 -0.0402634111029 -0.0758708633135 -0.19 -0.039164588031 -0.0758516458084 -0.19005 -0.0378994657398 -0.0758322005438 -0.1901 -0.0364328198458 -0.0758125256326 -0.19015 -0.0347187442491 -0.0757926189966 -0.1902 -0.0327024770529 -0.0757724783492 -0.19025 -0.0303154273114 -0.0757521011563 -0.1903 -0.0274787108245 -0.0757314846064 -0.19035 -0.0241028090796 -0.0757106255659 -0.1904 -0.0201010508954 -0.075689520532 -0.19045 -0.015407734864 -0.0756681655748 -0.1905 -0.0100205265764 -0.0756465562711 -0.19055 -0.00405242041924 -0.0756246876212 -0.1906 0.00221153524495 -0.0756025539551 -0.19065 0.00831299214099 -0.075580148811 -0.1907 0.0137068258554 -0.0755574647938 -0.19075 0.0179318144738 -0.0755344933956 -0.1908 0.0207506349858 -0.0755112247717 -0.19085 0.0221816436041 -0.0754876474611 -0.1909 0.0224168295787 -0.0754637480226 -0.19095 0.0217173164836 -0.0754395105757 -0.191 0.0203324736248 -0.0754149161871 -0.19105 0.0184691193078 -0.0753899420805 -0.1911 0.0162826456108 -0.0753645605713 -0.19115 0.0138877829327 -0.0753387376683 -0.1912 0.0113651670524 -0.0753124311941 -0.19125 0.00877372769059 -0.075285588306 -0.1913 0.00615393624624 -0.075258142207 -0.19135 0.00353611217846 -0.0752300078542 -0.1914 0.000940289344124 -0.0752010763763 -0.19145 -0.00161795753076 -0.0751712079289 -0.1915 -0.00412934718766 -0.0751402226022 -0.19155 -0.00658623456022 -0.0751078890097 -0.1916 -0.00898523163728 -0.0750739100284 -0.19165 -0.0113231133623 -0.0750379051546 -0.1917 -0.0135998321218 -0.0749993887122 -0.19175 -0.0158147322646 -0.074957743083 -0.1918 -0.0179697901002 -0.0749121858246 -0.19185 -0.0200660210607 -0.0748617293678 -0.1919 -0.0221068577941 -0.0748051315683 -0.19195 -0.0240946768374 -0.0747408350836 -0.192 -0.0260342472384 -0.0746668929521 -0.19205 -0.0279293101009 -0.0745808772514 -0.1921 -0.0297860320637 -0.0744797668624 -0.19215 -0.0316095738519 -0.074359809565 -0.1922 -0.0334074869928 -0.0742163524386 -0.19225 -0.0351862131998 -0.0740436332685 -0.1923 -0.0369543664833 -0.0738345237931 -0.19235 -0.0387190985453 -0.073580213581 -0.1924 -0.0404891880235 -0.0732698204725 -0.19245 -0.0422711724659 -0.0728899101867 -0.1925 -0.0440721232212 -0.0724239031031 -0.19255 -0.0458954142814 -0.0718513404776 -0.1926 -0.0477430802961 -0.07114697417 -0.19265 -0.0496112216688 -0.0702796325355 -0.1927 -0.0514921627829 -0.0692107971687 -0.19275 -0.053370077695 -0.0678927956728 -0.1928 -0.0552240292093 -0.0662664618152 -0.19285 -0.0570253699839 -0.0642580101221 -0.1929 -0.0587433683086 -0.0617746556828 -0.19295 -0.0603455085112 -0.0586980422559 -0.193 -0.0618052772842 -0.054873500177 -0.19305 -0.0631027776846 -0.0500908309108 -0.1931 -0.0642303918479 -0.0440473959726 -0.19315 -0.0651894304997 -0.0362760705087 -0.1932 -0.0659914719675 -0.0260210372118 -0.19325 -0.0666519367028 -0.0121438252722 -0.1933 -0.0671903351676 0.00628941589684 -0.19335 -0.0676245123614 0.0269856612454 -0.1934 -0.0679724749375 0.0417200164929 -0.19345 -0.0682483492 0.0462552808138 -0.1935 -0.0684655541268 0.0464375727384 -0.19355 -0.0686336346059 0.0459860755052 -0.1936 -0.0687618772644 0.0452831641653 -0.19365 -0.0688563178457 0.0443758820106 -0.1937 -0.0689233558247 0.043265005957 -0.19375 -0.0689667009926 0.0419621182737 -0.1938 -0.0689908887008 0.0404669237448 -0.19385 -0.0689981435191 0.038789282752 -0.1939 -0.068991808784 0.0369578198856 -0.19395 -0.0689731538459 0.0349924523704 -0.194 -0.0689447459821 0.0329066265984 -0.19405 -0.0689072260547 0.0307190915632 -0.1941 -0.0688626430783 0.0284447955757 -0.19415 -0.068811214137 0.026100635524 -0.1942 -0.0687546337748 0.0237007148378 -0.19425 -0.0686928273521 0.0212592625856 -0.1943 -0.0686272422239 0.0187882697874 -0.19435 -0.0685575997885 0.0162989687526 -0.1944 -0.0684851724765 0.0138007470119 -0.19445 -0.0684095375486 0.0113018965312 -0.1945 -0.068331842296 0.0088091988585 -0.19455 -0.068251561425 0.00632830115461 -0.1946 -0.0681697519507 0.00386363851998 -0.19465 -0.0680858153278 0.00141861526675 -0.1947 -0.0680007429937 -0.00100432060634 -0.19475 -0.0679138839932 -0.00340360484751 -0.1948 -0.0678261818178 -0.00577843686545 -0.19485 -0.0677369480225 -0.00812878309197 -0.1949 -0.0676470908053 -0.0104552819515 -0.19495 -0.0675558949617 -0.0127593274057 -0.195 -0.0674642425131 -0.0150430609135 -0.19505 -0.0673713992344 -0.0173095709243 -0.1951 -0.0672782275633 -0.0195630396409 -0.19515 -0.0671839798532 -0.0218091179887 -0.1952 -0.0670895037316 -0.0240553008758 -0.19525 -0.0669940421928 -0.0263115444847 -0.1953 -0.0668984315259 -0.0285909316958 -0.19535 -0.0668019083155 -0.0309105701181 -0.1954 -0.0667053000351 -0.0332925302957 -0.19545 -0.0666078390105 -0.0357648841937 -0.1955 -0.0665103457451 -0.0383624882857 -0.19555 -0.0664120498712 -0.0411271282192 -0.1956 -0.0663137662672 -0.044105891273 -0.19565 -0.0662147230158 -0.0473459443698 -0.1957 -0.0661157303578 -0.0508825264135 -0.19575 -0.0660160156637 -0.0547163686082 -0.1958 -0.0659163852592 -0.0587789906116 -0.19585 -0.0658160664128 -0.0628955419108 -0.1959 -0.0657158620646 -0.0667781596736 -0.19595 -0.0656149998263 -0.0700977949758 -0.196 -0.0655142796418 -0.072630215228 -0.19605 -0.0654129297914 -0.0743609708249 -0.1961 -0.0653117475076 -0.075445477865 -0.19615 -0.0652099619741 -0.0760879979181 -0.1962 -0.0651083679186 -0.0764579230866 -0.19625 -0.0650061955963 -0.0766690027272 -0.1963 -0.0649042373802 -0.0767898213674 -0.19635 -0.0648017247162 -0.076859631558 -0.1964 -0.0646994477296 -0.0769004421972 -0.19645 -0.0645966391384 -0.0769245613485 -0.1965 -0.0644940868952 -0.076938923084 -0.19655 -0.0643910250432 -0.0769474825645 -0.1966 -0.0642882394113 -0.0769525305308 -0.19665 -0.0641849653985 -0.0769554142902 -0.1967 -0.0640819867401 -0.0769569399452 -0.19675 -0.0639785402068 -0.0769575965196 -0.1968 -0.063875407459 -0.0769576862362 -0.19685 -0.0637718266454 -0.0769573975445 -0.1969 -0.063668577363 -0.0769568507072 -0.19695 -0.0635648991403 -0.0769561223046 -0.197 -0.0634615695187 -0.076955262889 -0.19705 -0.0633578294052 -0.0769543049586 -0.1971 -0.0632544542905 -0.0769532708441 -0.19715 -0.0631506864543 -0.0769521747305 -0.1972 -0.0630472993364 -0.0769510269198 -0.19725 -0.0629435365789 -0.0769498336109 -0.1973 -0.0628401695659 -0.0769485997243 -0.19735 -0.0627364432872 -0.0769473278183 -0.1974 -0.0626331270618 -0.0769460202891 -0.19745 -0.0625294672084 -0.0769446779666 -0.1975 -0.0624262309687 -0.0769433020039 -0.19755 -0.0623226659693 -0.076941892379 -0.1976 -0.0622195373606 -0.0769404495978 -0.19765 -0.0621160940543 -0.0769389732027 -0.1977 -0.0620130990947 -0.0769374633399 -0.19775 -0.0619098026563 -0.0769359193201 -0.1978 -0.0618069656624 -0.0769343410714 -0.19785 -0.0617038395278 -0.0769327277754 -0.1979 -0.0616011830403 -0.076931079214 -0.19795 -0.0614982488333 -0.0769293944919 -0.198 -0.0613957935453 -0.0769276732816 -0.19805 -0.0612930710071 -0.0769259146372 -0.1981 -0.0611908356953 -0.0769241181409 -0.19815 -0.0610883426183 -0.0769222828089 -0.1982 -0.0609863440788 -0.0769204081429 -0.19825 -0.0608840962434 -0.0769184931266 -0.1983 -0.0607823492301 -0.0769165371859 -0.19835 -0.060680360346 -0.0769145392734 -0.1984 -0.0605788775139 -0.076912498741 -0.19845 -0.0604771591638 -0.0769104145098 -0.1985 -0.0603759510135 -0.0769082858578 -0.19855 -0.0602745125991 -0.0769061116726 -0.1986 -0.060173587424 -0.0769038911582 -0.19865 -0.0600724361142 -0.076901623166 -0.1987 -0.05997179995 -0.0768993068252 -0.19875 -0.0598709406307 -0.0768969409482 -0.1988 -0.0597705972056 -0.0768945245884 -0.19885 -0.0596700324317 -0.0768920565163 -0.1989 -0.0595699831187 -0.0768895357095 -0.19895 -0.0594697130655 -0.0768869608933 -0.199 -0.0593699568332 -0.0768843309686 -0.19905 -0.0592699792465 -0.0768816446136 -0.1991 -0.0591705126086 -0.0768789006522 -0.19915 -0.0590708227531 -0.0768760977128 -0.1992 -0.0589716397154 -0.0768732345425 -0.19925 -0.0588722303208 -0.0768703097181 -0.1993 -0.0587733223266 -0.0768673219106 -0.19935 -0.0586741835304 -0.0768642696437 -0.1994 -0.0585755393986 -0.076861151513 -0.19945 -0.0584766586805 -0.0768579659884 -0.1995 -0.0583782645371 -0.0768547115914 -0.19955 -0.0582796266469 -0.0768513867378 -0.1996 -0.0581814658494 -0.0768479898769 -0.19965 -0.0580830527275 -0.0768445193704 -0.1997 -0.0579851057793 -0.0768409735974 -0.19975 -0.0578868964628 -0.0768373508668 -0.1998 -0.0577891409106 -0.0768336494902 -0.19985 -0.0576911114244 -0.0768298677251 -0.1999 -0.0575935217452 -0.0768260038192 -0.19995 -0.0574956449812 -0.0768220559801 -0.2 -0.0573981924485 -0.0768180223953 -0.20005 -0.0573004380186 -0.0768139012251 -0.2001 -0.0572030905436 -0.076809690601 -0.20015 -0.0571054246107 -0.0768053886391 -0.2002 -0.0570081465636 -0.0768009934191 -0.20025 -0.0569105316484 -0.0767965030166 -0.2003 -0.0568132836451 -0.0767919154648 -0.20035 -0.0567156783919 -0.0767872288026 -0.2004 -0.0566184170427 -0.0767824410217 -0.20045 -0.0565207759538 -0.0767775501291 -0.2005 -0.0564234535781 -0.0767725540812 -0.20055 -0.0563257267006 -0.076767450858 -0.2006 -0.0562282909836 -0.0767622383861 -0.20065 -0.0561304235387 -0.0767569146238 -0.2007 -0.0560328171358 -0.0767514774742 -0.20075 -0.0559347490947 -0.0767459248791 -0.2008 -0.0558369091698 -0.0767402547246 -0.20085 -0.0557385747487 -0.0767344649417 -0.2009 -0.0556404324268 -0.0767285534055 -0.20095 -0.0555417594986 -0.0767225180425 -0.201 -0.0554432392332 -0.0767163567241 -0.20105 -0.0553441486425 -0.076710067378 -0.2011 -0.0552451674692 -0.0767036478786 -0.20115 -0.0551455722193 -0.0766970961607 -0.2012 -0.0550460388759 -0.0766904101078 -0.20125 -0.0549458431798 -0.0766835876683 -0.2013 -0.0548456570788 -0.076676626741 -0.20135 -0.0547447552413 -0.0766695252932 -0.2014 -0.0546438052527 -0.0766622812464 -0.20145 -0.0545420803459 -0.0766548925933 -0.2015 -0.0544402433557 -0.0766473572834 -0.20155 -0.0543375656514 -0.0766396733407 -0.2016 -0.0542347048578 -0.0766318387487 -0.20165 -0.0541309299716 -0.0766238515673 -0.2017 -0.0540268928571 -0.0766157098194 -0.20175 -0.0539218595304 -0.0766074116066 -0.2018 -0.0538164754367 -0.0765989549972 -0.20185 -0.0537100028834 -0.0765903381392 -0.2019 -0.0536030801054 -0.0765815591508 -0.20195 -0.0534949648258 -0.0765726162307 -0.202 -0.0533862871135 -0.0765635075507 -0.20205 -0.053276299049 -0.0765542313644 -0.2021 -0.0531656213753 -0.0765447859021 -0.20215 -0.0530534992435 -0.0765351694762 -0.2022 -0.0529405426563 -0.0765253803786 -0.20225 -0.0528259882649 -0.0765154169828 -0.2023 -0.0527104335952 -0.0765052776449 -0.20235 -0.052593104865 -0.0764949608022 -0.2024 -0.0524745849816 -0.0764844648784 -0.20245 -0.0523540873369 -0.0764737883769 -0.2025 -0.0522321775587 -0.0764629297894 -0.20255 -0.0521080532321 -0.0764518876859 -0.2026 -0.0519822593748 -0.0764406606279 -0.20265 -0.0518539740249 -0.0764292472537 -0.2027 -0.0517237173911 -0.0764176461947 -0.20275 -0.051590643226 -0.0764058561567 -0.2028 -0.0514552415931 -0.0763938758398 -0.20285 -0.0513166359154 -0.076381704017 -0.2029 -0.0511752792631 -0.0763693394573 -0.20295 -0.0510302569444 -0.0763567809988 -0.203 -0.0508819761671 -0.0763440274758 -0.20305 -0.0507294739953 -0.076331077789 -0.2031 -0.0505731001783 -0.0763179308367 -0.20315 -0.0504118302063 -0.0763045855788 -0.2032 -0.0502459410281 -0.0762910409721 -0.20325 -0.0500743288299 -0.0762772960308 -0.2033 -0.0498971772193 -0.0762633497665 -0.20335 -0.049713279193 -0.0762492012427 -0.2034 -0.0495226971562 -0.0762348495178 -0.20345 -0.0493240882924 -0.0762202936971 -0.2035 -0.0491173554782 -0.0762055328798 -0.20355 -0.0489009748763 -0.0761905662048 -0.2036 -0.0486746363048 -0.076175392801 -0.20365 -0.0484365712417 -0.0761600118309 -0.2037 -0.0481861804293 -0.0761444224436 -0.20375 -0.0479213594606 -0.0761286238122 -0.2038 -0.0476411100906 -0.0761126150915 -0.20385 -0.0473428589267 -0.076096395452 -0.2039 -0.0470250467404 -0.0760799640389 -0.20395 -0.0466844329702 -0.0760633200008 -0.204 -0.0463186536677 -0.0760464624545 -0.20405 -0.0459234996894 -0.0760293905076 -0.2041 -0.0454954276028 -0.0760121032238 -0.20415 -0.0450287911093 -0.0759945996441 -0.2042 -0.0445182781962 -0.0759768787533 -0.20425 -0.0439560608298 -0.0759589394936 -0.2043 -0.0433341126353 -0.0759407807357 -0.20435 -0.0426412171691 -0.0759224012877 -0.2044 -0.0418650888602 -0.0759037998631 -0.20445 -0.040989141311 -0.0758849750877 -0.2045 -0.0399942891754 -0.0758659254674 -0.20455 -0.0388553323246 -0.0758466493856 -0.2046 -0.0375422857604 -0.0758271450734 -0.20465 -0.0360162564738 -0.0758074105981 -0.2047 -0.0342303001034 -0.0757874438293 -0.20475 -0.0321251095245 -0.075767242421 -0.2048 -0.0296304339645 -0.0757468037699 -0.20485 -0.0266630644506 -0.0757261249866 -0.2049 -0.0231339735044 -0.0757052028468 -0.20495 -0.0189581407737 -0.0756840337433 -0.205 -0.0140827976454 -0.0756626136263 -0.20505 -0.00852851883052 -0.0756409379316 -0.2051 -0.00244960603676 -0.0756190014974 -0.20515 0.00382247739276 -0.075596798461 -0.2052 0.00979313241358 -0.0755743221355 -0.20525 0.0149227233276 -0.075551564857 -0.2053 0.018796634749 -0.0755285177968 -0.20535 0.0212471510916 -0.0755051707219 -0.2054 0.022346525903 -0.0754815117003 -0.20545 0.0223154061038 -0.0754575267093 -0.2055 0.0214163921815 -0.0754331991477 -0.20555 0.0198907357985 -0.0754085091741 -0.2056 0.0179306968017 -0.0753834328624 -0.20565 0.0156813153978 -0.0753579410493 -0.2057 0.0132465178373 -0.0753319978364 -0.20575 0.0107016303317 -0.0753055585584 -0.2058 0.00809920648515 -0.0752785671278 -0.20585 0.005477759576 -0.0752509524955 -0.2059 0.00286362990385 -0.0752226240678 -0.20595 0.00027656130376 -0.0751934657362 -0.206 -0.0022706807417 -0.0751633282818 -0.20605 -0.00476828555758 -0.0751320197112 -0.2061 -0.00721082519888 -0.0750992931756 -0.20615 -0.00959395880115 -0.0750648318848 -0.2062 -0.0119163639994 -0.0750282304796 -0.20625 -0.0141768181448 -0.0749889720363 -0.2063 -0.0163764051499 -0.0749463998467 -0.20635 -0.0185158216175 -0.0748996827495 -0.2064 -0.0205977522416 -0.0748477726588 -0.20645 -0.0226243183482 -0.0747893524357 -0.2065 -0.0245995509303 -0.0747227719898 -0.20655 -0.0265269142897 -0.0746459698096 -0.2066 -0.0284118103313 -0.074556376655 -0.20665 -0.0302591119721 -0.0744507971908 -0.2067 -0.0320756352134 -0.0743252645428 -0.20675 -0.0338676218351 -0.0741748613934 -0.2068 -0.0356431217698 -0.0739934999342 -0.20685 -0.0374093657624 -0.0737736509585 -0.2069 -0.0391749904724 -0.0735060102815 -0.20695 -0.0409472183219 -0.0731790875643 -0.207 -0.0427338196522 -0.0727786991451 -0.20705 -0.0445399742261 -0.0722873414851 -0.2071 -0.0463698426583 -0.071683415702 -0.20715 -0.0482230248636 -0.0709402646606 -0.2072 -0.0500957836721 -0.0700249714676 -0.20725 -0.0519773969341 -0.0688968478411 -0.2073 -0.0538517365068 -0.0675055067358 -0.20735 -0.0556947278078 -0.0657883500991 -0.2074 -0.0574779261049 -0.0636671774868 -0.20745 -0.0591687245673 -0.0610433582609 -0.2075 -0.0607367425518 -0.057790436339 -0.20755 -0.0621558265976 -0.0537417536413 -0.2076 -0.0634101279126 -0.0486678331825 -0.20765 -0.064493411889 -0.0422324371465 -0.2077 -0.0654109033491 -0.0339078638759 -0.20775 -0.0661744736514 -0.0228408991188 -0.2078 -0.0668018841863 -0.00782889115364 -0.20785 -0.0673114036094 0.0116514893367 -0.2079 -0.0677220338307 0.0317359065257 -0.20795 -0.0680498163199 0.0437254140047 -0.208 -0.0683096977621 0.0464633404479 -0.20805 -0.0685130716158 0.0463532666189 -0.2081 -0.068670387465 0.0458273919051 -0.20815 -0.0687890617451 0.045072866167 -0.2082 -0.0688761966963 0.0441110414569 -0.20825 -0.0689364766869 0.042951506284 -0.2083 -0.0689748039384 0.041598288935 -0.20835 -0.0689941068888 0.0400557549093 -0.2084 -0.068997882873 0.0383334060293 -0.20845 -0.0689879371218 0.0364671775585 -0.2085 -0.0689668600732 0.0344687609219 -0.20855 -0.0689357244868 0.0323553854075 -0.2086 -0.0688965211058 0.030143857981 -0.20865 -0.068849832963 0.0278500950157 -0.2087 -0.0687972442376 0.0254901584734 -0.20875 -0.0687390030567 0.0230782068674 -0.2088 -0.068676412117 0.0206279744321 -0.20885 -0.0686094864367 0.0181511638832 -0.2089 -0.0685393306573 0.0156586452456 -0.20895 -0.0684657954765 0.0131594116177 -0.209 -0.0683898445192 0.0106614657883 -0.20905 -0.0683112116663 0.0081711945709 -0.2091 -0.0682307592508 0.00569401177353 -0.20915 -0.0681481376616 0.00323400138751 -0.2092 -0.0680641359775 0.000794381957614 -0.20925 -0.0679783447254 -0.00162269436843 -0.2093 -0.0678914996953 -0.00401581225007 -0.20935 -0.0678031484319 -0.00638442028829 -0.2094 -0.0677139877392 -0.00872861662109 -0.20945 -0.0676235343019 -0.0110492687508 -0.2095 -0.0675324562273 -0.0133479211095 -0.20955 -0.0674402480771 -0.0156269736483 -0.2096 -0.0673475566921 -0.0178897455996 -0.20965 -0.0672538608221 -0.0201407875535 -0.2097 -0.0671597914226 -0.0223861571616 -0.20975 -0.0670648160091 -0.0246339439345 -0.2098 -0.0669695535523 -0.0268948177836 -0.20985 -0.0668734636548 -0.0291828281942 -0.2099 -0.0667771561452 -0.031516250091 -0.20995 -0.0666800851325 -0.033918621464 -0.21 -0.0665828533704 -0.0364196888139 -0.21005 -0.066484911235 -0.0390561417587 -0.2101 -0.0663868559181 -0.0418713799337 -0.21015 -0.0662881353517 -0.0449132311724 -0.2102 -0.0661893422716 -0.0482272866186 -0.21025 -0.0660899231047 -0.051842568013 -0.2103 -0.0659904669394 -0.0557456927842 -0.21035 -0.0658904193852 -0.0598439075868 -0.2104 -0.0657903664776 -0.0639314992747 -0.21045 -0.0656897535124 -0.0676992236473 -0.2105 -0.0655891639073 -0.0708299538467 -0.21055 -0.0654880430095 -0.0731485891912 -0.2106 -0.0653869719368 -0.0746939109454 -0.21065 -0.0652853963542 -0.0756455271118 -0.2107 -0.0651838953115 -0.0762038640368 -0.21075 -0.0650819149838 -0.0765240845888 -0.2108 -0.0649800325218 -0.0767067854478 -0.21085 -0.0648776947482 -0.0768115731596 -0.2109 -0.0647754770344 -0.0768722968178 -0.21095 -0.0646728269457 -0.0769079030708 -0.211 -0.0645703181585 -0.0769289952236 -0.21105 -0.0644673990445 -0.0769415683779 -0.2111 -0.0643646416412 -0.0769490508448 -0.21115 -0.0642614951664 -0.0769534399613 -0.2112 -0.0641585300546 -0.076955911978 -0.21125 -0.0640551963914 -0.076957176668 -0.2113 -0.0639520630295 -0.0769576634512 -0.21135 -0.0638485809331 -0.0769576413987 -0.2114 -0.0637453173853 -0.0769572764412 -0.21145 -0.0636417242334 -0.0769566771133 -0.2115 -0.0635383671986 -0.0769559106578 -0.21155 -0.0634346990116 -0.0769550235405 -0.2116 -0.0633312838366 -0.076954043943 -0.21165 -0.0632275752849 -0.0769529929393 -0.2117 -0.0631241359641 -0.0769518824597 -0.21175 -0.0630204203589 -0.0769507226133 -0.2118 -0.0629169895163 -0.0769495182668 -0.21185 -0.0628132987825 -0.0769482745348 -0.2119 -0.0627099076347 -0.0769469930992 -0.21195 -0.0626062722644 -0.076945676671 -0.212 -0.0625029505676 -0.0769443254545 -0.21205 -0.0623993995619 -0.0769429409326 -0.2121 -0.0622961755463 -0.0769415226112 -0.21215 -0.0621927363436 -0.0769400713011 -0.2122 -0.0620896366403 -0.0769385861761 -0.21225 -0.0619863350427 -0.0769370676483 -0.2123 -0.0618833846085 -0.0769355147349 -0.21235 -0.0617802447061 -0.0769339275897 -0.2124 -0.0616774667485 -0.0769323051574 -0.21245 -0.0615745108455 -0.0769306474082 -0.2125 -0.0614719267501 -0.0769289532543 -0.21255 -0.0613691752936 -0.0769272225231 -0.2126 -0.0612668045553 -0.076925454112 -0.21265 -0.0611642760685 -0.076923647729 -0.2127 -0.0610621362253 -0.0769218022629 -0.21275 -0.0609598472432 -0.076919917316 -0.2128 -0.0608579538143 -0.0769179917688 -0.21285 -0.0607559188225 -0.0769160251263 -0.2129 -0.0606542852482 -0.076914016258 -0.21295 -0.0605525166252 -0.0769119645767 -0.213 -0.0604511542112 -0.0769098689367 -0.21305 -0.0603496621738 -0.0769077286619 -0.2131 -0.0602485800375 -0.0769055425866 -0.21315 -0.0601473725887 -0.076903309948 -0.2132 -0.060046577609 -0.0769010295552 -0.21325 -0.0599456604884 -0.0768987005602 -0.2133 -0.0598451572555 -0.0768963217421 -0.21335 -0.0597445338893 -0.0768938921685 -0.2134 -0.0596443246558 -0.0768914105842 -0.21345 -0.0595439961081 -0.0768888759732 -0.2135 -0.0594440807399 -0.0768862870421 -0.21355 -0.0593440456632 -0.0768836426916 -0.2136 -0.0592444215901 -0.0768809415866 -0.21365 -0.0591446761764 -0.0768781825454 -0.2137 -0.0590453383413 -0.0768753641879 -0.21375 -0.0589458762684 -0.0768724852512 -0.2138 -0.0588468170724 -0.0768695443075 -0.21385 -0.0587476294467 -0.0768665400138 -0.2139 -0.0586488386886 -0.0768634708931 -0.21395 -0.0585499139836 -0.0768603355234 -0.214 -0.058451378797 -0.0768571323772 -0.21405 -0.0583527027852 -0.0768538599554 -0.2141 -0.058254407565 -0.0768505166795 -0.21415 -0.05815596324 -0.0768471009755 -0.2142 -0.0580578895581 -0.0768436112136 -0.21425 -0.0579596570449 -0.0768400457475 -0.2143 -0.0578617835574 -0.076836402897 -0.21435 -0.0577637400135 -0.0768326809466 -0.2144 -0.0576660423518 -0.076828878167 -0.21445 -0.0575681618476 -0.0768249927769 -0.2145 -0.0574706124891 -0.076821023 -0.21455 -0.0573728658708 -0.0768169669928 -0.2146 -0.0572754339943 -0.0768128229343 -0.21465 -0.0571777887277 -0.0768085889234 -0.2147 -0.0570804400411 -0.0768042630974 -0.21475 -0.0569828600225 -0.0767998435023 -0.2148 -0.0568855565594 -0.076795328237 -0.21485 -0.0567880019006 -0.0767907152998 -0.2149 -0.0566907017901 -0.0767860027554 -0.21495 -0.056593128566 -0.0767811885594 -0.215 -0.0564957857562 -0.0767762707473 -0.21505 -0.056398145705 -0.0767712472382 -0.2151 -0.0563007096421 -0.0767661160428 -0.21515 -0.0562029498234 -0.0767608750498 -0.2152 -0.0561053650809 -0.0767555222504 -0.21525 -0.0560074274692 -0.0767500555091 -0.2153 -0.0559096333055 -0.0767444728028 -0.21535 -0.0558114543145 -0.0767387719781 -0.2154 -0.0557133841643 -0.0767329510036 -0.21545 -0.0556148940972 -0.0767270077143 -0.2155 -0.0555164749715 -0.0767209400764 -0.21555 -0.0554175973677 -0.0767147459208 -0.2156 -0.0553187491468 -0.076708423217 -0.21565 -0.0552194000213 -0.0767019697982 -0.2157 -0.0551200346341 -0.0766953836434 -0.21575 -0.0550201215845 -0.0766886625944 -0.2158 -0.0549201420359 -0.0766818046456 -0.21585 -0.0548195631855 -0.0766748076536 -0.2159 -0.0547188624098 -0.0766676696342 -0.21595 -0.0546175051659 -0.076660388466 -0.216 -0.0545159646793 -0.0766529621921 -0.21605 -0.0544137042651 -0.076645388719 -0.2161 -0.0543111925644 -0.0766376661227 -0.21615 -0.054207890273 -0.0766297923431 -0.2162 -0.0541042609317 -0.076621765494 -0.21625 -0.0539997620486 -0.0766135835546 -0.2163 -0.0538948514483 -0.0766052446821 -0.21635 -0.053788982773 -0.0765967469005 -0.2164 -0.053682607391 -0.0765880884153 -0.21645 -0.0535751742622 -0.0765792672996 -0.2165 -0.053467127407 -0.076570281811 -0.21655 -0.0533579101177 -0.0765611300762 -0.2166 -0.0532479579872 -0.0765518104091 -0.21665 -0.0531367074455 -0.0765423209945 -0.2167 -0.0530245843435 -0.0765326602061 -0.21675 -0.0529110167916 -0.0765228262901 -0.2168 -0.0527964192893 -0.0765128176824 -0.21685 -0.0526802098397 -0.0765026326926 -0.2169 -0.0525627896104 -0.0764922698221 -0.21695 -0.0524435642902 -0.0764817274475 -0.217 -0.0523229192614 -0.0764710041366 -0.21705 -0.0522002451538 -0.076460098334 -0.2171 -0.0520759085011 -0.0764490086748 -0.21715 -0.0519492814402 -0.0764377336728 -0.2172 -0.0518207078051 -0.0764262720321 -0.21725 -0.051689536905 -0.0764146223359 -0.2173 -0.0515560849966 -0.0764027833558 -0.21735 -0.0514196730447 -0.0763907537435 -0.2174 -0.0512805834919 -0.0763785323383 -0.21745 -0.051138101881 -0.0763661178598 -0.2175 -0.0509924687913 -0.0763535092125 -0.21755 -0.0508429251685 -0.0763407051805 -0.2176 -0.0506896592434 -0.0763277047313 -0.21765 -0.0505318553396 -0.076314506712 -0.2177 -0.0503696355306 -0.076301110149 -0.21775 -0.0502021115944 -0.0762875139469 -0.2178 -0.0500293210386 -0.0762737171862 -0.21785 -0.0498502817418 -0.0762597188255 -0.2179 -0.0496649218013 -0.0762455179937 -0.21795 -0.0494721361918 -0.076231113695 -0.218 -0.0492717096069 -0.0762165050995 -0.21805 -0.0490623741294 -0.0762016912511 -0.2181 -0.0488437238529 -0.0761866713518 -0.21815 -0.0486142720088 -0.0761714444742 -0.2182 -0.0483733554798 -0.0761560098428 -0.21825 -0.0481191890015 -0.0761403665484 -0.2183 -0.0478507565968 -0.0761245138242 -0.21835 -0.0475658590878 -0.0761084507651 -0.2184 -0.0472629876789 -0.0760921765998 -0.21845 -0.0469393587227 -0.0760756904107 -0.2185 -0.0465927616703 -0.0760589914025 -0.21855 -0.0462195710667 -0.0760420786269 -0.2186 -0.0458165559606 -0.0760249512438 -0.21865 -0.045378852309 -0.0760076082489 -0.2187 -0.0449017119373 -0.0759900487321 -0.21875 -0.0443784067448 -0.0759722716057 -0.2188 -0.0438018797476 -0.0759542758564 -0.21885 -0.0431625320555 -0.0759360602783 -0.2189 -0.0424497121686 -0.0759176237174 -0.21895 -0.0416493032995 -0.0758989648049 -0.219 -0.0407449463728 -0.075880082198 -0.21905 -0.0397152992601 -0.0758609743121 -0.2191 -0.0385348451235 -0.0758416395533 -0.21915 -0.0371706731428 -0.0758220760531 -0.2192 -0.0355827685538 -0.0758022818894 -0.21925 -0.033720371225 -0.07578225482 -0.2193 -0.0315222026298 -0.0757619924947 -0.21935 -0.0289137244783 -0.0757414921814 -0.2194 -0.025810337763 -0.0757207509671 -0.21945 -0.0221216537346 -0.0756997654759 -0.2195 -0.017768626267 -0.0756785320502 -0.21955 -0.0127116912387 -0.0756570464579 -0.2196 -0.00700094560818 -0.0756353040457 -0.21965 -0.000832711946706 -0.0756132994253 -0.2197 0.00541335551124 -0.0755910265905 -0.21975 0.0112169395441 -0.0755684785624 -0.2198 0.0160534166564 -0.0755456474522 -0.21985 0.0195657605804 -0.0755225240382 -0.2199 0.021652717416 -0.0754990977362 -0.21995 0.0224363173843 -0.0754753560608 -0.22 0.0221560879237 -0.0754512844314 -0.22005 0.0210743481477 -0.0754268654269 -0.2201 0.0194200515561 -0.0754020782976 -0.22015 0.0173735351621 -0.0753768978356 -0.2202 0.0150674978754 -0.0753512933558 -0.22025 0.0125983403738 -0.0753252268625 -0.2203 0.0100340385716 -0.0752986510823 -0.22035 0.00742377607499 -0.0752715063934 -0.2204 0.00480180492124 -0.0752437172462 -0.22045 0.00219327709895 -0.0752151870459 -0.2205 -0.000384799862115 -0.0751857919976 -0.22055 -0.00291978642781 -0.0751553728133 -0.2206 -0.00540385213807 -0.0751237246685 -0.22065 -0.0078311560053 -0.075090584199 -0.2207 -0.0101989417131 -0.0750556137639 -0.22075 -0.0125051896766 -0.0750183815718 -0.2208 -0.0147500524336 -0.0749783376312 -0.22085 -0.0169337736771 -0.0749347837939 -0.2209 -0.0190583263955 -0.0748868374144 -0.22095 -0.0211254996216 -0.0748333863828 -0.221 -0.0231386606928 -0.0747730343791 -0.22105 -0.0251009402823 -0.0747040333118 -0.2211 -0.0270170520863 -0.0746242007828 -0.22115 -0.0288915099235 -0.0745308183381 -0.2212 -0.0307304396414 -0.0744205068306 -0.22125 -0.0325397657788 -0.0742890728222 -0.2213 -0.0343269557533 -0.0741313200585 -0.22135 -0.0360991186244 -0.0739408171264 -0.2214 -0.0378646219557 -0.0737096118074 -0.22145 -0.0396310308405 -0.073427878856 -0.2215 -0.0414065085998 -0.0730834861814 -0.22155 -0.0431974858841 -0.0726614591625 -0.2216 -0.0450097163627 -0.0721433189967 -0.22165 -0.0468455531832 -0.0715062628177 -0.2217 -0.0487045976631 -0.0707221449687 -0.22175 -0.0505806780781 -0.0697562032256 -0.2218 -0.0524624783791 -0.0685654520854 -0.22185 -0.0543310491109 -0.0670966241102 -0.2219 -0.0561617597123 -0.065283466536 -0.22195 -0.0579240403398 -0.0630430481184 -0.222 -0.0595861781641 -0.0602704120176 -0.22205 -0.0611177306719 -0.0568302039887 -0.2221 -0.0624956492601 -0.052542327203 -0.22215 -0.0637057577153 -0.047155207516 -0.2222 -0.0647456537236 -0.0402934849957 -0.22225 -0.0656218236657 -0.0313595138246 -0.2223 -0.0663487002889 -0.0193970808552 -0.22235 -0.0669437034099 -0.00319449289455 -0.2224 -0.0674261933208 0.0170953435224 -0.22245 -0.067813767744 0.0358960761904 -0.2225 -0.0681229422934 0.0450600813367 -0.22255 -0.0683670104242 0.046515317304 -0.2226 -0.0685578231708 0.04624195737 -0.22265 -0.06870429012 0.0456479516679 -0.2227 -0.0688144422213 0.0448417408509 -0.22275 -0.0688940072458 0.0438260066799 -0.2228 -0.068948428334 0.0426171256089 -0.22285 -0.0689813582917 0.0412134415026 -0.2229 -0.0689965812358 0.0396234017307 -0.22295 -0.0689964258608 0.0378614580843 -0.223 -0.0689836124919 0.0359600030236 -0.22305 -0.0689596135235 0.0339298933285 -0.2231 -0.0689264525991 0.0317897488805 -0.22315 -0.06888503474 0.0295552990765 -0.2232 -0.0688369155944 0.0272430739001 -0.22325 -0.0687826150994 0.0248683379861 -0.2233 -0.0687233673366 0.0224453468964 -0.22335 -0.0686594256814 0.0199872059831 -0.2234 -0.0685917992946 0.0175054624182 -0.22345 -0.0685205543204 0.0150104680892 -0.2235 -0.0684465405158 0.012510964676 -0.22355 -0.0683696911764 0.0100145255602 -0.2236 -0.068290742003 0.00752727380506 -0.22365 -0.0682095313969 0.0050542716727 -0.2237 -0.0681267128713 0.00259936600128 -0.22375 -0.0680420567505 0.000165491205095 -0.2238 -0.0679561569856 -0.00224539958521 -0.22385 -0.0678687349361 -0.00463212284891 -0.2239 -0.0677803411686 -0.00699429592661 -0.22395 -0.0676906617768 -0.00933222102691 -0.224 -0.0676002155653 -0.0116469308588 -0.22405 -0.0675086632253 -0.0139401875465 -0.2241 -0.0674165001765 -0.0162146042367 -0.22415 -0.0673233688301 -0.0184737994949 -0.2242 -0.0672297472847 -0.0207226685213 -0.22425 -0.0671352648233 -0.0229677522899 -0.2243 -0.0670403866182 -0.0252177363764 -0.22435 -0.066944732569 -0.0274840944785 -0.2244 -0.066848758115 -0.0297818708673 -0.22445 -0.0667520764906 -0.0321306106663 -0.2245 -0.0666551357278 -0.0345553612348 -0.22455 -0.0665575443804 -0.0370876257338 -0.2246 -0.0664597447721 -0.0397658995287 -0.22465 -0.0663613422209 -0.0426350800669 -0.2247 -0.0662627745809 -0.0457432899016 -0.22475 -0.0661636449922 -0.0491336179593 -0.2248 -0.0660643877486 -0.0528271066579 -0.22485 -0.0659646045868 -0.0567936837343 -0.2249 -0.0658647269049 -0.0609137560365 -0.22495 -0.0657643556002 -0.0649509783124 -0.225 -0.0656639196623 -0.0685811384853 -0.22505 -0.0655630195621 -0.0715099504114 -0.2251 -0.0654620822375 -0.0736169005684 -0.22515 -0.0653607080345 -0.0749886611375 -0.2252 -0.0652593221006 -0.075820509334 -0.22525 -0.0651575248742 -0.0763046684877 -0.2253 -0.0650557399001 -0.0765815905218 -0.22535 -0.0649535678655 -0.0767396814392 -0.2254 -0.0648514308483 -0.0768305662266 -0.22545 -0.0647489298952 -0.076883393309 -0.2255 -0.0646464857128 -0.0769144581218 -0.22555 -0.0645436997825 -0.0769328994289 -0.2256 -0.0644409915056 -0.0769438972727 -0.22565 -0.0643379628472 -0.0769504283628 -0.2257 -0.0642350319442 -0.0769542311427 -0.22575 -0.0641318012737 -0.0769563364212 -0.2258 -0.0640286877329 -0.0769573661352 -0.22585 -0.0639252943257 -0.0769577005164 -0.2259 -0.0638220367241 -0.0769575763666 -0.22595 -0.0637185184657 -0.0769571424426 -0.226 -0.0636151540055 -0.076956494251 -0.22605 -0.0635115474174 -0.0769556931084 -0.2261 -0.0634081119449 -0.0769547795725 -0.22615 -0.0633044521981 -0.0769537800341 -0.2262 -0.0632009802104 -0.0769527124858 -0.22625 -0.0630973011233 -0.0769515886322 -0.2263 -0.0629938257566 -0.0769504167154 -0.22635 -0.0628901597737 -0.0769492019668 -0.2264 -0.0627867127728 -0.0769479482066 -0.22645 -0.0626830909253 -0.0769466576871 -0.2265 -0.0625797025958 -0.0769453321269 -0.22655 -0.0624761544459 -0.0769439723508 -0.2266 -0.0623728535917 -0.0769425790283 -0.22665 -0.0622694071659 -0.0769411522727 -0.2267 -0.0621662210194 -0.0769396922014 -0.22675 -0.0620629027351 -0.0769381985571 -0.2268 -0.0619598568823 -0.0769366711477 -0.22685 -0.0618566914733 -0.0769351095123 -0.2269 -0.061753809779 -0.076933513271 -0.22695 -0.0616508202212 -0.0769318818427 -0.227 -0.061548124756 -0.0769302147227 -0.22705 -0.0614453321947 -0.0769285112508 -0.2271 -0.0613428431632 -0.0769267708309 -0.22715 -0.0612402668439 -0.0769249927441 -0.2272 -0.0611380025176 -0.0769231763201 -0.22725 -0.06103565972 -0.0769213207906 -0.2273 -0.0609336363735 -0.0769194254204 -0.22735 -0.0608315423499 -0.0769174893948 -0.2274 -0.0607297742007 -0.0769155119182 -0.22745 -0.060627942118 -0.07691349213 -0.2275 -0.06052644127 -0.076911429176 -0.22755 -0.0604248821538 -0.0769093221481 -0.2276 -0.0603236585429 -0.0769071701339 -0.22765 -0.0602223812244 -0.0769049721753 -0.2277 -0.060121442566 -0.0769027273016 -0.22775 -0.0600204536306 -0.0769004345022 -0.2278 -0.0599198053694 -0.0768980927468 -0.22785 -0.0598191091068 -0.0768957009695 -0.2279 -0.0597187543677 -0.0768932580795 -0.22795 -0.0596183527241 -0.0768907629533 -0.228 -0.0595182922642 -0.0768882144385 -0.22805 -0.0594181847936 -0.0768856113518 -0.2281 -0.0593184169528 -0.0768829524779 -0.22815 -0.0592186007666 -0.0768802365717 -0.2282 -0.0591191214165 -0.0768774623547 -0.22825 -0.0590195911312 -0.0768746285182 -0.2283 -0.0589203936216 -0.0768717337198 -0.22835 -0.0588211413046 -0.0768687765866 -0.2284 -0.0587222164074 -0.0768657557119 -0.22845 -0.0586232315176 -0.0768626696581 -0.2285 -0.0585245673639 -0.0768595169546 -0.22855 -0.0584258366847 -0.0768562960989 -0.2286 -0.0583274186933 -0.0768530055572 -0.22865 -0.0582289262583 -0.076849643763 -0.2287 -0.0581307370589 -0.0768462091203 -0.22875 -0.0580324640698 -0.0768426999994 -0.2288 -0.0579344834131 -0.0768391147438 -0.22885 -0.0578364081415 -0.0768354516626 -0.2289 -0.0577386127936 -0.0768317090409 -0.22895 -0.057640710469 -0.0768278851292 -0.229 -0.0575430740936 -0.0768239781568 -0.22905 -0.0574453167776 -0.0768199863179 -0.2291 -0.0573478097969 -0.0768159077893 -0.22915 -0.0572501662291 -0.0768117407124 -0.2292 -0.0571527556589 -0.076807483215 -0.22925 -0.0570551910832 -0.0768031333894 -0.2293 -0.0569578403467 -0.0767986893185 -0.22935 -0.0568603163083 -0.07679414905 -0.2294 -0.0567629850131 -0.0767895106261 -0.22945 -0.0566654591153 -0.0767847720546 -0.2295 -0.0565681027939 -0.0767799313419 -0.22955 -0.0564705284227 -0.0767749864614 -0.2296 -0.0563730982338 -0.0767699353891 -0.22965 -0.0562754242295 -0.0767647760694 -0.2297 -0.0561778666007 -0.0767595064533 -0.22975 -0.0560800368741 -0.0767541244619 -0.2298 -0.0559822930913 -0.0767486280269 -0.22985 -0.0558842461815 -0.0767430150521 -0.2299 -0.0557862519066 -0.0767372834559 -0.22995 -0.0556879204539 -0.0767314311307 -0.23 -0.0555896051553 -0.0767254559877 -0.23005 -0.0554909152905 -0.0767193559146 -0.2301 -0.0553922015842 -0.0767131288222 -0.23015 -0.055293072213 -0.0767067725998 -0.2302 -0.0551938750841 -0.0767002851636 -0.23025 -0.05509421704 -0.0766936644107 -0.2303 -0.0549944429257 -0.0766869082691 -0.23035 -0.0548941579809 -0.0766800146501 -0.2304 -0.0547937036989 -0.0766729814992 -0.23045 -0.0546926833974 -0.076665806748 -0.2305 -0.054591434874 -0.0766584883665 -0.23055 -0.0544895591476 -0.0766510243131 -0.2306 -0.054387389913 -0.0766434125874 -0.23065 -0.0542845254445 -0.0766356511804 -0.2307 -0.0541812948517 -0.0766277381269 -0.23075 -0.0540772931329 -0.0766196714553 -0.2308 -0.0539728442347 -0.0766114492412 -0.23085 -0.0538675392442 -0.0766030695567 -0.2309 -0.0537616962532 -0.0765945305233 -0.23095 -0.0536549016761 -0.0765858302612 -0.231 -0.0535474669178 -0.0765769669423 -0.23105 -0.0534389728027 -0.076567938739 -0.2311 -0.0533297230426 -0.0765587438774 -0.23115 -0.0532192917612 -0.0765493805868 -0.2312 -0.0531079737557 -0.0765398471519 -0.23125 -0.0529953350966 -0.0765301418623 -0.2313 -0.0528816601755 -0.0765202630641 -0.23135 -0.0527665053542 -0.0765102091096 -0.2314 -0.0526501427843 -0.0764999784086 -0.23145 -0.0525321170809 -0.0764895693797 -0.2315 -0.0524126858894 -0.0764789804991 -0.23155 -0.0522913795485 -0.0764682102528 -0.2316 -0.0521684383798 -0.0764572571844 -0.23165 -0.0520433752898 -0.0764461198477 -0.2317 -0.0519164097399 -0.0764347968555 -0.23175 -0.0517870332339 -0.0764232868312 -0.2318 -0.0516554399089 -0.0764115884558 -0.23185 -0.0515210948264 -0.076399700421 -0.2319 -0.0513841611107 -0.0763876214757 -0.23195 -0.0512440709361 -0.0763753503798 -0.232 -0.0511009491011 -0.0763628859489 -0.23205 -0.0509541865703 -0.0763502270086 -0.2321 -0.0508038603202 -0.0763373724381 -0.23215 -0.0506493092441 -0.0763243211265 -0.2322 -0.0504905500448 -0.0763110720143 -0.23225 -0.0503268552152 -0.0762976240499 -0.2323 -0.0501581646633 -0.0762839762297 -0.23235 -0.0499836653601 -0.076270127557 -0.2324 -0.049803198224 -0.0762560770802 -0.23245 -0.0496158388508 -0.0762418238507 -0.2325 -0.0494212989632 -0.0762273669607 -0.23255 -0.0492185073509 -0.0762127055034 -0.2326 -0.0490070048238 -0.0761978386081 -0.23265 -0.0487855240649 -0.0761827653996 -0.2327 -0.048553376464 -0.0761674850335 -0.23275 -0.0483090288733 -0.076151996657 -0.2328 -0.048051479807 -0.0761362994409 -0.23285 -0.0477788299291 -0.0761203925404 -0.2329 -0.047489643637 -0.0761042751276 -0.23295 -0.0471815082 -0.0760879463522 -0.233 -0.0468523742617 -0.0760714053697 -0.23305 -0.0464990953388 -0.0760546513051 -0.2331 -0.0461187365513 -0.0760376832792 -0.23315 -0.0457070806411 -0.07602050037 -0.2332 -0.0452598869618 -0.0760031016379 -0.23325 -0.0447713405332 -0.0759854860886 -0.2333 -0.0442352306219 -0.0759676526932 -0.23335 -0.043643302667 -0.0759496003511 -0.2334 -0.0429863039547 -0.0759313279094 -0.23345 -0.0422521701426 -0.0759128341217 -0.2335 -0.0414268502098 -0.0758941176648 -0.23355 -0.0404922168918 -0.0758751770982 -0.2336 -0.0394265366099 -0.075856010873 -0.23365 -0.0382019523469 -0.0758366172903 -0.2337 -0.036784453687 -0.0758169945061 -0.23375 -0.0351308552724 -0.0757971404823 -0.2338 -0.0331883962921 -0.0757770529872 -0.23385 -0.0308918363006 -0.0757567295406 -0.2339 -0.0281643482858 -0.0757361674021 -0.23395 -0.0249184078792 -0.0757153635101 -0.234 -0.0210651690028 -0.0756943144547 -0.23405 -0.016531613647 -0.0756730164034 -0.2341 -0.0112965423134 -0.0756514650561 -0.23415 -0.00544171920101 -0.0756296555463 -0.2342 0.00078994493583 -0.07560758237 -0.23425 0.00697506420843 -0.0755852392513 -0.2343 0.012575259128 -0.0755626190254 -0.23435 0.0170948169049 -0.0755397134493 -0.2344 0.0202386405748 -0.0755165130072 -0.23445 0.0219711982609 -0.0754930066279 -0.2345 0.0224550366099 -0.0754691813591 -0.23455 0.0219438652439 -0.0754450219147 -0.2346 0.0206942634959 -0.0754205101189 -0.23465 0.0189237419334 -0.075395624142 -0.2347 0.0167990813394 -0.0753703375237 -0.23475 0.0144431907725 -0.0753446178398 -0.2348 0.011943714611 -0.0753184249624 -0.23485 0.00936368130565 -0.0752917087126 -0.2349 0.00674739886137 -0.075264405791 -0.23495 0.00412700156187 -0.0752364357157 -0.235 0.00152475851066 -0.0752076955751 -0.23505 -0.001043054944 -0.0751780532471 -0.2351 -0.00356570780403 -0.0751473387994 -0.23515 -0.00603541239813 -0.0751153336242 -0.2352 -0.00844773650133 -0.0750817568875 -0.23525 -0.010799605804 -0.075046248691 -0.2353 -0.0130901437334 -0.0750083493051 -0.23535 -0.0153189969814 -0.0749674735967 -0.2354 -0.0174874190445 -0.0749228796541 -0.23545 -0.0195967930564 -0.0748736302806 -0.2355 -0.0216498667699 -0.0748185457982 -0.23555 -0.0236493976274 -0.0747561461417 -0.2356 -0.025599470559 -0.0746845798303 -0.23565 -0.0275041985552 -0.0746015367517 -0.2357 -0.0293690577107 -0.0745041410571 -0.23575 -0.031199578497 -0.0743888195233 -0.2358 -0.033002635805 -0.0742511397314 -0.23585 -0.034785072367 -0.074085611006 -0.2359 -0.0365548863936 -0.0738854394757 -0.23595 -0.0383197246774 -0.0736422264818 -0.236 -0.0400878926333 -0.0733455970419 -0.23605 -0.0418666228836 -0.0729827417298 -0.2361 -0.0436627919551 -0.0725378511942 -0.23615 -0.0454808329321 -0.0719914169654 -0.2362 -0.0473230453269 -0.0713193647893 -0.23625 -0.0491871208021 -0.0704919760788 -0.2363 -0.0510662001048 -0.0694725370701 -0.23635 -0.0529465003523 -0.0682156289791 -0.2364 -0.0548080814301 -0.0666649258998 -0.23645 -0.0566240369777 -0.0647502778115 -0.2365 -0.0583636923978 -0.0623836735865 -0.23655 -0.0599946971366 -0.0594532872387 -0.2366 -0.0614886569874 -0.0558139429219 -0.23665 -0.062824038181 -0.0512703920159 -0.2367 -0.0639902229358 -0.045545601387 -0.23675 -0.0649867553135 -0.038218604208 -0.2368 -0.0658230027998 -0.0286118407047 -0.23685 -0.0665139383486 -0.0156669291133 -0.2369 -0.0670782528519 0.00174276941676 -0.23695 -0.0675344691785 0.0224701158673 -0.237 -0.0679005081769 0.0393383806748 -0.23705 -0.0681915395669 0.0458606404547 -0.2371 -0.0684210002966 0.0464864036989 -0.23715 -0.0685994245835 0.0461079754904 -0.2372 -0.0687359931949 0.0454527669105 -0.23725 -0.0688375852441 0.0445929885771 -0.2373 -0.0689103582986 0.0435251027916 -0.23735 -0.0689587459693 0.0422659334342 -0.2374 -0.0689869457568 0.0408124226804 -0.23745 -0.0689978273589 0.0391749956214 -0.2375 -0.0689943363645 0.0373749496447 -0.23755 -0.0689783382012 0.0354388675292 -0.2376 -0.0689519659746 0.0333782487515 -0.23765 -0.068916425818 0.0312123119355 -0.2377 -0.0688733102071 0.028956051747 -0.23775 -0.0688233815182 0.0266263989381 -0.2378 -0.0687678637482 0.0242378816667 -0.23785 -0.0687072140699 0.0218048018421 -0.2379 -0.0686424003721 0.0193396367125 -0.23795 -0.0685736664132 0.0168537655852 -0.238 -0.0685017994472 0.0143570249436 -0.23805 -0.0684268922287 0.0118578944244 -0.2381 -0.0683496032495 0.00936353526944 -0.23815 -0.0682699175602 0.00687978933216 -0.2382 -0.0681884011641 0.004411396902 -0.23825 -0.0681049618774 0.0019619435252 -0.2383 -0.0680200988815 -0.000465884100302 -0.23835 -0.067933664415 -0.00287036073092 -0.2384 -0.0678461091456 -0.00525049692164 -0.23845 -0.0677572452272 -0.00760611090141 -0.2385 -0.0676674879474 -0.00993767488159 -0.23855 -0.0675766205104 -0.0122464228916 -0.2386 -0.0674850322813 -0.0145343093326 -0.23865 -0.0673924855511 -0.0168042026133 -0.2387 -0.0672993505921 -0.0190600092381 -0.23875 -0.0672053745917 -0.0213070213017 -0.2388 -0.0671109136827 -0.0235522708946 -0.23885 -0.0670157041621 -0.0258051063737 -0.2389 -0.0669200916139 -0.0280778356789 -0.23895 -0.0668238045076 -0.0303865802297 -0.239 -0.0667271804964 -0.0327522040726 -0.23905 -0.0666299424512 -0.0352013457509 -0.2391 -0.0665324219995 -0.0377672874948 -0.23915 -0.066434338039 -0.0404903102872 -0.2392 -0.0663360175661 -0.0434165940155 -0.23925 -0.0662371766953 -0.0465940300865 -0.2393 -0.0661381388093 -0.0500620711773 -0.23935 -0.0660386181075 -0.0538318314028 -0.2394 -0.0659389351043 -0.0578538642071 -0.23945 -0.0658388027197 -0.0619796606035 -0.2395 -0.0657385391474 -0.0659439255498 -0.23955 -0.0656378564937 -0.0694157095919 -0.2396 -0.0655370710314 -0.072134125975 -0.23965 -0.0654358943905 -0.07403565996 -0.2397 -0.065334641215 -0.0752474617409 -0.23975 -0.0652330229055 -0.0759725840418 -0.2398 -0.0651313526889 -0.0763919116975 -0.23985 -0.0650293419144 -0.0766313487499 -0.2399 -0.0649273025459 -0.0767682007905 -0.23995 -0.064824946008 -0.0768470814366 -0.24 -0.0647225831098 -0.0768930714415 -0.24005 -0.0646199254387 -0.0769201902626 -0.2401 -0.0645172827238 -0.0769363176148 -0.24015 -0.0644143667736 -0.0769459349091 -0.2402 -0.0643114862862 -0.0769516276761 -0.24025 -0.064208353327 -0.0769549120526 -0.2403 -0.0641052755932 -0.0769566908843 -0.24035 -0.0640019654267 -0.0769575109967 -0.2404 -0.0638987295407 -0.0769577081311 -0.24045 -0.0637952805642 -0.0769574920441 -0.2405 -0.0636919242357 -0.0769569950903 -0.24055 -0.0635883734756 -0.0769563024085 -0.2406 -0.0634849330535 -0.0769554689447 -0.24065 -0.0633813161822 -0.0769545310264 -0.2407 -0.0632778266648 -0.0769535124624 -0.24075 -0.063174178004 -0.0769524294038 -0.2408 -0.0630706730344 -0.0769512924793 -0.24085 -0.0629670255415 -0.0769501090693 -0.2409 -0.0628635373847 -0.0769488839564 -0.24095 -0.0627599226206 -0.0769476205222 -0.241 -0.0626564821217 -0.0769463208419 -0.24105 -0.0625529302003 -0.0769449863863 -0.2411 -0.0624495667282 -0.0769436179253 -0.24115 -0.0623461062547 -0.076942215971 -0.2412 -0.0622428476341 -0.0769407806385 -0.24125 -0.0621395056327 -0.0769393119316 -0.2413 -0.0620363780696 -0.0769378096224 -0.24135 -0.0619331799085 -0.0769362734265 -0.2414 -0.0618302079155 -0.0769347029266 -0.24145 -0.0617271772313 -0.0769330976612 -0.2415 -0.0616243835526 -0.0769314571003 -0.24155 -0.0615215421777 -0.0769297806621 -0.2416 -0.0614189477173 -0.0769280677428 -0.24165 -0.0613163156092 -0.0769263176701 -0.2417 -0.0612139393631 -0.0769245297853 -0.24175 -0.0611115345385 -0.076922703341 -0.2418 -0.0610093935295 -0.0769208376326 -0.24185 -0.0609072320008 -0.0769189318457 -0.2419 -0.0608053412171 -0.0769169852325 -0.24195 -0.0607034369322 -0.0769149969154 -0.242 -0.0606018092686 -0.0769129661037 -0.24205 -0.060500174054 -0.0769108918581 -0.2421 -0.0603988202565 -0.0769087733434 -0.24215 -0.0602974637631 -0.0769066095589 -0.2422 -0.0601963923761 -0.0769043996225 -0.24225 -0.0600953220282 -0.0769021424716 -0.2423 -0.0599945393447 -0.0768998371743 -0.24235 -0.0598937602902 -0.0768974826054 -0.2424 -0.0597932703018 -0.0768950777804 -0.24245 -0.0596927853628 -0.0768926215105 -0.2425 -0.0595925897109 -0.0768901127561 -0.24255 -0.0594923993346 -0.0768875502639 -0.2426 -0.0593924972612 -0.0768849329368 -0.24265 -0.0592925994705 -0.0768822594562 -0.2427 -0.0591929877688 -0.0768795286652 -0.24275 -0.0590933781126 -0.0768767391797 -0.2428 -0.0589940510748 -0.076873889781 -0.24285 -0.0588947225741 -0.0768709790195 -0.2429 -0.0587956719358 -0.0768680056136 -0.24295 -0.058696615024 -0.076864968048 -0.243 -0.0585978299027 -0.0768618649776 -0.24305 -0.0584990323638 -0.0768586948223 -0.2431 -0.0584004991937 -0.0768554561729 -0.24315 -0.0583019460918 -0.0768521473858 -0.2432 -0.058203648548 -0.0768487669881 -0.24325 -0.0581053221461 -0.0768453132739 -0.2433 -0.0580072410574 -0.0768417847076 -0.24335 -0.0579091207254 -0.076838179523 -0.2434 -0.0578112339786 -0.0768344961233 -0.24345 -0.0577132960904 -0.0768307326849 -0.2435 -0.0576155785163 -0.0768268875517 -0.24355 -0.0575177963248 -0.0768229588456 -0.2436 -0.0574202195643 -0.0768189448539 -0.24365 -0.0573225630601 -0.0768148436473 -0.2437 -0.0572250954141 -0.0768106534596 -0.24375 -0.0571275311621 -0.0768063723142 -0.2438 -0.0570301374112 -0.0768019983951 -0.24385 -0.0569326283535 -0.0767975296828 -0.2439 -0.0568352695474 -0.0767929643156 -0.24395 -0.0567377747808 -0.0767883002357 -0.244 -0.0566404079985 -0.0767835355403 -0.24405 -0.0565428825102 -0.0767786681384 -0.2441 -0.0564454605703 -0.0767736960915 -0.24415 -0.0563478549271 -0.0767686172811 -0.2442 -0.0562503260572 -0.0767634297379 -0.24425 -0.056152586049 -0.0767581313219 -0.2443 -0.0560548934966 -0.0767527200384 -0.24435 -0.0559569597121 -0.0767471937315 -0.2444 -0.0558590412851 -0.0767415503876 -0.24445 -0.0557608486188 -0.0767357878407 -0.2445 -0.055662636156 -0.0767299040639 -0.24455 -0.0555641132337 -0.0767238968877 -0.2446 -0.0554655319788 -0.0767177642786 -0.24465 -0.0553666004767 -0.0767115040701 -0.2447 -0.0552675683427 -0.0767051142284 -0.24475 -0.0551681421964 -0.0766985925962 -0.2448 -0.0550685689096 -0.0766919371453 -0.24485 -0.0549685533817 -0.0766851457338 -0.2449 -0.0548683394669 -0.0766782163456 -0.24495 -0.054767630044 -0.07667114686 -0.245 -0.0546666656283 -0.0766639352794 -0.24505 -0.0545651467264 -0.0766565795111 -0.2451 -0.054463310132 -0.076649077582 -0.24515 -0.0543608535608 -0.076641427433 -0.2452 -0.0542580096309 -0.076633627121 -0.24525 -0.054154472769 -0.0766256746258 -0.2453 -0.0540504708762 -0.0766175680396 -0.24535 -0.0539456944964 -0.0766093053866 -0.2454 -0.0538403661679 -0.0766008848004 -0.24545 -0.0537341718417 -0.0765923043548 -0.2455 -0.0536273279156 -0.0765835622291 -0.24555 -0.0535195148927 -0.0765746565507 -0.2456 -0.0534109420926 -0.0765655855488 -0.24565 -0.0533012835364 -0.0765563474085 -0.2457 -0.0531907403297 -0.0765469404137 -0.24575 -0.0530789787558 -0.0765373628114 -0.2458 -0.0529661903207 -0.0765276129433 -0.24585 -0.0528520320351 -0.0765176891207 -0.2459 -0.0527366841085 -0.0765075897456 -0.24595 -0.0526197923934 -0.0764973131964 -0.246 -0.0525015237101 -0.0764868579388 -0.24605 -0.0523815104212 -0.0764762224206 -0.2461 -0.0522599033598 -0.0764654051723 -0.24615 -0.0521363184948 -0.0764544047116 -0.2462 -0.0520108874231 -0.0764432196348 -0.24625 -0.0518832060762 -0.0764318485313 -0.2463 -0.0517533827229 -0.0764202900643 -0.24635 -0.0516209886533 -0.076408542894 -0.2464 -0.0514861036138 -0.0763966057492 -0.24645 -0.0513482683738 -0.0763844773603 -0.2465 -0.0512075275024 -0.0763721565221 -0.24655 -0.0510633836899 -0.0763596420334 -0.2466 -0.0509158377193 -0.0763469327521 -0.24665 -0.0507643443709 -0.0763340275425 -0.2467 -0.0506088493981 -0.0763209253237 -0.24675 -0.0504487467613 -0.0763076250228 -0.2468 -0.0502839123244 -0.0762941256151 -0.24685 -0.0501136620728 -0.0762804260854 -0.2469 -0.0499377821205 -0.0762665254615 -0.24695 -0.0497554874004 -0.0762524227809 -0.247 -0.0495664473737 -0.0762381171167 -0.24705 -0.0493697444528 -0.0762236075513 -0.2471 -0.0491648945043 -0.0762088931969 -0.24715 -0.0489508038875 -0.0761939731735 -0.2472 -0.048726783369 -0.0761788466213 -0.24725 -0.0484915020608 -0.0761635126876 -0.2473 -0.048243992631 -0.0761479705319 -0.24735 -0.0479825994577 -0.0761322193161 -0.2474 -0.0477059717855 -0.0761162582045 -0.24745 -0.0474120018624 -0.0761000863602 -0.2475 -0.0470988006239 -0.0760837029381 -0.24755 -0.0467636189216 -0.0760671070836 -0.2476 -0.0464037968962 -0.0760502979231 -0.24765 -0.0460156568745 -0.0760332745658 -0.2477 -0.0455954116348 -0.0760160360862 -0.24775 -0.0451380097097 -0.0759985815315 -0.2478 -0.044637977416 -0.0759809098988 -0.24785 -0.044088183657 -0.0759630201425 -0.2479 -0.0434805726898 -0.0759449111479 -0.24795 -0.0428047922128 -0.0759265817414 -0.248 -0.0420487439007 -0.0759080306553 -0.24805 -0.0411969813405 -0.0758892565406 -0.2481 -0.0402309614553 -0.075870257927 -0.24815 -0.0391270724568 -0.0758510332325 -0.2482 -0.0378564331083 -0.0758315807184 -0.24825 -0.0363824152902 -0.075811898498 -0.2483 -0.0346599497758 -0.0757919844802 -0.24835 -0.0326327642284 -0.0757718363784 -0.2484 -0.0302330195798 -0.0757514516425 -0.24845 -0.0273803332202 -0.0757308274597 -0.2485 -0.0239861635043 -0.0757099606768 -0.24855 -0.0199630083277 -0.0756888477875 -0.2486 -0.0152475612639 -0.0756674848377 -0.24865 -0.00983914391438 -0.0756458673974 -0.2487 -0.00385657797336 -0.0756239904368 -0.24875 0.00241033906448 -0.0756018482735 -0.2488 0.00849749280922 -0.0755794344073 -0.24885 0.0138607338403 -0.0755567414224 -0.2489 0.0180431083915 -0.0755337607603 -0.24895 0.0208167415313 -0.0755104825419 -0.249 0.0222060011425 -0.075486895237 -0.24905 0.0224077398977 -0.0754629853477 -0.2491 0.0216825852379 -0.0754387368938 -0.24915 0.020279953634 -0.075414130847 -0.2492 0.0184039434812 -0.0753891442795 -0.24925 0.0162095819479 -0.0753637493446 -0.2493 0.013809298153 -0.0753379118091 -0.24935 0.0112839798433 -0.0753115892135 -0.2494 0.00869081527658 -0.0752847283137 -0.24945 0.00607095235025 -0.0752572618212 -0.2495 0.00345327750376 -0.0752291040158 -0.24955 0.000858712512877 -0.075200145179 -0.2496 -0.00169844926616 -0.0751702443315 -0.24965 -0.00420793606597 -0.075139220137 -0.2497 -0.00666330667742 -0.0751068393444 -0.24975 -0.00906013068632 -0.0750728024952 -0.2498 -0.0113963448917 -0.0750367260944 -0.24985 -0.0136708329041 -0.0749981207409 -0.2499 -0.0158840780115 -0.074956364116 -0.24995 -0.0180369763345 -0.0749106679554 -0.25 -0.0201316710708 -0.0748600374168 diff --git a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/data/reference_neuron.dat b/tests/python/Rallpacks/moose_vs_neuron/rallpack3/data/reference_neuron.dat deleted file mode 100644 index a699f90a..00000000 --- a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/data/reference_neuron.dat +++ /dev/null @@ -1,5000 +0,0 @@ -0 -0.065 -0.065 -5e-05 -0.0601856 -0.0651575 -0.0001 -0.0582823 -0.0653124 -0.00015 -0.0568717 -0.0654652 -0.0002 -0.0557084 -0.0656163 -0.00025 -0.0546937 -0.0657659 -0.0003 -0.053774 -0.0659142 -0.00035 -0.0529147 -0.0660614 -0.0004 -0.0520903 -0.0662074 -0.00045 -0.0512804 -0.0663522 -0.0005 -0.0504671 -0.0664959 -0.00055 -0.0496335 -0.0666385 -0.0006 -0.0487623 -0.0667798 -0.00065 -0.0478347 -0.0669198 -0.0007 -0.0468292 -0.0670584 -0.00075 -0.0457198 -0.0671956 -0.0008 -0.044474 -0.0673314 -0.00085 -0.0430497 -0.0674655 -0.0009 -0.0413909 -0.0675981 -0.00095 -0.0394214 -0.0677289 -0.001 -0.0370361 -0.067858 -0.00105 -0.0340882 -0.0679853 -0.0011 -0.0303727 -0.0681108 -0.00115 -0.0256099 -0.0682344 -0.0012 -0.0194435 -0.068356 -0.00125 -0.0114985 -0.0684757 -0.0013 -0.00159644 -0.0685934 -0.00135 0.00979541 -0.068709 -0.0014 0.0211855 -0.0688226 -0.00145 0.030577 -0.068934 -0.0015 0.0368121 -0.0690434 -0.00155 0.0401051 -0.0691506 -0.0016 0.0413273 -0.0692556 -0.00165 0.0412677 -0.0693585 -0.0017 0.0404276 -0.0694591 -0.00175 0.0390879 -0.0695576 -0.0018 0.0374054 -0.0696538 -0.00185 0.035473 -0.0697478 -0.0019 0.0333514 -0.0698395 -0.00195 0.0310844 -0.0699289 -0.002 0.0287062 -0.0700161 -0.00205 0.0262448 -0.0701009 -0.0021 0.0237236 -0.0701833 -0.00215 0.021163 -0.0702632 -0.0022 0.0185799 -0.0703406 -0.00225 0.0159891 -0.0704153 -0.0023 0.0134027 -0.0704872 -0.00235 0.0108307 -0.070556 -0.0024 0.00828138 -0.0706214 -0.00245 0.00576114 -0.0706831 -0.0025 0.00327499 -0.0707406 -0.00255 0.000826651 -0.0707933 -0.0026 -0.00158128 -0.0708404 -0.00265 -0.00394712 -0.0708808 -0.0027 -0.00626999 -0.0709134 -0.00275 -0.00854969 -0.0709365 -0.0028 -0.0107866 -0.0709483 -0.00285 -0.0129815 -0.0709462 -0.0029 -0.0151359 -0.0709273 -0.00295 -0.0172516 -0.0708878 -0.003 -0.0193309 -0.070823 -0.00305 -0.0213771 -0.0707271 -0.0031 -0.0233937 -0.0705931 -0.00315 -0.0253855 -0.0704119 -0.0032 -0.0273581 -0.0701727 -0.00325 -0.0293185 -0.0698619 -0.0033 -0.031275 -0.0694627 -0.00335 -0.033237 -0.0689543 -0.0034 -0.0352157 -0.0683112 -0.00345 -0.0372234 -0.0675016 -0.0035 -0.0392732 -0.066486 -0.00355 -0.0413785 -0.0652157 -0.0036 -0.0435513 -0.0636298 -0.00365 -0.0458007 -0.0616519 -0.0037 -0.0481295 -0.0591854 -0.00375 -0.0505306 -0.0561056 -0.0038 -0.0529817 -0.0522469 -0.00385 -0.0554424 -0.0473802 -0.0039 -0.0578523 -0.0411686 -0.00395 -0.0601364 -0.0330904 -0.004 -0.0622169 -0.0223354 -0.00405 -0.0640296 -0.00788677 -0.0041 -0.0655387 0.0103026 -0.00415 -0.0667423 0.0283645 -0.0042 -0.0676669 0.0398132 -0.00425 -0.0683558 0.0439189 -0.0043 -0.0688565 0.0445382 -0.00435 -0.069213 0.0440554 -0.0044 -0.0694614 0.0431558 -0.00445 -0.06963 0.0419918 -0.0045 -0.0697396 0.0406073 -0.00455 -0.0698056 0.0390257 -0.0046 -0.069839 0.0372668 -0.00465 -0.0698476 0.03535 -0.0047 -0.0698375 0.0332948 -0.00475 -0.0698126 0.031121 -0.0048 -0.0697764 0.0288476 -0.00485 -0.069731 0.026493 -0.0049 -0.0696782 0.0240743 -0.00495 -0.0696196 0.0216072 -0.005 -0.069556 0.0191059 -0.00505 -0.0694883 0.0165828 -0.0051 -0.0694172 0.0140487 -0.00515 -0.0693433 0.0115129 -0.0052 -0.0692668 0.00898313 -0.00525 -0.0691883 0.00646556 -0.0053 -0.0691078 0.00396518 -0.00535 -0.0690257 0.00148576 -0.0054 -0.0689422 -0.00096999 -0.00545 -0.0688573 -0.00340035 -0.0055 -0.0687713 -0.00580441 -0.00555 -0.0686841 -0.0081821 -0.0056 -0.068596 -0.0105341 -0.00565 -0.068507 -0.0128619 -0.0057 -0.0684172 -0.0151677 -0.00575 -0.0683266 -0.0174547 -0.0058 -0.0682352 -0.0197275 -0.00585 -0.0681432 -0.0219919 -0.0059 -0.0680504 -0.0242558 -0.00595 -0.0679571 -0.0265296 -0.006 -0.0678632 -0.028827 -0.00605 -0.0677687 -0.0311659 -0.0061 -0.0676736 -0.0335693 -0.00615 -0.067578 -0.036066 -0.0062 -0.067482 -0.038692 -0.00625 -0.0673854 -0.0414895 -0.0063 -0.0672884 -0.0445053 -0.00635 -0.0671909 -0.0477839 -0.0064 -0.067093 -0.0513541 -0.00645 -0.0669947 -0.0552043 -0.0065 -0.0668959 -0.0592483 -0.00655 -0.0667968 -0.0632943 -0.0066 -0.0666973 -0.0670551 -0.00665 -0.0665974 -0.0702332 -0.0067 -0.0664971 -0.0726505 -0.00675 -0.0663966 -0.0743173 -0.0068 -0.0662957 -0.0753814 -0.00685 -0.0661944 -0.0760272 -0.0069 -0.0660929 -0.0764088 -0.00695 -0.0659911 -0.0766322 -0.007 -0.065889 -0.0767633 -0.00705 -0.0657866 -0.0768407 -0.0071 -0.0656839 -0.0768871 -0.00715 -0.065581 -0.076915 -0.0072 -0.0654779 -0.076932 -0.00725 -0.0653745 -0.0769424 -0.0073 -0.065271 -0.0769487 -0.00735 -0.0651672 -0.0769525 -0.0074 -0.0650632 -0.0769546 -0.00745 -0.064959 -0.0769557 -0.0075 -0.0648547 -0.076956 -0.00755 -0.0647502 -0.076956 -0.0076 -0.0646455 -0.0769555 -0.00765 -0.0645407 -0.0769549 -0.0077 -0.0644358 -0.0769541 -0.00775 -0.0643308 -0.0769532 -0.0078 -0.0642256 -0.0769522 -0.00785 -0.0641203 -0.0769511 -0.0079 -0.064015 -0.07695 -0.00795 -0.0639096 -0.0769488 -0.008 -0.063804 -0.0769475 -0.00805 -0.0636985 -0.0769462 -0.0081 -0.0635928 -0.0769449 -0.00815 -0.0634872 -0.0769435 -0.0082 -0.0633815 -0.0769422 -0.00825 -0.0632757 -0.0769407 -0.0083 -0.06317 -0.0769393 -0.00835 -0.0630642 -0.0769378 -0.0084 -0.0629585 -0.0769362 -0.00845 -0.0628527 -0.0769347 -0.0085 -0.062747 -0.0769331 -0.00855 -0.0626413 -0.0769314 -0.0086 -0.0625356 -0.0769297 -0.00865 -0.06243 -0.076928 -0.0087 -0.0623244 -0.0769263 -0.00875 -0.0622188 -0.0769245 -0.0088 -0.0621134 -0.0769227 -0.00885 -0.0620079 -0.0769208 -0.0089 -0.0619026 -0.0769189 -0.00895 -0.0617974 -0.076917 -0.009 -0.0616922 -0.076915 -0.00905 -0.0615871 -0.076913 -0.0091 -0.0614821 -0.0769109 -0.00915 -0.0613772 -0.0769088 -0.0092 -0.0612725 -0.0769066 -0.00925 -0.0611678 -0.0769044 -0.0093 -0.0610633 -0.0769022 -0.00935 -0.0609588 -0.0768999 -0.0094 -0.0608545 -0.0768976 -0.00945 -0.0607503 -0.0768952 -0.0095 -0.0606463 -0.0768927 -0.00955 -0.0605424 -0.0768902 -0.0096 -0.0604386 -0.0768877 -0.00965 -0.060335 -0.0768851 -0.0097 -0.0602314 -0.0768824 -0.00975 -0.0601281 -0.0768797 -0.0098 -0.0600249 -0.0768769 -0.00985 -0.0599218 -0.0768741 -0.0099 -0.0598188 -0.0768712 -0.00995 -0.0597161 -0.0768683 -0.01 -0.0596134 -0.0768653 -0.01005 -0.0595109 -0.0768622 -0.0101 -0.0594085 -0.0768591 -0.01015 -0.0593063 -0.0768559 -0.0102 -0.0592042 -0.0768526 -0.01025 -0.0591023 -0.0768493 -0.0103 -0.0590005 -0.0768459 -0.01035 -0.0588988 -0.0768424 -0.0104 -0.0587973 -0.0768388 -0.01045 -0.0586958 -0.0768352 -0.0105 -0.0585945 -0.0768315 -0.01055 -0.0584934 -0.0768277 -0.0106 -0.0583923 -0.0768238 -0.01065 -0.0582913 -0.0768199 -0.0107 -0.0581905 -0.0768158 -0.01075 -0.0580897 -0.0768117 -0.0108 -0.0579891 -0.0768075 -0.01085 -0.0578885 -0.0768032 -0.0109 -0.057788 -0.0767988 -0.01095 -0.0576876 -0.0767943 -0.011 -0.0575872 -0.0767897 -0.01105 -0.0574869 -0.0767851 -0.0111 -0.0573867 -0.0767803 -0.01115 -0.0572864 -0.0767754 -0.0112 -0.0571862 -0.0767704 -0.01125 -0.057086 -0.0767653 -0.0113 -0.0569859 -0.0767601 -0.01135 -0.0568857 -0.0767548 -0.0114 -0.0567855 -0.0767494 -0.01145 -0.0566852 -0.0767439 -0.0115 -0.0565849 -0.0767383 -0.01155 -0.0564846 -0.0767325 -0.0116 -0.0563842 -0.0767266 -0.01165 -0.0562837 -0.0767206 -0.0117 -0.0561831 -0.0767145 -0.01175 -0.0560823 -0.0767083 -0.0118 -0.0559814 -0.0767019 -0.01185 -0.0558804 -0.0766954 -0.0119 -0.0557792 -0.0766888 -0.01195 -0.0556777 -0.076682 -0.012 -0.0555761 -0.0766751 -0.01205 -0.0554742 -0.0766681 -0.0121 -0.055372 -0.0766609 -0.01215 -0.0552696 -0.0766535 -0.0122 -0.0551668 -0.0766461 -0.01225 -0.0550637 -0.0766385 -0.0123 -0.0549602 -0.0766307 -0.01235 -0.0548562 -0.0766228 -0.0124 -0.0547519 -0.0766147 -0.01245 -0.054647 -0.0766065 -0.0125 -0.0545417 -0.0765982 -0.01255 -0.0544358 -0.0765896 -0.0126 -0.0543293 -0.0765809 -0.01265 -0.0542222 -0.0765721 -0.0127 -0.0541144 -0.0765631 -0.01275 -0.0540058 -0.0765539 -0.0128 -0.0538965 -0.0765446 -0.01285 -0.0537864 -0.0765351 -0.0129 -0.0536753 -0.0765254 -0.01295 -0.0535633 -0.0765156 -0.013 -0.0534503 -0.0765055 -0.01305 -0.0533362 -0.0764953 -0.0131 -0.0532209 -0.076485 -0.01315 -0.0531044 -0.0764744 -0.0132 -0.0529866 -0.0764637 -0.01325 -0.0528673 -0.0764528 -0.0133 -0.0527466 -0.0764417 -0.01335 -0.0526242 -0.0764304 -0.0134 -0.0525 -0.076419 -0.01345 -0.052374 -0.0764073 -0.0135 -0.052246 -0.0763955 -0.01355 -0.0521158 -0.0763835 -0.0136 -0.0519834 -0.0763713 -0.01365 -0.0518484 -0.0763589 -0.0137 -0.0517109 -0.0763463 -0.01375 -0.0515704 -0.0763335 -0.0138 -0.0514269 -0.0763205 -0.01385 -0.05128 -0.0763074 -0.0139 -0.0511296 -0.076294 -0.01395 -0.0509752 -0.0762804 -0.014 -0.0508167 -0.0762667 -0.01405 -0.0506536 -0.0762527 -0.0141 -0.0504855 -0.0762386 -0.01415 -0.0503121 -0.0762242 -0.0142 -0.0501328 -0.0762096 -0.01425 -0.049947 -0.0761949 -0.0143 -0.0497542 -0.0761799 -0.01435 -0.0495537 -0.0761647 -0.0144 -0.0493447 -0.0761494 -0.01445 -0.0491264 -0.0761338 -0.0145 -0.0488977 -0.076118 -0.01455 -0.0486576 -0.076102 -0.0146 -0.0484047 -0.0760858 -0.01465 -0.0481377 -0.0760694 -0.0147 -0.0478548 -0.0760528 -0.01475 -0.0475541 -0.0760359 -0.0148 -0.0472333 -0.0760189 -0.01485 -0.0468898 -0.0760016 -0.0149 -0.0465206 -0.0759842 -0.01495 -0.046122 -0.0759665 -0.015 -0.0456896 -0.0759486 -0.01505 -0.0452185 -0.0759305 -0.0151 -0.0447024 -0.0759122 -0.01515 -0.0441339 -0.0758937 -0.0152 -0.0435042 -0.0758749 -0.01525 -0.0428021 -0.075856 -0.0153 -0.0420142 -0.0758368 -0.01535 -0.041124 -0.0758174 -0.0154 -0.0401105 -0.0757977 -0.01545 -0.038948 -0.0757779 -0.0155 -0.0376038 -0.0757578 -0.01555 -0.0360373 -0.0757375 -0.0156 -0.0341972 -0.0757169 -0.01565 -0.0320206 -0.0756962 -0.0157 -0.0294306 -0.0756751 -0.01575 -0.026338 -0.0756539 -0.0158 -0.0226466 -0.0756324 -0.01585 -0.0182686 -0.0756107 -0.0159 -0.0131557 -0.0755887 -0.01595 -0.00735079 -0.0755665 -0.016 -0.00105105 -0.075544 -0.01605 0.00535352 -0.0755212 -0.0161 0.0113237 -0.0754982 -0.01615 0.0163182 -0.0754749 -0.0162 0.01997 -0.0754513 -0.01625 0.0221769 -0.0754274 -0.0163 0.0230624 -0.0754032 -0.01635 0.0228686 -0.0753787 -0.0164 0.0218589 -0.0753538 -0.01645 0.0202639 -0.0753286 -0.0165 0.018265 -0.075303 -0.01655 0.0159966 -0.075277 -0.0166 0.0135559 -0.0752505 -0.01665 0.0110125 -0.0752235 -0.0167 0.00841615 -0.0751959 -0.01675 0.00580237 -0.0751678 -0.0168 0.00319671 -0.0751389 -0.01685 0.000617364 -0.0751091 -0.0169 -0.00192282 -0.0750784 -0.01695 -0.00441498 -0.0750464 -0.017 -0.0068532 -0.075013 -0.01705 -0.00923383 -0.0749777 -0.0171 -0.0115549 -0.0749402 -0.01715 -0.0138158 -0.0748999 -0.0172 -0.0160169 -0.0748561 -0.01725 -0.0181594 -0.0748078 -0.0173 -0.0202452 -0.074754 -0.01735 -0.0222771 -0.0746932 -0.0174 -0.0242583 -0.0746236 -0.01745 -0.0261928 -0.074543 -0.0175 -0.0280851 -0.0744484 -0.01755 -0.0299408 -0.0743366 -0.0176 -0.0317659 -0.0742029 -0.01765 -0.0335672 -0.0740421 -0.0177 -0.0353521 -0.0738473 -0.01775 -0.0371284 -0.0736103 -0.0178 -0.0389043 -0.0733206 -0.01785 -0.0406877 -0.0729655 -0.0179 -0.0424859 -0.0725291 -0.01795 -0.044305 -0.0719916 -0.018 -0.0461488 -0.0713289 -0.01805 -0.0480178 -0.0705108 -0.0181 -0.0499078 -0.0695001 -0.01815 -0.0518089 -0.0682506 -0.0182 -0.0537043 -0.0667047 -0.01825 -0.0555702 -0.0647907 -0.0183 -0.0573773 -0.0624182 -0.01835 -0.0590926 -0.0594722 -0.0184 -0.0606844 -0.0558024 -0.01845 -0.0621263 -0.0512055 -0.0185 -0.0634009 -0.0453902 -0.01855 -0.064502 -0.0379075 -0.0186 -0.0654339 -0.0280261 -0.01865 -0.0662091 -0.0146203 -0.0187 -0.0668449 0.00329633 -0.01875 -0.0673605 0.0236412 -0.0188 -0.0677749 0.0388942 -0.01885 -0.068105 0.0450639 -0.0189 -0.0683657 0.04623 -0.01895 -0.0685693 0.0459579 -0.019 -0.0687259 0.045269 -0.01905 -0.0688438 0.0443449 -0.0191 -0.0689295 0.0432194 -0.01915 -0.0689886 0.0419056 -0.0192 -0.0690254 0.0404147 -0.01925 -0.0690434 0.0387587 -0.0193 -0.0690457 0.0369518 -0.01935 -0.0690347 0.0350092 -0.0194 -0.0690122 0.0329471 -0.01945 -0.0689802 0.0307819 -0.0195 -0.0689398 0.0285298 -0.01955 -0.0688924 0.0262066 -0.0196 -0.0688389 0.0238269 -0.01965 -0.0687801 0.0214044 -0.0197 -0.0687167 0.0189512 -0.01975 -0.0686494 0.0164784 -0.0198 -0.0685786 0.0139954 -0.01985 -0.0685048 0.0115105 -0.0199 -0.0684283 0.00903047 -0.01995 -0.0683495 0.00656106 -0.02 -0.0682686 0.00410677 -0.02005 -0.0681859 0.00167107 -0.0201 -0.0681016 -0.00074351 -0.02015 -0.0680158 -0.00313531 -0.0202 -0.0679286 -0.00550343 -0.02025 -0.0678403 -0.00784774 -0.0203 -0.0677509 -0.0101688 -0.02035 -0.0676605 -0.0124678 -0.0204 -0.0675692 -0.0147469 -0.02045 -0.067477 -0.0170089 -0.0205 -0.0673842 -0.0192579 -0.02055 -0.0672906 -0.0214993 -0.0206 -0.0671963 -0.0237403 -0.02065 -0.0671015 -0.0259906 -0.0207 -0.067006 -0.0282627 -0.02075 -0.06691 -0.0305732 -0.0208 -0.0668136 -0.0329435 -0.02085 -0.0667166 -0.035401 -0.0209 -0.0666192 -0.0379799 -0.02095 -0.0665214 -0.040721 -0.021 -0.0664232 -0.0436712 -0.02105 -0.0663246 -0.0468777 -0.0211 -0.0662257 -0.0503769 -0.02115 -0.0661264 -0.0541723 -0.0212 -0.0660267 -0.0582011 -0.02125 -0.0659268 -0.0622985 -0.0213 -0.0658266 -0.0661909 -0.02135 -0.0657261 -0.0695626 -0.0214 -0.0656253 -0.0721882 -0.02145 -0.0655243 -0.0740311 -0.0215 -0.0654231 -0.0752189 -0.02155 -0.0653216 -0.0759409 -0.0216 -0.0652199 -0.0763654 -0.02165 -0.065118 -0.0766116 -0.0217 -0.065016 -0.0767543 -0.02175 -0.0649137 -0.0768376 -0.0218 -0.0648113 -0.0768867 -0.02185 -0.0647087 -0.0769159 -0.0219 -0.064606 -0.0769335 -0.02195 -0.0645032 -0.0769441 -0.022 -0.0644002 -0.0769504 -0.02205 -0.0642971 -0.0769541 -0.0221 -0.064194 -0.0769562 -0.02215 -0.0640907 -0.0769572 -0.0222 -0.0639873 -0.0769575 -0.02225 -0.0638839 -0.0769574 -0.0223 -0.0637804 -0.076957 -0.02235 -0.0636769 -0.0769564 -0.0224 -0.0635733 -0.0769556 -0.02245 -0.0634696 -0.0769546 -0.0225 -0.063366 -0.0769536 -0.02255 -0.0632623 -0.0769526 -0.0226 -0.0631586 -0.0769515 -0.02265 -0.0630549 -0.0769503 -0.0227 -0.0629512 -0.0769491 -0.02275 -0.0628476 -0.0769478 -0.0228 -0.0627439 -0.0769465 -0.02285 -0.0626403 -0.0769452 -0.0229 -0.0625367 -0.0769438 -0.02295 -0.0624332 -0.0769424 -0.023 -0.0623297 -0.076941 -0.02305 -0.0622262 -0.0769395 -0.0231 -0.0621229 -0.076938 -0.02315 -0.0620196 -0.0769365 -0.0232 -0.0619163 -0.0769349 -0.02325 -0.0618132 -0.0769333 -0.0233 -0.0617101 -0.0769317 -0.02335 -0.0616072 -0.07693 -0.0234 -0.0615043 -0.0769283 -0.02345 -0.0614015 -0.0769266 -0.0235 -0.0612989 -0.0769248 -0.02355 -0.0611963 -0.076923 -0.0236 -0.0610939 -0.0769211 -0.02365 -0.0609916 -0.0769192 -0.0237 -0.0608894 -0.0769173 -0.02375 -0.0607873 -0.0769153 -0.0238 -0.0606854 -0.0769133 -0.02385 -0.0605836 -0.0769112 -0.0239 -0.0604819 -0.0769091 -0.02395 -0.0603804 -0.076907 -0.024 -0.060279 -0.0769048 -0.02405 -0.0601778 -0.0769025 -0.0241 -0.0600767 -0.0769002 -0.02415 -0.0599757 -0.0768979 -0.0242 -0.0598749 -0.0768955 -0.02425 -0.0597743 -0.076893 -0.0243 -0.0596737 -0.0768905 -0.02435 -0.0595734 -0.076888 -0.0244 -0.0594732 -0.0768854 -0.02445 -0.0593731 -0.0768827 -0.0245 -0.0592732 -0.07688 -0.02455 -0.0591734 -0.0768772 -0.0246 -0.0590737 -0.0768744 -0.02465 -0.0589742 -0.0768715 -0.0247 -0.0588749 -0.0768685 -0.02475 -0.0587756 -0.0768655 -0.0248 -0.0586765 -0.0768624 -0.02485 -0.0585776 -0.0768592 -0.0249 -0.0584787 -0.076856 -0.02495 -0.05838 -0.0768527 -0.025 -0.0582814 -0.0768494 -0.02505 -0.0581829 -0.0768459 -0.0251 -0.0580845 -0.0768424 -0.02515 -0.0579863 -0.0768388 -0.0252 -0.0578881 -0.0768352 -0.02525 -0.05779 -0.0768314 -0.0253 -0.057692 -0.0768276 -0.02535 -0.0575941 -0.0768237 -0.0254 -0.0574962 -0.0768197 -0.02545 -0.0573984 -0.0768156 -0.0255 -0.0573007 -0.0768114 -0.02555 -0.057203 -0.0768072 -0.0256 -0.0571054 -0.0768028 -0.02565 -0.0570078 -0.0767984 -0.0257 -0.0569102 -0.0767938 -0.02575 -0.0568126 -0.0767892 -0.0258 -0.056715 -0.0767845 -0.02585 -0.0566174 -0.0767796 -0.0259 -0.0565197 -0.0767747 -0.02595 -0.0564221 -0.0767696 -0.026 -0.0563243 -0.0767645 -0.02605 -0.0562265 -0.0767592 -0.0261 -0.0561287 -0.0767538 -0.02615 -0.0560307 -0.0767483 -0.0262 -0.0559326 -0.0767427 -0.02625 -0.0558344 -0.076737 -0.0263 -0.055736 -0.0767311 -0.02635 -0.0556375 -0.0767252 -0.0264 -0.0555388 -0.0767191 -0.02645 -0.0554399 -0.0767128 -0.0265 -0.0553408 -0.0767065 -0.02655 -0.0552414 -0.0767 -0.0266 -0.0551418 -0.0766934 -0.02665 -0.0550418 -0.0766866 -0.0267 -0.0549416 -0.0766797 -0.02675 -0.054841 -0.0766727 -0.0268 -0.05474 -0.0766655 -0.02685 -0.0546386 -0.0766582 -0.0269 -0.0545368 -0.0766508 -0.02695 -0.0544345 -0.0766432 -0.027 -0.0543317 -0.0766354 -0.02705 -0.0542284 -0.0766275 -0.0271 -0.0541245 -0.0766194 -0.02715 -0.05402 -0.0766112 -0.0272 -0.0539148 -0.0766029 -0.02725 -0.0538089 -0.0765943 -0.0273 -0.0537023 -0.0765856 -0.02735 -0.0535948 -0.0765768 -0.0274 -0.0534865 -0.0765678 -0.02745 -0.0533773 -0.0765586 -0.0275 -0.0532671 -0.0765492 -0.02755 -0.0531558 -0.0765397 -0.0276 -0.0530434 -0.07653 -0.02765 -0.0529298 -0.0765201 -0.0277 -0.0528149 -0.0765101 -0.02775 -0.0526987 -0.0764999 -0.0278 -0.052581 -0.0764895 -0.02785 -0.0524618 -0.0764789 -0.0279 -0.0523408 -0.0764681 -0.02795 -0.0522181 -0.0764572 -0.028 -0.0520935 -0.0764461 -0.02805 -0.0519669 -0.0764347 -0.0281 -0.051838 -0.0764232 -0.02815 -0.0517068 -0.0764116 -0.0282 -0.0515731 -0.0763997 -0.02825 -0.0514366 -0.0763876 -0.0283 -0.0512973 -0.0763754 -0.02835 -0.0511547 -0.0763629 -0.0284 -0.0510088 -0.0763503 -0.02845 -0.0508592 -0.0763374 -0.0285 -0.0507056 -0.0763244 -0.02855 -0.0505477 -0.0763112 -0.0286 -0.0503852 -0.0762977 -0.02865 -0.0502176 -0.0762841 -0.0287 -0.0500444 -0.0762703 -0.02875 -0.0498653 -0.0762562 -0.0288 -0.0496795 -0.076242 -0.02885 -0.0494866 -0.0762275 -0.0289 -0.0492858 -0.0762129 -0.02895 -0.0490762 -0.076198 -0.029 -0.0488571 -0.076183 -0.02905 -0.0486274 -0.0761677 -0.0291 -0.0483859 -0.0761523 -0.02915 -0.0481313 -0.0761366 -0.0292 -0.0478622 -0.0761207 -0.02925 -0.0475768 -0.0761046 -0.0293 -0.0472731 -0.0760883 -0.02935 -0.0469487 -0.0760718 -0.0294 -0.046601 -0.076055 -0.02945 -0.0462268 -0.0760381 -0.0295 -0.0458223 -0.0760209 -0.02955 -0.0453831 -0.0760035 -0.0296 -0.0449038 -0.0759859 -0.02965 -0.0443783 -0.0759681 -0.0297 -0.0437987 -0.0759501 -0.02975 -0.0431558 -0.0759318 -0.0298 -0.0424384 -0.0759134 -0.02985 -0.0416324 -0.0758947 -0.0299 -0.0407208 -0.0758758 -0.02995 -0.0396821 -0.0758566 -0.03 -0.0384897 -0.0758373 -0.03005 -0.0371105 -0.0758177 -0.0301 -0.0355027 -0.0757978 -0.03015 -0.0336148 -0.0757778 -0.0302 -0.0313832 -0.0757575 -0.03025 -0.0287319 -0.0757369 -0.0303 -0.0255743 -0.0757162 -0.03035 -0.0218199 -0.0756951 -0.0304 -0.0173917 -0.0756739 -0.03045 -0.012259 -0.0756524 -0.0305 -0.00648815 -0.0756306 -0.03055 -0.00029949 -0.0756086 -0.0306 0.00590731 -0.0755862 -0.03065 0.0116097 -0.0755637 -0.0307 0.0163076 -0.0755408 -0.03075 0.0196806 -0.0755176 -0.0308 0.0216568 -0.0754942 -0.03085 0.0223677 -0.0754704 -0.0309 0.0220484 -0.0754463 -0.03095 0.0209504 -0.0754219 -0.031 0.0192935 -0.075397 -0.03105 0.017251 -0.0753718 -0.0311 0.0149523 -0.0753462 -0.03115 0.0124912 -0.0753201 -0.0312 0.00993506 -0.0752935 -0.03125 0.00733224 -0.0752663 -0.0313 0.00471723 -0.0752385 -0.03135 0.00211469 -0.0752099 -0.0314 -0.000457911 -0.0751804 -0.03145 -0.00298832 -0.07515 -0.0315 -0.00546819 -0.0751182 -0.03155 -0.00789206 -0.075085 -0.0316 -0.0102567 -0.0750499 -0.03165 -0.0125604 -0.0750125 -0.0317 -0.0148029 -0.0749722 -0.03175 -0.0169849 -0.0749283 -0.0318 -0.0191078 -0.0748799 -0.03185 -0.0211739 -0.0748258 -0.0319 -0.0231861 -0.0747646 -0.03195 -0.025148 -0.0746944 -0.032 -0.0270638 -0.074613 -0.03205 -0.0289386 -0.0745175 -0.0321 -0.0307781 -0.0744045 -0.03215 -0.0325885 -0.0742693 -0.0322 -0.0343771 -0.0741068 -0.03225 -0.0361512 -0.07391 -0.0323 -0.037919 -0.0736705 -0.03235 -0.0396883 -0.0733782 -0.0324 -0.0414668 -0.07302 -0.03245 -0.0432613 -0.0725801 -0.0325 -0.045077 -0.0720391 -0.03255 -0.0469163 -0.0713725 -0.0326 -0.0487782 -0.0705506 -0.03265 -0.0506564 -0.0695362 -0.0327 -0.0525387 -0.0682834 -0.03275 -0.0544062 -0.0667353 -0.0328 -0.0562336 -0.0648205 -0.03285 -0.0579905 -0.0624497 -0.0329 -0.0596454 -0.0595089 -0.03295 -0.0611689 -0.0558496 -0.033 -0.0625382 -0.0512709 -0.03305 -0.0637406 -0.0454852 -0.0331 -0.0647736 -0.0380499 -0.03315 -0.0656445 -0.0282445 -0.0332 -0.0663672 -0.0149568 -0.03325 -0.0669593 0.00281347 -0.0333 -0.0674394 0.0231109 -0.03335 -0.0678254 0.0385381 -0.0334 -0.0681332 0.0449037 -0.03345 -0.0683763 0.0461476 -0.0335 -0.068566 0.0458937 -0.03355 -0.0687118 0.0452076 -0.0336 -0.0688211 0.044282 -0.03365 -0.0689 0.0431534 -0.0337 -0.0689537 0.0418357 -0.03375 -0.0689862 0.0403403 -0.0338 -0.0690007 0.0386798 -0.03385 -0.0690002 0.0368683 -0.0339 -0.0689868 0.0349214 -0.03395 -0.0689625 0.0328553 -0.034 -0.0689288 0.0306865 -0.03405 -0.0688872 0.0284313 -0.0341 -0.0688387 0.0261053 -0.03415 -0.0687842 0.0237234 -0.0342 -0.0687246 0.0212991 -0.03425 -0.0686606 0.0188445 -0.0343 -0.0685926 0.0163707 -0.03435 -0.0685213 0.0138871 -0.0344 -0.068447 0.0114018 -0.03445 -0.0683701 0.00892174 -0.0345 -0.068291 0.00645248 -0.03455 -0.0682097 0.00399851 -0.0346 -0.0681267 0.00156327 -0.03465 -0.0680421 -0.00085074 -0.0347 -0.067956 -0.00324191 -0.03475 -0.0678686 -0.00560937 -0.0348 -0.06778 -0.007953 -0.03485 -0.0676904 -0.0102734 -0.0349 -0.0675998 -0.0125719 -0.03495 -0.0675083 -0.0148505 -0.035 -0.0674159 -0.0171122 -0.03505 -0.0673229 -0.0193611 -0.0351 -0.0672291 -0.0216027 -0.03515 -0.0671347 -0.0238443 -0.0352 -0.0670397 -0.0260957 -0.03525 -0.0669441 -0.0283696 -0.0353 -0.066848 -0.030683 -0.03535 -0.0667513 -0.0330574 -0.0354 -0.0666543 -0.0355205 -0.03545 -0.0665567 -0.0381069 -0.0355 -0.0664588 -0.0408579 -0.03555 -0.0663605 -0.0438204 -0.0356 -0.0662618 -0.0470414 -0.03565 -0.0661627 -0.0505563 -0.0357 -0.0660634 -0.0543662 -0.03575 -0.0659636 -0.0584039 -0.0358 -0.0658636 -0.0624988 -0.03585 -0.0657634 -0.0663729 -0.0359 -0.0656628 -0.0697117 -0.03595 -0.065562 -0.0722976 -0.036 -0.0654609 -0.0741039 -0.03605 -0.0653596 -0.075264 -0.0361 -0.0652581 -0.0759676 -0.03615 -0.0651564 -0.0763809 -0.0362 -0.0650545 -0.0766205 -0.03625 -0.0649524 -0.0767595 -0.0363 -0.0648501 -0.0768406 -0.03635 -0.0647477 -0.0768885 -0.0364 -0.0646451 -0.076917 -0.03645 -0.0645424 -0.0769341 -0.0365 -0.0644396 -0.0769444 -0.03655 -0.0643367 -0.0769506 -0.0366 -0.0642336 -0.0769542 -0.03665 -0.0641305 -0.0769562 -0.0367 -0.0640272 -0.0769572 -0.03675 -0.0639239 -0.0769575 -0.0368 -0.0638205 -0.0769574 -0.03685 -0.0637171 -0.0769569 -0.0369 -0.0636136 -0.0769563 -0.03695 -0.0635101 -0.0769555 -0.037 -0.0634065 -0.0769546 -0.03705 -0.063303 -0.0769536 -0.0371 -0.0631994 -0.0769525 -0.03715 -0.0630958 -0.0769514 -0.0372 -0.0629922 -0.0769502 -0.03725 -0.0628886 -0.076949 -0.0373 -0.062785 -0.0769477 -0.03735 -0.0626815 -0.0769464 -0.0374 -0.062578 -0.0769451 -0.03745 -0.0624745 -0.0769437 -0.0375 -0.0623711 -0.0769423 -0.03755 -0.0622677 -0.0769409 -0.0376 -0.0621644 -0.0769394 -0.03765 -0.0620612 -0.0769379 -0.0377 -0.061958 -0.0769364 -0.03775 -0.061855 -0.0769348 -0.0378 -0.061752 -0.0769332 -0.03785 -0.061649 -0.0769316 -0.0379 -0.0615462 -0.0769299 -0.03795 -0.0614435 -0.0769282 -0.038 -0.0613409 -0.0769265 -0.03805 -0.0612384 -0.0769247 -0.0381 -0.061136 -0.0769229 -0.03815 -0.0610338 -0.076921 -0.0382 -0.0609316 -0.0769191 -0.03825 -0.0608296 -0.0769172 -0.0383 -0.0607277 -0.0769152 -0.03835 -0.060626 -0.0769131 -0.0384 -0.0605244 -0.0769111 -0.03845 -0.0604229 -0.076909 -0.0385 -0.0603216 -0.0769068 -0.03855 -0.0602204 -0.0769046 -0.0386 -0.0601193 -0.0769023 -0.03865 -0.0600184 -0.0769 -0.0387 -0.0599176 -0.0768977 -0.03875 -0.059817 -0.0768953 -0.0388 -0.0597166 -0.0768928 -0.03885 -0.0596162 -0.0768903 -0.0389 -0.0595161 -0.0768878 -0.03895 -0.059416 -0.0768852 -0.039 -0.0593162 -0.0768825 -0.03905 -0.0592164 -0.0768798 -0.0391 -0.0591168 -0.076877 -0.03915 -0.0590174 -0.0768741 -0.0392 -0.0589181 -0.0768712 -0.03925 -0.0588189 -0.0768683 -0.0393 -0.0587199 -0.0768652 -0.03935 -0.0586209 -0.0768621 -0.0394 -0.0585222 -0.076859 -0.03945 -0.0584235 -0.0768557 -0.0395 -0.058325 -0.0768524 -0.03955 -0.0582266 -0.0768491 -0.0396 -0.0581283 -0.0768456 -0.03965 -0.0580301 -0.0768421 -0.0397 -0.057932 -0.0768385 -0.03975 -0.057834 -0.0768348 -0.0398 -0.0577361 -0.0768311 -0.03985 -0.0576382 -0.0768272 -0.0399 -0.0575405 -0.0768233 -0.03995 -0.0574428 -0.0768193 -0.04 -0.0573452 -0.0768152 -0.04005 -0.0572476 -0.076811 -0.0401 -0.0571501 -0.0768068 -0.04015 -0.0570526 -0.0768024 -0.0402 -0.0569551 -0.0767979 -0.04025 -0.0568577 -0.0767934 -0.0403 -0.0567602 -0.0767887 -0.04035 -0.0566628 -0.076784 -0.0404 -0.0565653 -0.0767791 -0.04045 -0.0564678 -0.0767741 -0.0405 -0.0563703 -0.0767691 -0.04055 -0.0562727 -0.0767639 -0.0406 -0.056175 -0.0767586 -0.04065 -0.0560772 -0.0767532 -0.0407 -0.0559794 -0.0767477 -0.04075 -0.0558814 -0.0767421 -0.0408 -0.0557833 -0.0767363 -0.04085 -0.055685 -0.0767304 -0.0409 -0.0555866 -0.0767245 -0.04095 -0.0554879 -0.0767183 -0.041 -0.0553891 -0.0767121 -0.04105 -0.05529 -0.0767057 -0.0411 -0.0551907 -0.0766992 -0.04115 -0.0550911 -0.0766926 -0.0412 -0.0549912 -0.0766858 -0.04125 -0.054891 -0.0766789 -0.0413 -0.0547904 -0.0766718 -0.04135 -0.0546894 -0.0766646 -0.0414 -0.054588 -0.0766573 -0.04145 -0.0544862 -0.0766498 -0.0415 -0.0543839 -0.0766422 -0.04155 -0.0542811 -0.0766344 -0.0416 -0.0541777 -0.0766264 -0.04165 -0.0540738 -0.0766184 -0.0417 -0.0539692 -0.0766101 -0.04175 -0.0538639 -0.0766017 -0.0418 -0.0537579 -0.0765931 -0.04185 -0.0536511 -0.0765844 -0.0419 -0.0535436 -0.0765755 -0.04195 -0.0534351 -0.0765665 -0.042 -0.0533257 -0.0765573 -0.04205 -0.0532153 -0.0765479 -0.0421 -0.0531038 -0.0765383 -0.04215 -0.0529912 -0.0765286 -0.0422 -0.0528773 -0.0765187 -0.04225 -0.0527621 -0.0765086 -0.0423 -0.0526456 -0.0764983 -0.04235 -0.0525276 -0.0764879 -0.0424 -0.0524079 -0.0764773 -0.04245 -0.0522866 -0.0764665 -0.0425 -0.0521634 -0.0764555 -0.04255 -0.0520383 -0.0764444 -0.0426 -0.0519111 -0.076433 -0.04265 -0.0517817 -0.0764215 -0.0427 -0.0516499 -0.0764097 -0.04275 -0.0515154 -0.0763978 -0.0428 -0.0513782 -0.0763857 -0.04285 -0.051238 -0.0763734 -0.0429 -0.0510946 -0.0763609 -0.04295 -0.0509477 -0.0763483 -0.043 -0.050797 -0.0763354 -0.04305 -0.0506423 -0.0763223 -0.0431 -0.0504831 -0.076309 -0.04315 -0.0503192 -0.0762955 -0.0432 -0.05015 -0.0762819 -0.04325 -0.0499752 -0.076268 -0.0433 -0.0497942 -0.0762539 -0.04335 -0.0496065 -0.0762396 -0.0434 -0.0494113 -0.0762251 -0.04345 -0.049208 -0.0762105 -0.0435 -0.0489957 -0.0761956 -0.04355 -0.0487736 -0.0761805 -0.0436 -0.0485405 -0.0761652 -0.04365 -0.0482953 -0.0761496 -0.0437 -0.0480366 -0.0761339 -0.04375 -0.0477628 -0.076118 -0.0438 -0.0474722 -0.0761018 -0.04385 -0.0471625 -0.0760855 -0.0439 -0.0468315 -0.0760689 -0.04395 -0.0464762 -0.0760521 -0.044 -0.0460933 -0.0760351 -0.04405 -0.0456788 -0.0760179 -0.0441 -0.0452282 -0.0760005 -0.04415 -0.0447357 -0.0759829 -0.0442 -0.0441947 -0.075965 -0.04425 -0.0435971 -0.0759469 -0.0443 -0.0429331 -0.0759286 -0.04435 -0.0421906 -0.0759101 -0.0444 -0.0413548 -0.0758913 -0.04445 -0.0404075 -0.0758724 -0.0445 -0.0393258 -0.0758532 -0.04455 -0.0380812 -0.0758338 -0.0446 -0.0366384 -0.0758141 -0.04465 -0.0349528 -0.0757942 -0.0447 -0.0329697 -0.0757741 -0.04475 -0.0306218 -0.0757538 -0.0448 -0.02783 -0.0757332 -0.04485 -0.0245055 -0.0757123 -0.0449 -0.0205602 -0.0756913 -0.04495 -0.0159269 -0.0756699 -0.045 -0.0105984 -0.0756484 -0.04505 -0.00468155 -0.0756265 -0.0451 0.00155027 -0.0756044 -0.04515 0.00765183 -0.075582 -0.0452 0.0130914 -0.0755594 -0.04525 0.0174099 -0.0755364 -0.0453 0.0203597 -0.0755132 -0.04535 0.0219375 -0.0754897 -0.0454 0.0223153 -0.0754658 -0.04545 0.0217395 -0.0754416 -0.0455 0.0204548 -0.0754171 -0.04555 0.0186675 -0.0753922 -0.0456 0.0165372 -0.0753668 -0.04565 0.0141817 -0.0753411 -0.0457 0.0116861 -0.0753148 -0.04575 0.00911171 -0.0752881 -0.0458 0.00650213 -0.0752607 -0.04585 0.00388865 -0.0752327 -0.0459 0.0012936 -0.0752039 -0.04595 -0.00126729 -0.0751742 -0.046 -0.00378304 -0.0751433 -0.04605 -0.00624626 -0.0751112 -0.0461 -0.00865222 -0.0750775 -0.04615 -0.0109982 -0.0750417 -0.0462 -0.013283 -0.0750035 -0.04625 -0.0155067 -0.0749623 -0.0463 -0.0176701 -0.0749171 -0.04635 -0.019775 -0.0748672 -0.0464 -0.0218238 -0.0748111 -0.04645 -0.0238198 -0.0747475 -0.0465 -0.0257666 -0.0746742 -0.04655 -0.0276688 -0.0745889 -0.0466 -0.0295317 -0.0744886 -0.04665 -0.031361 -0.0743695 -0.0467 -0.0331635 -0.0742269 -0.04675 -0.0349463 -0.0740549 -0.0468 -0.0367172 -0.0738464 -0.04685 -0.0384841 -0.0735924 -0.0469 -0.0402549 -0.073282 -0.04695 -0.0420372 -0.0729014 -0.047 -0.0438372 -0.0724338 -0.04705 -0.0456594 -0.0718584 -0.0471 -0.0475053 -0.0711493 -0.04715 -0.0493722 -0.0702748 -0.0472 -0.0512522 -0.0691952 -0.04725 -0.053131 -0.0678619 -0.0473 -0.0549875 -0.0662138 -0.04735 -0.0567948 -0.0641751 -0.0474 -0.0585217 -0.0616499 -0.04745 -0.0601369 -0.0585153 -0.0475 -0.0616129 -0.0546101 -0.04755 -0.0629298 -0.0497126 -0.0476 -0.0640781 -0.0434991 -0.04765 -0.0650587 -0.0354611 -0.0477 -0.0658811 -0.0247683 -0.04775 -0.0665607 -0.0102255 -0.0478 -0.0671157 0.00873768 -0.04785 -0.0675646 0.0285001 -0.0479 -0.0679247 0.041245 -0.04795 -0.068211 0.0455663 -0.048 -0.0684365 0.0461435 -0.04805 -0.0686118 0.0457172 -0.0481 -0.0687456 0.0449529 -0.04815 -0.068845 0.0439654 -0.0482 -0.0689158 0.0427796 -0.04825 -0.0689626 0.041408 -0.0483 -0.0689892 0.0398622 -0.04835 -0.068999 0.0381552 -0.0484 -0.0689943 0.0363018 -0.04845 -0.0689774 0.0343176 -0.0485 -0.0689501 0.0322191 -0.04855 -0.0689139 0.0300228 -0.0486 -0.0688701 0.0277448 -0.04865 -0.0688197 0.0254006 -0.0487 -0.0687636 0.0230046 -0.04875 -0.0687026 0.0205699 -0.0488 -0.0686373 0.0181084 -0.04885 -0.0685683 0.0156306 -0.0489 -0.0684961 0.0131455 -0.04895 -0.068421 0.010661 -0.049 -0.0683434 0.00818354 -0.04905 -0.0682635 0.0057183 -0.0491 -0.0681818 0.00326949 -0.04915 -0.0680982 0.00084025 -0.0492 -0.0680131 -0.00156719 -0.04925 -0.0679266 -0.00395143 -0.0493 -0.0678389 -0.00631185 -0.04935 -0.0677499 -0.00864855 -0.0494 -0.06766 -0.0109623 -0.04945 -0.0675691 -0.0132547 -0.0495 -0.0674773 -0.0155279 -0.04955 -0.0673848 -0.0177854 -0.0496 -0.0672915 -0.0200316 -0.04965 -0.0671975 -0.0222724 -0.0497 -0.0671029 -0.0245158 -0.04975 -0.0670077 -0.0267725 -0.0498 -0.0669119 -0.0290563 -0.04985 -0.0668157 -0.0313854 -0.0499 -0.0667189 -0.0337832 -0.04995 -0.0666217 -0.0362793 -0.05 -0.066524 -0.0389103 -0.05005 -0.066426 -0.0417195 -0.0501 -0.0663275 -0.0447547 -0.05015 -0.0662287 -0.0480609 -0.0502 -0.0661296 -0.0516663 -0.05025 -0.0660301 -0.0555555 -0.0503 -0.0659303 -0.0596335 -0.05035 -0.0658302 -0.0636952 -0.0504 -0.0657298 -0.0674405 -0.05045 -0.0656292 -0.070569 -0.0505 -0.0655283 -0.0729156 -0.05055 -0.0654271 -0.07451 -0.0506 -0.0653258 -0.0755138 -0.05065 -0.0652242 -0.0761153 -0.0507 -0.0651224 -0.0764666 -0.05075 -0.0650205 -0.0766702 -0.0508 -0.0649183 -0.0767884 -0.05085 -0.064816 -0.0768576 -0.0509 -0.0647136 -0.0768985 -0.05095 -0.064611 -0.076923 -0.051 -0.0645082 -0.0769377 -0.05105 -0.0644053 -0.0769466 -0.0511 -0.0643024 -0.0769519 -0.05115 -0.0641993 -0.076955 -0.0512 -0.0640961 -0.0769566 -0.05125 -0.0639929 -0.0769574 -0.0513 -0.0638895 -0.0769575 -0.05135 -0.0637861 -0.0769573 -0.0514 -0.0636827 -0.0769568 -0.05145 -0.0635792 -0.0769561 -0.0515 -0.0634757 -0.0769552 -0.05155 -0.0633721 -0.0769543 -0.0516 -0.0632685 -0.0769533 -0.05165 -0.063165 -0.0769522 -0.0517 -0.0630614 -0.076951 -0.05175 -0.0629578 -0.0769498 -0.0518 -0.0628542 -0.0769486 -0.05185 -0.0627506 -0.0769473 -0.0519 -0.0626471 -0.076946 -0.05195 -0.0625436 -0.0769447 -0.052 -0.0624402 -0.0769433 -0.05205 -0.0623368 -0.0769419 -0.0521 -0.0622335 -0.0769405 -0.05215 -0.0621302 -0.076939 -0.0522 -0.062027 -0.0769375 -0.05225 -0.0619238 -0.0769359 -0.0523 -0.0618208 -0.0769344 -0.05235 -0.0617178 -0.0769328 -0.0524 -0.061615 -0.0769311 -0.05245 -0.0615122 -0.0769294 -0.0525 -0.0614095 -0.0769277 -0.05255 -0.061307 -0.0769259 -0.0526 -0.0612045 -0.0769241 -0.05265 -0.0611022 -0.0769223 -0.0527 -0.061 -0.0769204 -0.05275 -0.0608979 -0.0769185 -0.0528 -0.0607959 -0.0769166 -0.05285 -0.0606941 -0.0769146 -0.0529 -0.0605924 -0.0769125 -0.05295 -0.0604908 -0.0769104 -0.053 -0.0603894 -0.0769083 -0.05305 -0.0602881 -0.0769061 -0.0531 -0.060187 -0.0769039 -0.05315 -0.060086 -0.0769017 -0.0532 -0.0599851 -0.0768993 -0.05325 -0.0598844 -0.076897 -0.0533 -0.0597838 -0.0768946 -0.05335 -0.0596834 -0.0768921 -0.0534 -0.0595832 -0.0768896 -0.05345 -0.059483 -0.076887 -0.0535 -0.0593831 -0.0768844 -0.05355 -0.0592832 -0.0768817 -0.0536 -0.0591836 -0.0768789 -0.05365 -0.059084 -0.0768761 -0.0537 -0.0589846 -0.0768733 -0.05375 -0.0588854 -0.0768703 -0.0538 -0.0587862 -0.0768674 -0.05385 -0.0586873 -0.0768643 -0.0539 -0.0585884 -0.0768612 -0.05395 -0.0584897 -0.076858 -0.054 -0.0583911 -0.0768547 -0.05405 -0.0582926 -0.0768514 -0.0541 -0.0581942 -0.076848 -0.05415 -0.058096 -0.0768446 -0.0542 -0.0579978 -0.076841 -0.05425 -0.0578997 -0.0768374 -0.0543 -0.0578018 -0.0768337 -0.05435 -0.0577039 -0.0768299 -0.0544 -0.0576061 -0.076826 -0.05445 -0.0575084 -0.0768221 -0.0545 -0.0574108 -0.0768181 -0.05455 -0.0573132 -0.076814 -0.0546 -0.0572156 -0.0768097 -0.05465 -0.0571181 -0.0768054 -0.0547 -0.0570206 -0.076801 -0.05475 -0.0569232 -0.0767966 -0.0548 -0.0568258 -0.076792 -0.05485 -0.0567283 -0.0767873 -0.0549 -0.0566309 -0.0767825 -0.05495 -0.0565334 -0.0767776 -0.055 -0.0564359 -0.0767726 -0.05505 -0.0563383 -0.0767675 -0.0551 -0.0562407 -0.0767623 -0.05515 -0.056143 -0.076757 -0.0552 -0.0560452 -0.0767516 -0.05525 -0.0559474 -0.076746 -0.0553 -0.0558493 -0.0767403 -0.05535 -0.0557512 -0.0767345 -0.0554 -0.0556529 -0.0767286 -0.05545 -0.0555544 -0.0767226 -0.0555 -0.0554557 -0.0767164 -0.05555 -0.0553568 -0.0767102 -0.0556 -0.0552577 -0.0767037 -0.05565 -0.0551583 -0.0766972 -0.0557 -0.0550586 -0.0766905 -0.05575 -0.0549586 -0.0766837 -0.0558 -0.0548583 -0.0766767 -0.05585 -0.0547576 -0.0766696 -0.0559 -0.0546565 -0.0766624 -0.05595 -0.054555 -0.076655 -0.056 -0.054453 -0.0766475 -0.05605 -0.0543506 -0.0766398 -0.0561 -0.0542476 -0.076632 -0.05615 -0.0541441 -0.076624 -0.0562 -0.0540399 -0.0766159 -0.05625 -0.0539351 -0.0766076 -0.0563 -0.0538297 -0.0765991 -0.05635 -0.0537234 -0.0765905 -0.0564 -0.0536164 -0.0765817 -0.05645 -0.0535086 -0.0765728 -0.0565 -0.0533998 -0.0765637 -0.05655 -0.0532901 -0.0765544 -0.0566 -0.0531794 -0.076545 -0.05665 -0.0530676 -0.0765354 -0.0567 -0.0529546 -0.0765256 -0.05675 -0.0528403 -0.0765156 -0.0568 -0.0527248 -0.0765055 -0.05685 -0.0526078 -0.0764952 -0.0569 -0.0524893 -0.0764847 -0.05695 -0.0523691 -0.076474 -0.057 -0.0522472 -0.0764632 -0.05705 -0.0521235 -0.0764521 -0.0571 -0.0519978 -0.0764409 -0.05715 -0.0518699 -0.0764295 -0.0572 -0.0517397 -0.0764179 -0.05725 -0.0516071 -0.0764061 -0.0573 -0.0514718 -0.0763942 -0.05735 -0.0513337 -0.076382 -0.0574 -0.0511926 -0.0763696 -0.05745 -0.0510481 -0.0763571 -0.0575 -0.0509 -0.0763443 -0.05755 -0.0507481 -0.0763314 -0.0576 -0.0505921 -0.0763182 -0.05765 -0.0504315 -0.0763049 -0.0577 -0.050266 -0.0762914 -0.05775 -0.0500951 -0.0762776 -0.0578 -0.0499184 -0.0762637 -0.05785 -0.0497354 -0.0762496 -0.0579 -0.0495454 -0.0762352 -0.05795 -0.0493478 -0.0762207 -0.058 -0.0491418 -0.0762059 -0.05805 -0.0489266 -0.076191 -0.0581 -0.0487012 -0.0761758 -0.05815 -0.0484645 -0.0761604 -0.0582 -0.0482152 -0.0761448 -0.05825 -0.047952 -0.0761291 -0.0583 -0.0476732 -0.0761131 -0.05835 -0.0473768 -0.0760968 -0.0584 -0.0470608 -0.0760804 -0.05845 -0.0467225 -0.0760638 -0.0585 -0.046359 -0.0760469 -0.05855 -0.0459668 -0.0760299 -0.0586 -0.0455416 -0.0760126 -0.05865 -0.0450786 -0.0759951 -0.0587 -0.0445718 -0.0759774 -0.05875 -0.0440141 -0.0759595 -0.0588 -0.043397 -0.0759413 -0.05885 -0.04271 -0.075923 -0.0589 -0.0419402 -0.0759044 -0.05895 -0.0410718 -0.0758855 -0.059 -0.0400853 -0.0758665 -0.05905 -0.0389563 -0.0758472 -0.0591 -0.0376542 -0.0758278 -0.05915 -0.0361411 -0.075808 -0.0592 -0.0343694 -0.0757881 -0.05925 -0.0322805 -0.0757679 -0.0593 -0.0298036 -0.0757475 -0.05935 -0.0268559 -0.0757268 -0.0594 -0.0233475 -0.0757059 -0.05945 -0.0191937 -0.0756847 -0.0595 -0.0143412 -0.0756633 -0.05955 -0.00881185 -0.0756417 -0.0596 -0.00275983 -0.0756197 -0.05965 0.00348499 -0.0755976 -0.0597 0.00943683 -0.0755751 -0.05975 0.0145683 -0.0755524 -0.0598 0.0184752 -0.0755293 -0.05985 0.0209882 -0.075506 -0.0599 0.0221688 -0.0754824 -0.05995 0.0222226 -0.0754584 -0.06 0.0214015 -0.0754341 -0.06005 0.0199406 -0.0754095 -0.0601 0.0180317 -0.0753844 -0.06015 0.0158204 -0.075359 -0.0602 0.0134135 -0.075333 -0.06025 0.0108878 -0.0753067 -0.0603 0.00829844 -0.0752797 -0.06035 0.00568477 -0.0752522 -0.0604 0.00307499 -0.0752239 -0.06045 0.000489136 -0.0751948 -0.0605 -0.00205868 -0.0751648 -0.06055 -0.00455871 -0.0751336 -0.0606 -0.00700449 -0.075101 -0.06065 -0.00939198 -0.0750667 -0.0607 -0.011719 -0.0750302 -0.06075 -0.0139847 -0.0749911 -0.0608 -0.0161894 -0.0749488 -0.06085 -0.0183343 -0.0749022 -0.0609 -0.0204214 -0.0748505 -0.06095 -0.0224534 -0.0747923 -0.061 -0.0244335 -0.0747259 -0.06105 -0.0263659 -0.0746492 -0.0611 -0.0282552 -0.0745596 -0.06115 -0.0301069 -0.0744539 -0.0612 -0.0319271 -0.074328 -0.06125 -0.0337226 -0.0741769 -0.0613 -0.0355009 -0.0739944 -0.06135 -0.0372696 -0.0737728 -0.0614 -0.0390369 -0.0735026 -0.06145 -0.0408105 -0.0731719 -0.0615 -0.0425977 -0.0727663 -0.06155 -0.0444042 -0.0722676 -0.0616 -0.0462338 -0.0716536 -0.06165 -0.0480866 -0.0708968 -0.0617 -0.0499587 -0.0699631 -0.06175 -0.0518401 -0.0688104 -0.0618 -0.0537144 -0.0673863 -0.06185 -0.0555586 -0.0656258 -0.0619 -0.0573441 -0.0634472 -0.06195 -0.0590393 -0.0607471 -0.062 -0.0606137 -0.0573925 -0.06205 -0.0620416 -0.0532062 -0.0621 -0.0633063 -0.0479408 -0.06215 -0.0644016 -0.0412265 -0.0622 -0.0653314 -0.0324713 -0.06225 -0.0661074 -0.020719 -0.0623 -0.0667461 -0.00476111 -0.06235 -0.067266 0.0151489 -0.0624 -0.0676855 0.033499 -0.06245 -0.068021 0.0432883 -0.0625 -0.0682871 0.0459542 -0.06255 -0.0684959 0.0460655 -0.0626 -0.0686574 0.0455065 -0.06265 -0.0687798 0.0446679 -0.0627 -0.0688697 0.0436171 -0.06275 -0.0689325 0.0423723 -0.0628 -0.0689727 0.0409451 -0.06285 -0.0689937 0.0393477 -0.0629 -0.0689987 0.0375936 -0.06295 -0.06899 0.0356977 -0.063 -0.0689697 0.0336762 -0.06305 -0.0689395 0.0315455 -0.0631 -0.0689008 0.0293221 -0.06315 -0.0688549 0.0270219 -0.0632 -0.0688026 0.0246601 -0.06325 -0.0687449 0.0222506 -0.0633 -0.0686825 0.0198064 -0.06335 -0.068616 0.0173387 -0.0634 -0.0685459 0.0148578 -0.06345 -0.0684728 0.0123721 -0.0635 -0.0683968 0.00988915 -0.06355 -0.0683185 0.00741494 -0.0636 -0.0682381 0.00495441 -0.06365 -0.0681557 0.00251139 -0.0637 -0.0680717 8.87274e-05 -0.06375 -0.0679861 -0.00231161 -0.0638 -0.0678992 -0.00468848 -0.06385 -0.0678111 -0.00704148 -0.0639 -0.0677218 -0.00937093 -0.06395 -0.0676316 -0.0116778 -0.064 -0.0675404 -0.013964 -0.06405 -0.0674484 -0.0162319 -0.0641 -0.0673556 -0.0184853 -0.06415 -0.0672621 -0.0207291 -0.0642 -0.0671679 -0.0229698 -0.06425 -0.0670731 -0.0252161 -0.0643 -0.0669777 -0.0274795 -0.06435 -0.0668818 -0.0297753 -0.0644 -0.0667854 -0.032123 -0.06445 -0.0666885 -0.0345479 -0.0645 -0.0665911 -0.0370817 -0.06455 -0.0664933 -0.0397633 -0.0646 -0.0663951 -0.0426376 -0.06465 -0.0662966 -0.0457527 -0.0647 -0.0661977 -0.0491504 -0.06475 -0.0660984 -0.0528487 -0.0648 -0.0659988 -0.0568116 -0.06485 -0.0658989 -0.0609119 -0.0649 -0.0657987 -0.06491 -0.06495 -0.0656983 -0.0684917 -0.065 -0.0655976 -0.0713854 -0.06505 -0.0654966 -0.0734864 -0.0651 -0.0653954 -0.0748765 -0.06515 -0.065294 -0.0757359 -0.0652 -0.0651923 -0.0762457 -0.06525 -0.0650905 -0.0765422 -0.0653 -0.0649885 -0.076714 -0.06535 -0.0648863 -0.076814 -0.0654 -0.0647839 -0.0768727 -0.06545 -0.0646814 -0.0769075 -0.0655 -0.0645787 -0.0769284 -0.06555 -0.064476 -0.076941 -0.0656 -0.0643731 -0.0769486 -0.06565 -0.0642701 -0.076953 -0.0657 -0.0641669 -0.0769556 -0.06575 -0.0640637 -0.0769569 -0.0658 -0.0639605 -0.0769575 -0.06585 -0.0638571 -0.0769575 -0.0659 -0.0637537 -0.0769571 -0.06595 -0.0636502 -0.0769566 -0.066 -0.0635467 -0.0769558 -0.06605 -0.0634432 -0.0769549 -0.0661 -0.0633396 -0.076954 -0.06615 -0.0632361 -0.0769529 -0.0662 -0.0631325 -0.0769518 -0.06625 -0.0630289 -0.0769507 -0.0663 -0.0629253 -0.0769495 -0.06635 -0.0628217 -0.0769482 -0.0664 -0.0627182 -0.0769469 -0.06645 -0.0626147 -0.0769456 -0.0665 -0.0625112 -0.0769443 -0.06655 -0.0624078 -0.0769429 -0.0666 -0.0623044 -0.0769415 -0.06665 -0.0622011 -0.07694 -0.0667 -0.0620978 -0.0769385 -0.06675 -0.0619946 -0.076937 -0.0668 -0.0618915 -0.0769355 -0.06685 -0.0617885 -0.0769339 -0.0669 -0.0616856 -0.0769322 -0.06695 -0.0615827 -0.0769306 -0.067 -0.06148 -0.0769289 -0.06705 -0.0613774 -0.0769272 -0.0671 -0.0612748 -0.0769254 -0.06715 -0.0611724 -0.0769236 -0.0672 -0.0610701 -0.0769217 -0.06725 -0.0609679 -0.0769198 -0.0673 -0.0608659 -0.0769179 -0.06735 -0.060764 -0.0769159 -0.0674 -0.0606622 -0.0769139 -0.06745 -0.0605605 -0.0769119 -0.0675 -0.060459 -0.0769098 -0.06755 -0.0603576 -0.0769076 -0.0676 -0.0602564 -0.0769055 -0.06765 -0.0601553 -0.0769032 -0.0677 -0.0600543 -0.0769009 -0.06775 -0.0599535 -0.0768986 -0.0678 -0.0598529 -0.0768962 -0.06785 -0.0597523 -0.0768938 -0.0679 -0.059652 -0.0768913 -0.06795 -0.0595518 -0.0768888 -0.068 -0.0594517 -0.0768862 -0.06805 -0.0593518 -0.0768835 -0.0681 -0.059252 -0.0768808 -0.06815 -0.0591523 -0.0768781 -0.0682 -0.0590529 -0.0768752 -0.06825 -0.0589535 -0.0768724 -0.0683 -0.0588543 -0.0768694 -0.06835 -0.0587552 -0.0768664 -0.0684 -0.0586563 -0.0768633 -0.06845 -0.0585575 -0.0768602 -0.0685 -0.0584588 -0.076857 -0.06855 -0.0583602 -0.0768537 -0.0686 -0.0582618 -0.0768504 -0.06865 -0.0581634 -0.076847 -0.0687 -0.0580652 -0.0768435 -0.06875 -0.0579671 -0.0768399 -0.0688 -0.057869 -0.0768362 -0.06885 -0.0577711 -0.0768325 -0.0689 -0.0576733 -0.0768287 -0.06895 -0.0575755 -0.0768248 -0.069 -0.0574778 -0.0768209 -0.06905 -0.0573802 -0.0768168 -0.0691 -0.0572826 -0.0768126 -0.06915 -0.0571851 -0.0768084 -0.0692 -0.0570876 -0.0768041 -0.06925 -0.0569901 -0.0767997 -0.0693 -0.0568927 -0.0767951 -0.06935 -0.0567952 -0.0767905 -0.0694 -0.0566978 -0.0767858 -0.06945 -0.0566003 -0.076781 -0.0695 -0.0565029 -0.0767761 -0.06955 -0.0564053 -0.076771 -0.0696 -0.0563078 -0.0767659 -0.06965 -0.0562101 -0.0767607 -0.0697 -0.0561124 -0.0767553 -0.06975 -0.0560146 -0.0767498 -0.0698 -0.0559167 -0.0767443 -0.06985 -0.0558186 -0.0767385 -0.0699 -0.0557204 -0.0767327 -0.06995 -0.0556221 -0.0767268 -0.07 -0.0555235 -0.0767207 -0.07005 -0.0554248 -0.0767145 -0.0701 -0.0553258 -0.0767082 -0.07015 -0.0552266 -0.0767017 -0.0702 -0.0551271 -0.0766951 -0.07025 -0.0550273 -0.0766884 -0.0703 -0.0549272 -0.0766815 -0.07035 -0.0548268 -0.0766745 -0.0704 -0.054726 -0.0766674 -0.07045 -0.0546248 -0.0766601 -0.0705 -0.0545231 -0.0766527 -0.07055 -0.054421 -0.0766451 -0.0706 -0.0543184 -0.0766374 -0.07065 -0.0542153 -0.0766295 -0.0707 -0.0541115 -0.0766215 -0.07075 -0.0540072 -0.0766133 -0.0708 -0.0539022 -0.0766049 -0.07085 -0.0537965 -0.0765964 -0.0709 -0.05369 -0.0765878 -0.07095 -0.0535828 -0.076579 -0.071 -0.0534747 -0.07657 -0.07105 -0.0533656 -0.0765608 -0.0711 -0.0532556 -0.0765515 -0.07115 -0.0531445 -0.076542 -0.0712 -0.0530323 -0.0765323 -0.07125 -0.052919 -0.0765225 -0.0713 -0.0528043 -0.0765125 -0.07135 -0.0526883 -0.0765023 -0.0714 -0.0525709 -0.0764919 -0.07145 -0.0524519 -0.0764814 -0.0715 -0.0523312 -0.0764707 -0.07155 -0.0522087 -0.0764597 -0.0716 -0.0520844 -0.0764487 -0.07165 -0.051958 -0.0764374 -0.0717 -0.0518294 -0.0764259 -0.07175 -0.0516985 -0.0764143 -0.0718 -0.0515651 -0.0764024 -0.07185 -0.051429 -0.0763904 -0.0719 -0.0512899 -0.0763782 -0.07195 -0.0511478 -0.0763657 -0.072 -0.0510022 -0.0763531 -0.07205 -0.050853 -0.0763403 -0.0721 -0.0506998 -0.0763273 -0.07215 -0.0505424 -0.0763141 -0.0722 -0.0503803 -0.0763007 -0.07225 -0.0502132 -0.0762871 -0.0723 -0.0500405 -0.0762733 -0.07235 -0.049862 -0.0762593 -0.0724 -0.0496768 -0.0762451 -0.07245 -0.0494845 -0.0762307 -0.0725 -0.0492844 -0.0762161 -0.07255 -0.0490756 -0.0762013 -0.0726 -0.0488573 -0.0761863 -0.07265 -0.0486285 -0.076171 -0.0727 -0.048388 -0.0761556 -0.07275 -0.0481346 -0.0761399 -0.0728 -0.0478667 -0.0761241 -0.07285 -0.0475826 -0.076108 -0.0729 -0.0472804 -0.0760917 -0.07295 -0.0469577 -0.0760753 -0.073 -0.0466119 -0.0760586 -0.07305 -0.0462398 -0.0760416 -0.0731 -0.0458378 -0.0760245 -0.07315 -0.0454013 -0.0760072 -0.0732 -0.0449253 -0.0759896 -0.07325 -0.0444035 -0.0759718 -0.0733 -0.0438283 -0.0759538 -0.07335 -0.0431906 -0.0759356 -0.0734 -0.0424792 -0.0759172 -0.07345 -0.0416805 -0.0758985 -0.0735 -0.0407776 -0.0758796 -0.07355 -0.0397495 -0.0758605 -0.0736 -0.0385701 -0.0758412 -0.07365 -0.0372066 -0.0758216 -0.0737 -0.0356184 -0.0758018 -0.07375 -0.0337546 -0.0757818 -0.0738 -0.0315529 -0.0757615 -0.07385 -0.0289384 -0.075741 -0.0739 -0.0258255 -0.0757203 -0.07395 -0.022124 -0.0756993 -0.074 -0.0177555 -0.0756781 -0.07405 -0.0126844 -0.0756566 -0.0741 -0.00696771 -0.0756349 -0.07415 -0.000811622 -0.0756129 -0.0742 0.0053989 -0.0755906 -0.07425 0.0111487 -0.075568 -0.0743 0.0159316 -0.0755452 -0.07435 0.0194098 -0.0755221 -0.0744 0.0214916 -0.0754987 -0.07445 0.0222946 -0.0754749 -0.0745 0.0220483 -0.0754509 -0.07455 0.0210041 -0.0754265 -0.0746 0.0193851 -0.0754017 -0.07465 0.0173682 -0.0753765 -0.0747 0.015086 -0.0753509 -0.07475 0.012635 -0.0753249 -0.0748 0.0100843 -0.0752983 -0.07485 0.00748372 -0.0752712 -0.0749 0.00486867 -0.0752434 -0.07495 0.00226452 -0.0752149 -0.075 -0.000310741 -0.0751856 -0.07505 -0.00284452 -0.0751552 -0.0751 -0.00532819 -0.0751236 -0.07515 -0.00775611 -0.0750905 -0.0752 -0.0101249 -0.0750555 -0.07525 -0.0124328 -0.0750183 -0.0753 -0.0146793 -0.0749783 -0.07535 -0.0168652 -0.0749347 -0.0754 -0.0189919 -0.0748867 -0.07545 -0.0210615 -0.0748331 -0.0755 -0.0230769 -0.0747726 -0.07555 -0.0250417 -0.0747032 -0.0756 -0.0269601 -0.0746228 -0.07565 -0.028837 -0.0745285 -0.0757 -0.0306782 -0.074417 -0.07575 -0.0324899 -0.0742838 -0.0758 -0.0342792 -0.0741237 -0.07585 -0.0360536 -0.0739299 -0.0759 -0.037821 -0.0736942 -0.07595 -0.0395895 -0.0734065 -0.076 -0.0413666 -0.0730542 -0.07605 -0.0431593 -0.0726216 -0.0761 -0.0449727 -0.0720896 -0.07615 -0.0468097 -0.0714342 -0.0762 -0.0486693 -0.0706263 -0.07625 -0.0505456 -0.0696292 -0.0763 -0.0524268 -0.068398 -0.07635 -0.0542945 -0.0668766 -0.0764 -0.0561236 -0.0649952 -0.07645 -0.0578844 -0.0626662 -0.0765 -0.059545 -0.0597779 -0.07655 -0.061076 -0.0561855 -0.0766 -0.0624543 -0.0516934 -0.07665 -0.0636663 -0.0460235 -0.0767 -0.0647092 -0.0387502 -0.07675 -0.0655894 -0.0291825 -0.0768 -0.0663206 -0.0162396 -0.07685 -0.0669202 0.00115205 -0.0769 -0.0674069 0.0214599 -0.07695 -0.0677985 0.0375921 -0.077 -0.0681109 0.0446316 -0.07705 -0.0683579 0.046123 -0.0771 -0.0685509 0.0459316 -0.07715 -0.0686994 0.0452696 -0.0772 -0.068811 0.0443616 -0.07725 -0.068892 0.0432489 -0.0773 -0.0689473 0.041946 -0.07735 -0.0689811 0.0404644 -0.0774 -0.0689969 0.0388165 -0.07745 -0.0689973 0.0370165 -0.0775 -0.0689848 0.0350797 -0.07755 -0.0689613 0.0330223 -0.0776 -0.0689283 0.0308609 -0.07765 -0.0688872 0.0286119 -0.0777 -0.0688392 0.0262909 -0.07775 -0.0687851 0.0239127 -0.0778 -0.0687259 0.0214911 -0.07785 -0.0686621 0.0190384 -0.0779 -0.0685945 0.0165656 -0.07795 -0.0685234 0.0140823 -0.078 -0.0684493 0.0115967 -0.07805 -0.0683726 0.0091159 -0.0781 -0.0682936 0.00664549 -0.07815 -0.0682125 0.00419005 -0.0782 -0.0681296 0.00175312 -0.07825 -0.0680451 -0.00066274 -0.0783 -0.0679591 -0.00305584 -0.07835 -0.0678718 -0.00542528 -0.0784 -0.0677833 -0.00777086 -0.07845 -0.0676937 -0.0100931 -0.0785 -0.0676032 -0.0123933 -0.07855 -0.0675118 -0.0146735 -0.0786 -0.0674195 -0.0169365 -0.07865 -0.0673265 -0.0191863 -0.0787 -0.0672327 -0.0214283 -0.07875 -0.0671384 -0.0236696 -0.0788 -0.0670434 -0.0259199 -0.07885 -0.0669478 -0.0281916 -0.0789 -0.0668517 -0.0305012 -0.07895 -0.0667552 -0.03287 -0.079 -0.0666581 -0.0353252 -0.07905 -0.0665606 -0.0379006 -0.0791 -0.0664627 -0.0406372 -0.07915 -0.0663644 -0.0435816 -0.0792 -0.0662657 -0.046781 -0.07925 -0.0661667 -0.0502724 -0.0793 -0.0660673 -0.0540607 -0.07935 -0.0659677 -0.0580853 -0.0794 -0.0658677 -0.0621845 -0.07945 -0.0657674 -0.0660873 -0.0795 -0.0656669 -0.0694774 -0.07955 -0.0655661 -0.0721254 -0.0796 -0.065465 -0.0739889 -0.07965 -0.0653637 -0.0751925 -0.0797 -0.0652622 -0.0759251 -0.07975 -0.0651605 -0.0763561 -0.0798 -0.0650586 -0.0766061 -0.07985 -0.0649566 -0.0767511 -0.0799 -0.0648543 -0.0768357 -0.07995 -0.0647519 -0.0768855 -0.08 -0.0646494 -0.0769152 -0.08005 -0.0645467 -0.076933 -0.0801 -0.0644439 -0.0769438 -0.08015 -0.0643409 -0.0769502 -0.0802 -0.0642379 -0.076954 -0.08025 -0.0641347 -0.0769561 -0.0803 -0.0640315 -0.0769572 -0.08035 -0.0639282 -0.0769575 -0.0804 -0.0638248 -0.0769574 -0.08045 -0.0637214 -0.076957 -0.0805 -0.0636179 -0.0769564 -0.08055 -0.0635144 -0.0769556 -0.0806 -0.0634109 -0.0769546 -0.08065 -0.0633073 -0.0769537 -0.0807 -0.0632037 -0.0769526 -0.08075 -0.0631001 -0.0769515 -0.0808 -0.0629965 -0.0769503 -0.08085 -0.062893 -0.0769491 -0.0809 -0.0627894 -0.0769478 -0.08095 -0.0626859 -0.0769465 -0.081 -0.0625824 -0.0769452 -0.08105 -0.0624789 -0.0769438 -0.0811 -0.0623755 -0.0769424 -0.08115 -0.0622721 -0.076941 -0.0812 -0.0621688 -0.0769396 -0.08125 -0.0620656 -0.0769381 -0.0813 -0.0619624 -0.0769365 -0.08135 -0.0618594 -0.076935 -0.0814 -0.0617564 -0.0769334 -0.08145 -0.0616535 -0.0769317 -0.0815 -0.0615506 -0.0769301 -0.08155 -0.0614479 -0.0769283 -0.0816 -0.0613453 -0.0769266 -0.08165 -0.0612428 -0.0769248 -0.0817 -0.0611405 -0.076923 -0.08175 -0.0610382 -0.0769211 -0.0818 -0.0609361 -0.0769192 -0.08185 -0.0608341 -0.0769173 -0.0819 -0.0607322 -0.0769153 -0.08195 -0.0606304 -0.0769133 -0.082 -0.0605288 -0.0769112 -0.08205 -0.0604273 -0.0769091 -0.0821 -0.060326 -0.076907 -0.08215 -0.0602248 -0.0769048 -0.0822 -0.0601237 -0.0769025 -0.08225 -0.0600228 -0.0769002 -0.0823 -0.0599221 -0.0768979 -0.08235 -0.0598215 -0.0768955 -0.0824 -0.059721 -0.076893 -0.08245 -0.0596207 -0.0768905 -0.0825 -0.0595205 -0.076888 -0.08255 -0.0594205 -0.0768854 -0.0826 -0.0593206 -0.0768827 -0.08265 -0.0592209 -0.07688 -0.0827 -0.0591213 -0.0768772 -0.08275 -0.0590218 -0.0768744 -0.0828 -0.0589225 -0.0768715 -0.08285 -0.0588233 -0.0768685 -0.0829 -0.0587243 -0.0768655 -0.08295 -0.0586254 -0.0768624 -0.083 -0.0585266 -0.0768592 -0.08305 -0.058428 -0.076856 -0.0831 -0.0583295 -0.0768527 -0.08315 -0.058231 -0.0768493 -0.0832 -0.0581327 -0.0768459 -0.08325 -0.0580345 -0.0768424 -0.0833 -0.0579365 -0.0768388 -0.08335 -0.0578385 -0.0768351 -0.0834 -0.0577406 -0.0768313 -0.08345 -0.0576427 -0.0768275 -0.0835 -0.057545 -0.0768236 -0.08355 -0.0574473 -0.0768196 -0.0836 -0.0573497 -0.0768155 -0.08365 -0.0572521 -0.0768113 -0.0837 -0.0571546 -0.0768071 -0.08375 -0.0570571 -0.0768027 -0.0838 -0.0569597 -0.0767983 -0.08385 -0.0568623 -0.0767937 -0.0839 -0.0567648 -0.0767891 -0.08395 -0.0566674 -0.0767843 -0.084 -0.0565699 -0.0767795 -0.08405 -0.0564724 -0.0767745 -0.0841 -0.0563749 -0.0767695 -0.08415 -0.0562773 -0.0767643 -0.0842 -0.0561796 -0.076759 -0.08425 -0.0560819 -0.0767536 -0.0843 -0.055984 -0.0767481 -0.08435 -0.0558861 -0.0767425 -0.0844 -0.055788 -0.0767367 -0.08445 -0.0556897 -0.0767309 -0.0845 -0.0555913 -0.0767249 -0.08455 -0.0554927 -0.0767188 -0.0846 -0.0553939 -0.0767125 -0.08465 -0.0552949 -0.0767062 -0.0847 -0.0551956 -0.0766997 -0.08475 -0.055096 -0.076693 -0.0848 -0.0549961 -0.0766863 -0.08485 -0.0548959 -0.0766794 -0.0849 -0.0547954 -0.0766723 -0.08495 -0.0546944 -0.0766651 -0.085 -0.0545931 -0.0766578 -0.08505 -0.0544913 -0.0766503 -0.0851 -0.054389 -0.0766427 -0.08515 -0.0542863 -0.0766349 -0.0852 -0.054183 -0.076627 -0.08525 -0.054079 -0.0766189 -0.0853 -0.0539745 -0.0766107 -0.08535 -0.0538693 -0.0766023 -0.0854 -0.0537633 -0.0765938 -0.08545 -0.0536566 -0.076585 -0.0855 -0.0535491 -0.0765762 -0.08555 -0.0534407 -0.0765671 -0.0856 -0.0533314 -0.0765579 -0.08565 -0.053221 -0.0765485 -0.0857 -0.0531096 -0.076539 -0.08575 -0.0529971 -0.0765293 -0.0858 -0.0528833 -0.0765194 -0.08585 -0.0527683 -0.0765093 -0.0859 -0.0526518 -0.0764991 -0.08595 -0.0525339 -0.0764887 -0.086 -0.0524144 -0.0764781 -0.08605 -0.0522932 -0.0764673 -0.0861 -0.0521701 -0.0764563 -0.08615 -0.0520452 -0.0764452 -0.0862 -0.0519181 -0.0764338 -0.08625 -0.0517888 -0.0764223 -0.0863 -0.0516572 -0.0764106 -0.08635 -0.0515229 -0.0763987 -0.0864 -0.0513859 -0.0763866 -0.08645 -0.0512459 -0.0763743 -0.0865 -0.0511027 -0.0763618 -0.08655 -0.050956 -0.0763492 -0.0866 -0.0508056 -0.0763363 -0.08665 -0.0506511 -0.0763232 -0.0867 -0.0504923 -0.07631 -0.08675 -0.0503287 -0.0762965 -0.0868 -0.0501599 -0.0762828 -0.08685 -0.0499855 -0.076269 -0.0869 -0.0498049 -0.0762549 -0.08695 -0.0496176 -0.0762406 -0.087 -0.0494229 -0.0762262 -0.08705 -0.0492202 -0.0762115 -0.0871 -0.0490085 -0.0761966 -0.08715 -0.0487871 -0.0761815 -0.0872 -0.0485547 -0.0761662 -0.08725 -0.0483104 -0.0761507 -0.0873 -0.0480526 -0.076135 -0.08735 -0.0477798 -0.0761191 -0.0874 -0.0474903 -0.076103 -0.08745 -0.047182 -0.0760866 -0.0875 -0.0468524 -0.0760701 -0.08755 -0.0464988 -0.0760533 -0.0876 -0.0461177 -0.0760363 -0.08765 -0.0457055 -0.0760191 -0.0877 -0.0452573 -0.0760017 -0.08775 -0.0447677 -0.0759841 -0.0878 -0.0442301 -0.0759662 -0.08785 -0.0436364 -0.0759482 -0.0879 -0.0429771 -0.0759299 -0.08795 -0.04224 -0.0759114 -0.088 -0.0414108 -0.0758927 -0.08805 -0.0404713 -0.0758737 -0.0881 -0.039399 -0.0758545 -0.08815 -0.038166 -0.0758351 -0.0882 -0.0367372 -0.0758155 -0.08825 -0.0350689 -0.0757956 -0.0883 -0.0331069 -0.0757755 -0.08835 -0.030785 -0.0757552 -0.0884 -0.0280246 -0.0757346 -0.08845 -0.0247376 -0.0757138 -0.0885 -0.0208351 -0.0756927 -0.08855 -0.0162479 -0.0756714 -0.0886 -0.0109633 -0.0756498 -0.08865 -0.00507896 -0.075628 -0.0887 0.00114343 -0.0756059 -0.08875 0.00726843 -0.0755836 -0.0888 0.0127657 -0.075561 -0.08885 0.0171665 -0.075538 -0.0889 0.0202072 -0.0755148 -0.08895 0.0218699 -0.0754913 -0.089 0.0223183 -0.0754675 -0.08905 0.0217967 -0.0754433 -0.0891 0.0205512 -0.0754188 -0.08915 0.0187913 -0.0753939 -0.0892 0.0166792 -0.0753686 -0.08925 0.0143354 -0.0753428 -0.0893 0.0118469 -0.0753166 -0.08935 0.00927609 -0.0752899 -0.0894 0.00666772 -0.0752626 -0.08945 0.00405375 -0.0752346 -0.0895 0.00145697 -0.0752059 -0.08955 -0.00110649 -0.0751762 -0.0896 -0.0036254 -0.0751455 -0.08965 -0.00609216 -0.0751134 -0.0897 -0.0085019 -0.0750798 -0.08975 -0.0108518 -0.0750442 -0.0898 -0.0131405 -0.0750062 -0.08985 -0.015368 -0.0749651 -0.0899 -0.0175353 -0.0749203 -0.08995 -0.0196438 -0.0748707 -0.09 -0.0216962 -0.0748151 -0.09005 -0.0236954 -0.0747519 -0.0901 -0.0256452 -0.0746794 -0.09015 -0.0275501 -0.074595 -0.0902 -0.0294152 -0.0744957 -0.09025 -0.0312465 -0.074378 -0.0903 -0.0330504 -0.074237 -0.09035 -0.0348343 -0.0740671 -0.0904 -0.0366056 -0.0738613 -0.09045 -0.0383725 -0.0736106 -0.0905 -0.0401429 -0.0733042 -0.09055 -0.0419242 -0.0729286 -0.0906 -0.0437228 -0.0724672 -0.09065 -0.0455435 -0.0718995 -0.0907 -0.0473878 -0.0712 -0.09075 -0.0492535 -0.0703373 -0.0908 -0.051133 -0.0692724 -0.09085 -0.0530123 -0.0679573 -0.0909 -0.0548709 -0.0663318 -0.09095 -0.056682 -0.0643211 -0.091 -0.0584149 -0.0618308 -0.09105 -0.060038 -0.0587403 -0.0911 -0.0615234 -0.054891 -0.09115 -0.0628508 -0.0500665 -0.0912 -0.0640098 -0.0439514 -0.09125 -0.0650008 -0.0360528 -0.0913 -0.0658328 -0.0255661 -0.09135 -0.066521 -0.0113102 -0.0914 -0.0670834 0.00740621 -0.09145 -0.0675385 0.0273525 -0.0915 -0.0679038 0.0407123 -0.09155 -0.0681944 0.0454471 -0.0916 -0.0684235 0.0461503 -0.09165 -0.0686017 0.0457574 -0.0917 -0.0687379 0.0450096 -0.09175 -0.0688393 0.0440355 -0.0918 -0.0689118 0.0428621 -0.09185 -0.06896 0.0415022 -0.0919 -0.0689878 0.0399673 -0.09195 -0.0689985 0.0382704 -0.092 -0.0689947 0.0364259 -0.09205 -0.0689786 0.0344497 -0.0921 -0.0689519 0.0323581 -0.09215 -0.0689163 0.0301676 -0.0922 -0.0688729 0.0278945 -0.09225 -0.0688229 0.0255541 -0.0923 -0.0687671 0.023161 -0.09235 -0.0687064 0.0207284 -0.0924 -0.0686414 0.0182683 -0.09245 -0.0685726 0.0157912 -0.0925 -0.0685006 0.0133064 -0.09255 -0.0684257 0.0108217 -0.0926 -0.0683482 0.00834352 -0.09265 -0.0682685 0.00587734 -0.0927 -0.0681868 0.00342735 -0.09275 -0.0681034 0.000996762 -0.0928 -0.0680184 -0.00141214 -0.09285 -0.067932 -0.00379792 -0.0929 -0.0678443 -0.0061599 -0.09295 -0.0677555 -0.00849812 -0.093 -0.0676656 -0.0108133 -0.09305 -0.0675747 -0.013107 -0.0931 -0.067483 -0.0153814 -0.09315 -0.0673905 -0.0176398 -0.0932 -0.0672973 -0.0198865 -0.09325 -0.0672033 -0.0221275 -0.0933 -0.0671088 -0.0243705 -0.09335 -0.0670136 -0.0266259 -0.0934 -0.0669179 -0.0289075 -0.09345 -0.0668216 -0.031233 -0.0935 -0.0667249 -0.0336256 -0.09355 -0.0666277 -0.0361143 -0.0936 -0.0665301 -0.0387353 -0.09365 -0.0664321 -0.0415316 -0.0937 -0.0663337 -0.0445507 -0.09375 -0.0662349 -0.0478382 -0.0938 -0.0661357 -0.0514241 -0.09385 -0.0660363 -0.0552967 -0.0939 -0.0659365 -0.0593675 -0.09395 -0.0658364 -0.0634386 -0.094 -0.0657361 -0.0672142 -0.09405 -0.0656354 -0.0703896 -0.0941 -0.0655345 -0.0727879 -0.09415 -0.0654334 -0.0744269 -0.0942 -0.0653321 -0.0754629 -0.09425 -0.0652305 -0.0760853 -0.0943 -0.0651288 -0.0764492 -0.09435 -0.0650268 -0.0766601 -0.0944 -0.0649247 -0.0767825 -0.09445 -0.0648224 -0.0768541 -0.0945 -0.0647199 -0.0768965 -0.09455 -0.0646173 -0.0769218 -0.0946 -0.0645146 -0.076937 -0.09465 -0.0644117 -0.0769462 -0.0947 -0.0643088 -0.0769516 -0.09475 -0.0642057 -0.0769548 -0.0948 -0.0641025 -0.0769565 -0.09485 -0.0639993 -0.0769573 -0.0949 -0.063896 -0.0769575 -0.09495 -0.0637926 -0.0769573 -0.095 -0.0636891 -0.0769568 -0.09505 -0.0635856 -0.0769561 -0.0951 -0.0634821 -0.0769553 -0.09515 -0.0633785 -0.0769543 -0.0952 -0.063275 -0.0769533 -0.09525 -0.0631714 -0.0769522 -0.0953 -0.0630678 -0.0769511 -0.09535 -0.0629642 -0.0769499 -0.0954 -0.0628606 -0.0769487 -0.09545 -0.0627571 -0.0769474 -0.0955 -0.0626536 -0.0769461 -0.09555 -0.0625501 -0.0769448 -0.0956 -0.0624466 -0.0769434 -0.09565 -0.0623432 -0.076942 -0.0957 -0.0622399 -0.0769406 -0.09575 -0.0621366 -0.0769391 -0.0958 -0.0620334 -0.0769376 -0.09585 -0.0619303 -0.076936 -0.0959 -0.0618272 -0.0769345 -0.09595 -0.0617242 -0.0769329 -0.096 -0.0616214 -0.0769312 -0.09605 -0.0615186 -0.0769295 -0.0961 -0.0614159 -0.0769278 -0.09615 -0.0613133 -0.0769261 -0.0962 -0.0612109 -0.0769243 -0.09625 -0.0611085 -0.0769224 -0.0963 -0.0610063 -0.0769206 -0.09635 -0.0609042 -0.0769186 -0.0964 -0.0608022 -0.0769167 -0.09645 -0.0607004 -0.0769147 -0.0965 -0.0605987 -0.0769127 -0.09655 -0.0604971 -0.0769106 -0.0966 -0.0603957 -0.0769085 -0.09665 -0.0602944 -0.0769063 -0.0967 -0.0601932 -0.0769041 -0.09675 -0.0600922 -0.0769018 -0.0968 -0.0599914 -0.0768995 -0.09685 -0.0598907 -0.0768971 -0.0969 -0.0597901 -0.0768947 -0.09695 -0.0596897 -0.0768922 -0.097 -0.0595894 -0.0768897 -0.09705 -0.0594893 -0.0768872 -0.0971 -0.0593893 -0.0768845 -0.09715 -0.0592895 -0.0768819 -0.0972 -0.0591898 -0.0768791 -0.09725 -0.0590902 -0.0768763 -0.0973 -0.0589908 -0.0768735 -0.09735 -0.0588915 -0.0768705 -0.0974 -0.0587924 -0.0768676 -0.09745 -0.0586934 -0.0768645 -0.0975 -0.0585946 -0.0768614 -0.09755 -0.0584958 -0.0768582 -0.0976 -0.0583972 -0.076855 -0.09765 -0.0582987 -0.0768516 -0.0977 -0.0582003 -0.0768482 -0.09775 -0.0581021 -0.0768448 -0.0978 -0.0580039 -0.0768412 -0.09785 -0.0579059 -0.0768376 -0.0979 -0.0578079 -0.0768339 -0.09795 -0.05771 -0.0768302 -0.098 -0.0576122 -0.0768263 -0.09805 -0.0575145 -0.0768224 -0.0981 -0.0574168 -0.0768183 -0.09815 -0.0573193 -0.0768142 -0.0982 -0.0572217 -0.07681 -0.09825 -0.0571242 -0.0768057 -0.0983 -0.0570267 -0.0768013 -0.09835 -0.0569293 -0.0767969 -0.0984 -0.0568318 -0.0767923 -0.09845 -0.0567344 -0.0767876 -0.0985 -0.056637 -0.0767828 -0.09855 -0.0565395 -0.0767779 -0.0986 -0.056442 -0.0767729 -0.09865 -0.0563444 -0.0767679 -0.0987 -0.0562468 -0.0767626 -0.09875 -0.0561491 -0.0767573 -0.0988 -0.0560514 -0.0767519 -0.09885 -0.0559535 -0.0767464 -0.0989 -0.0558555 -0.0767407 -0.09895 -0.0557573 -0.0767349 -0.099 -0.055659 -0.076729 -0.09905 -0.0555606 -0.076723 -0.0991 -0.0554619 -0.0767168 -0.09915 -0.055363 -0.0767106 -0.0992 -0.0552639 -0.0767042 -0.09925 -0.0551645 -0.0766976 -0.0993 -0.0550649 -0.0766909 -0.09935 -0.0549649 -0.0766841 -0.0994 -0.0548646 -0.0766772 -0.09945 -0.0547639 -0.0766701 -0.0995 -0.0546629 -0.0766629 -0.09955 -0.0545614 -0.0766555 -0.0996 -0.0544594 -0.076648 -0.09965 -0.054357 -0.0766403 -0.0997 -0.0542541 -0.0766325 -0.09975 -0.0541506 -0.0766245 -0.0998 -0.0540465 -0.0766164 -0.09985 -0.0539417 -0.0766081 -0.0999 -0.0538363 -0.0765997 -0.09995 -0.0537301 -0.0765911 -0.1 -0.0536232 -0.0765823 -0.10005 -0.0535154 -0.0765734 -0.1001 -0.0534067 -0.0765643 -0.10015 -0.0532971 -0.076555 -0.1002 -0.0531864 -0.0765456 -0.10025 -0.0530746 -0.076536 -0.1003 -0.0529617 -0.0765262 -0.10035 -0.0528476 -0.0765163 -0.1004 -0.0527321 -0.0765061 -0.10045 -0.0526152 -0.0764958 -0.1005 -0.0524968 -0.0764854 -0.10055 -0.0523767 -0.0764747 -0.1006 -0.052255 -0.0764639 -0.10065 -0.0521313 -0.0764528 -0.1007 -0.0520057 -0.0764416 -0.10075 -0.051878 -0.0764302 -0.1008 -0.051748 -0.0764187 -0.10085 -0.0516155 -0.0764069 -0.1009 -0.0514805 -0.0763949 -0.10095 -0.0513425 -0.0763828 -0.101 -0.0512016 -0.0763704 -0.10105 -0.0510573 -0.0763579 -0.1011 -0.0509095 -0.0763452 -0.10115 -0.0507578 -0.0763322 -0.1012 -0.0506021 -0.0763191 -0.10125 -0.0504418 -0.0763058 -0.1013 -0.0502766 -0.0762922 -0.10135 -0.0501061 -0.0762785 -0.1014 -0.0499298 -0.0762646 -0.10145 -0.0497472 -0.0762505 -0.1015 -0.0495577 -0.0762361 -0.10155 -0.0493606 -0.0762216 -0.1016 -0.0491551 -0.0762069 -0.10165 -0.0489405 -0.0761919 -0.1017 -0.0487158 -0.0761768 -0.10175 -0.0484798 -0.0761614 -0.1018 -0.0482314 -0.0761458 -0.10185 -0.0479691 -0.0761301 -0.1019 -0.0476914 -0.0761141 -0.10195 -0.0473962 -0.0760979 -0.102 -0.0470815 -0.0760815 -0.10205 -0.0467447 -0.0760649 -0.1021 -0.0463829 -0.076048 -0.10215 -0.0459926 -0.076031 -0.1022 -0.0455697 -0.0760137 -0.10225 -0.0451092 -0.0759962 -0.1023 -0.0446054 -0.0759785 -0.10235 -0.0440512 -0.0759606 -0.1024 -0.0434382 -0.0759425 -0.10245 -0.042756 -0.0759241 -0.1025 -0.0419919 -0.0759056 -0.10255 -0.0411304 -0.0758868 -0.1026 -0.0401521 -0.0758677 -0.10265 -0.0390329 -0.0758485 -0.1027 -0.037743 -0.075829 -0.10275 -0.0362446 -0.0758093 -0.1028 -0.034491 -0.0757894 -0.10285 -0.0324243 -0.0757692 -0.1029 -0.0299745 -0.0757488 -0.10295 -0.0270595 -0.0757281 -0.103 -0.0235895 -0.0757072 -0.10305 -0.019479 -0.0756861 -0.1031 -0.0146715 -0.0756647 -0.10315 -0.00918243 -0.0756431 -0.1032 -0.00315588 -0.0756212 -0.10325 0.00308982 -0.075599 -0.1033 0.0090764 -0.0755766 -0.10335 0.0142743 -0.0755538 -0.1034 0.018267 -0.0755308 -0.10345 0.0208691 -0.0755075 -0.1035 0.0221295 -0.0754839 -0.10355 0.0222476 -0.07546 -0.1036 0.0214749 -0.0754357 -0.10365 0.0200486 -0.075411 -0.1037 0.0181635 -0.075386 -0.10375 0.0159679 -0.0753606 -0.1038 0.0135709 -0.0753347 -0.10385 0.011051 -0.0753084 -0.1039 0.00846431 -0.0752815 -0.10395 0.00585125 -0.0752539 -0.104 0.00324055 -0.0752257 -0.10405 0.000652696 -0.0751967 -0.1041 -0.00189787 -0.0751667 -0.10415 -0.00440117 -0.0751356 -0.1042 -0.00685055 -0.0751031 -0.10425 -0.00924183 -0.0750689 -0.1043 -0.0115727 -0.0750326 -0.10435 -0.0138423 -0.0749937 -0.1044 -0.0160509 -0.0749516 -0.10445 -0.0181996 -0.0749054 -0.1045 -0.0202903 -0.074854 -0.10455 -0.0223257 -0.0747963 -0.1046 -0.024309 -0.0747304 -0.10465 -0.0262443 -0.0746544 -0.1047 -0.0281362 -0.0745658 -0.10475 -0.0299901 -0.0744612 -0.1048 -0.0318121 -0.0743367 -0.10485 -0.033609 -0.0741874 -0.1049 -0.0353881 -0.0740071 -0.10495 -0.0371572 -0.0737883 -0.105 -0.0389243 -0.0735215 -0.10505 -0.0406973 -0.0731951 -0.1051 -0.0424834 -0.0727947 -0.10515 -0.0442886 -0.0723026 -0.1052 -0.0461166 -0.0716967 -0.10525 -0.0479681 -0.0709499 -0.1053 -0.0498392 -0.0700287 -0.10535 -0.0517204 -0.0688914 -0.1054 -0.0535957 -0.0674864 -0.10545 -0.0554426 -0.0657496 -0.1055 -0.0572328 -0.0636004 -0.10555 -0.0589347 -0.0609372 -0.1056 -0.0605176 -0.0576291 -0.10565 -0.0619554 -0.0535023 -0.1057 -0.0632308 -0.048315 -0.10575 -0.0643369 -0.0417077 -0.1058 -0.0652769 -0.0331066 -0.10585 -0.0660622 -0.021582 -0.1059 -0.0667091 -0.00591841 -0.10595 -0.0672361 0.0138347 -0.106 -0.0676614 0.0325446 -0.10605 -0.0680018 0.0429323 -0.1061 -0.068272 0.0458956 -0.10615 -0.0684841 0.0460866 -0.1062 -0.0686483 0.0455518 -0.10625 -0.068773 0.044728 -0.1063 -0.0688648 0.04369 -0.10635 -0.0689292 0.0424572 -0.1064 -0.0689707 0.0410413 -0.10645 -0.0689929 0.0394544 -0.1065 -0.0689988 0.0377098 -0.10655 -0.0689909 0.0358225 -0.1066 -0.0689713 0.0338085 -0.10665 -0.0689417 0.0316843 -0.1067 -0.0689035 0.0294663 -0.10675 -0.068858 0.0271705 -0.1068 -0.0688061 0.0248122 -0.10685 -0.0687487 0.0224054 -0.1069 -0.0686866 0.019963 -0.10695 -0.0686203 0.0174965 -0.107 -0.0685505 0.0150161 -0.10705 -0.0684775 0.0125306 -0.1071 -0.0684017 0.0100472 -0.10715 -0.0683236 0.0075723 -0.1072 -0.0682432 0.00511077 -0.10725 -0.068161 0.00266653 -0.1073 -0.068077 0.000242507 -0.10735 -0.0679916 -0.0021593 -0.1074 -0.0679048 -0.00453768 -0.10745 -0.0678167 -0.00689221 -0.1075 -0.0677275 -0.00922314 -0.10755 -0.0676373 -0.0115314 -0.1076 -0.0675462 -0.0138188 -0.10765 -0.0674543 -0.0160878 -0.1077 -0.0673615 -0.0183421 -0.10775 -0.067268 -0.0205863 -0.1078 -0.0671739 -0.0228269 -0.10785 -0.0670791 -0.0250725 -0.1079 -0.0669838 -0.0273345 -0.10795 -0.0668879 -0.0296276 -0.108 -0.0667915 -0.0319713 -0.10805 -0.0666946 -0.0343905 -0.1081 -0.0665973 -0.0369163 -0.10815 -0.0664996 -0.0395871 -0.1082 -0.0664014 -0.0424477 -0.10825 -0.0663029 -0.045546 -0.1083 -0.066204 -0.0489248 -0.10835 -0.0661047 -0.0526043 -0.1084 -0.0660052 -0.0565529 -0.10845 -0.0659053 -0.0606505 -0.1085 -0.0658051 -0.0646641 -0.10855 -0.0657047 -0.0682817 -0.1086 -0.065604 -0.0712245 -0.10865 -0.065503 -0.0733753 -0.1087 -0.0654018 -0.0748058 -0.10875 -0.0653004 -0.0756933 -0.1088 -0.0651988 -0.0762207 -0.10885 -0.065097 -0.0765278 -0.1089 -0.0649949 -0.0767056 -0.10895 -0.0648928 -0.0768091 -0.109 -0.0647904 -0.0768698 -0.10905 -0.0646879 -0.0769058 -0.1091 -0.0645853 -0.0769274 -0.10915 -0.0644825 -0.0769404 -0.1092 -0.0643796 -0.0769482 -0.10925 -0.0642766 -0.0769528 -0.1093 -0.0641735 -0.0769555 -0.10935 -0.0640703 -0.0769569 -0.1094 -0.063967 -0.0769574 -0.10945 -0.0638637 -0.0769575 -0.1095 -0.0637603 -0.0769572 -0.10955 -0.0636568 -0.0769566 -0.1096 -0.0635533 -0.0769559 -0.10965 -0.0634498 -0.076955 -0.1097 -0.0633462 -0.076954 -0.10975 -0.0632426 -0.076953 -0.1098 -0.0631391 -0.0769519 -0.10985 -0.0630355 -0.0769507 -0.1099 -0.0629319 -0.0769495 -0.10995 -0.0628283 -0.0769483 -0.11 -0.0627248 -0.076947 -0.11005 -0.0626213 -0.0769457 -0.1101 -0.0625178 -0.0769444 -0.11015 -0.0624143 -0.076943 -0.1102 -0.062311 -0.0769416 -0.11025 -0.0622076 -0.0769401 -0.1103 -0.0621044 -0.0769386 -0.11035 -0.0620012 -0.0769371 -0.1104 -0.0618981 -0.0769356 -0.11045 -0.0617951 -0.076934 -0.1105 -0.0616921 -0.0769323 -0.11055 -0.0615893 -0.0769307 -0.1106 -0.0614865 -0.076929 -0.11065 -0.0613839 -0.0769273 -0.1107 -0.0612813 -0.0769255 -0.11075 -0.0611789 -0.0769237 -0.1108 -0.0610766 -0.0769218 -0.11085 -0.0609744 -0.07692 -0.1109 -0.0608724 -0.076918 -0.11095 -0.0607704 -0.0769161 -0.111 -0.0606686 -0.0769141 -0.11105 -0.060567 -0.076912 -0.1111 -0.0604654 -0.0769099 -0.11115 -0.0603641 -0.0769078 -0.1112 -0.0602628 -0.0769056 -0.11125 -0.0601617 -0.0769034 -0.1113 -0.0600607 -0.0769011 -0.11135 -0.0599599 -0.0768988 -0.1114 -0.0598593 -0.0768964 -0.11145 -0.0597587 -0.0768939 -0.1115 -0.0596584 -0.0768915 -0.11155 -0.0595581 -0.0768889 -0.1116 -0.059458 -0.0768863 -0.11165 -0.0593581 -0.0768837 -0.1117 -0.0592583 -0.076881 -0.11175 -0.0591587 -0.0768782 -0.1118 -0.0590592 -0.0768754 -0.11185 -0.0589598 -0.0768725 -0.1119 -0.0588606 -0.0768696 -0.11195 -0.0587615 -0.0768666 -0.112 -0.0586626 -0.0768635 -0.11205 -0.0585637 -0.0768604 -0.1121 -0.058465 -0.0768572 -0.11215 -0.0583665 -0.0768539 -0.1122 -0.058268 -0.0768506 -0.11225 -0.0581697 -0.0768472 -0.1123 -0.0580714 -0.0768437 -0.11235 -0.0579733 -0.0768401 -0.1124 -0.0578753 -0.0768365 -0.11245 -0.0577773 -0.0768328 -0.1125 -0.0576795 -0.076829 -0.11255 -0.0575817 -0.0768251 -0.1126 -0.057484 -0.0768211 -0.11265 -0.0573864 -0.0768171 -0.1127 -0.0572888 -0.0768129 -0.11275 -0.0571913 -0.0768087 -0.1128 -0.0570938 -0.0768044 -0.11285 -0.0569963 -0.0767999 -0.1129 -0.0568989 -0.0767954 -0.11295 -0.0568014 -0.0767908 -0.113 -0.056704 -0.0767861 -0.11305 -0.0566065 -0.0767813 -0.1131 -0.0565091 -0.0767764 -0.11315 -0.0564115 -0.0767714 -0.1132 -0.056314 -0.0767662 -0.11325 -0.0562163 -0.076761 -0.1133 -0.0561186 -0.0767557 -0.11335 -0.0560208 -0.0767502 -0.1134 -0.0559229 -0.0767446 -0.11345 -0.0558249 -0.0767389 -0.1135 -0.0557267 -0.0767331 -0.11355 -0.0556283 -0.0767272 -0.1136 -0.0555298 -0.0767211 -0.11365 -0.0554311 -0.0767149 -0.1137 -0.0553321 -0.0767086 -0.11375 -0.0552329 -0.0767021 -0.1138 -0.0551334 -0.0766956 -0.11385 -0.0550337 -0.0766888 -0.1139 -0.0549336 -0.076682 -0.11395 -0.0548332 -0.076675 -0.114 -0.0547324 -0.0766679 -0.11405 -0.0546312 -0.0766606 -0.1141 -0.0545296 -0.0766532 -0.11415 -0.0544275 -0.0766456 -0.1142 -0.054325 -0.0766379 -0.11425 -0.0542218 -0.07663 -0.1143 -0.0541182 -0.076622 -0.11435 -0.0540139 -0.0766138 -0.1144 -0.0539089 -0.0766055 -0.11445 -0.0538032 -0.076597 -0.1145 -0.0536968 -0.0765883 -0.11455 -0.0535896 -0.0765795 -0.1146 -0.0534816 -0.0765705 -0.11465 -0.0533726 -0.0765614 -0.1147 -0.0532626 -0.0765521 -0.11475 -0.0531516 -0.0765426 -0.1148 -0.0530395 -0.076533 -0.11485 -0.0529262 -0.0765231 -0.1149 -0.0528117 -0.0765131 -0.11495 -0.0526957 -0.0765029 -0.115 -0.0525784 -0.0764926 -0.11505 -0.0524595 -0.0764821 -0.1151 -0.0523389 -0.0764713 -0.11515 -0.0522166 -0.0764604 -0.1152 -0.0520924 -0.0764494 -0.11525 -0.0519661 -0.0764381 -0.1153 -0.0518377 -0.0764266 -0.11535 -0.0517069 -0.076415 -0.1154 -0.0515737 -0.0764032 -0.11545 -0.0514377 -0.0763912 -0.1155 -0.0512989 -0.0763789 -0.11555 -0.0511569 -0.0763665 -0.1156 -0.0510116 -0.0763539 -0.11565 -0.0508626 -0.0763411 -0.1157 -0.0507097 -0.0763281 -0.11575 -0.0505525 -0.076315 -0.1158 -0.0503907 -0.0763016 -0.11585 -0.050224 -0.076288 -0.1159 -0.0500517 -0.0762742 -0.11595 -0.0498735 -0.0762602 -0.116 -0.0496888 -0.076246 -0.11605 -0.049497 -0.0762316 -0.1161 -0.0492974 -0.076217 -0.11615 -0.0490892 -0.0762022 -0.1162 -0.0488715 -0.0761872 -0.11625 -0.0486434 -0.076172 -0.1163 -0.0484037 -0.0761566 -0.11635 -0.0481511 -0.0761409 -0.1164 -0.0478842 -0.0761251 -0.11645 -0.0476012 -0.0761091 -0.1165 -0.0473002 -0.0760928 -0.11655 -0.0469789 -0.0760763 -0.1166 -0.0466347 -0.0760596 -0.11665 -0.0462644 -0.0760427 -0.1167 -0.0458643 -0.0760256 -0.11675 -0.0454302 -0.0760083 -0.1168 -0.0449569 -0.0759907 -0.11685 -0.0444382 -0.075973 -0.1169 -0.0438667 -0.075955 -0.11695 -0.0432333 -0.0759368 -0.117 -0.042527 -0.0759184 -0.11705 -0.0417343 -0.0758997 -0.1171 -0.0408386 -0.0758808 -0.11715 -0.0398192 -0.0758618 -0.1172 -0.0386503 -0.0758424 -0.11725 -0.0372997 -0.0758229 -0.1173 -0.0357271 -0.0758031 -0.11735 -0.0338826 -0.0757831 -0.1174 -0.0317045 -0.0757628 -0.11745 -0.0291188 -0.0757424 -0.1175 -0.0260403 -0.0757216 -0.11755 -0.0223789 -0.0757007 -0.1176 -0.0180546 -0.0756794 -0.11765 -0.0130278 -0.075658 -0.1177 -0.00734791 -0.0756363 -0.11775 -0.00121018 -0.0756143 -0.1178 0.00501141 -0.075592 -0.11785 0.0108067 -0.0755695 -0.1179 0.0156636 -0.0755467 -0.11795 0.0192302 -0.0755236 -0.118 0.0213992 -0.0755002 -0.11805 0.0222774 -0.0754765 -0.1181 0.0220903 -0.0754524 -0.11815 0.0210898 -0.075428 -0.1182 0.0195017 -0.0754033 -0.11825 0.0175057 -0.0753781 -0.1183 0.0152372 -0.0753526 -0.11835 0.0127946 -0.0753265 -0.1184 0.0102486 -0.0753 -0.11845 0.00765003 -0.0752729 -0.1185 0.00503506 -0.0752452 -0.11855 0.00242962 -0.0752168 -0.1186 -0.000147909 -0.0751875 -0.11865 -0.00268462 -0.0751572 -0.1187 -0.00517168 -0.0751256 -0.11875 -0.00760327 -0.0750926 -0.1188 -0.00997587 -0.0750578 -0.11885 -0.0122877 -0.0750208 -0.1189 -0.0145381 -0.074981 -0.11895 -0.0167278 -0.0749376 -0.119 -0.0188582 -0.0748899 -0.11905 -0.0209313 -0.0748368 -0.1191 -0.0229501 -0.0747767 -0.11915 -0.024918 -0.0747079 -0.1192 -0.0268392 -0.0746283 -0.11925 -0.0287186 -0.074535 -0.1193 -0.0305619 -0.0744247 -0.11935 -0.0323753 -0.074293 -0.1194 -0.0341658 -0.0741348 -0.11945 -0.0359409 -0.0739434 -0.1195 -0.0377086 -0.0737107 -0.11955 -0.0394767 -0.0734266 -0.1196 -0.0412531 -0.0730788 -0.11965 -0.0430446 -0.0726519 -0.1197 -0.0448566 -0.0721268 -0.11975 -0.046692 -0.0714802 -0.1198 -0.0485503 -0.0706829 -0.11985 -0.0504258 -0.0696991 -0.1199 -0.0523072 -0.0684844 -0.11995 -0.0541765 -0.0669834 -0.12 -0.0560089 -0.0651273 -0.12005 -0.0577749 -0.0628298 -0.1201 -0.0594429 -0.0599811 -0.12015 -0.0609829 -0.0564386 -0.1202 -0.0623714 -0.052011 -0.12025 -0.0635942 -0.0464268 -0.1203 -0.0646477 -0.0392726 -0.12035 -0.065538 -0.0298789 -0.1204 -0.0662782 -0.0171893 -0.1205 -0.0673789 0.0201962 -0.12055 -0.067776 0.0368363 -0.1206 -0.0680931 0.0444062 -0.12065 -0.0683439 0.0461021 -0.1207 -0.0685401 0.0459625 -0.12075 -0.0686911 0.0453199 -0.1208 -0.0688049 0.0444258 -0.12085 -0.0688876 0.0433256 -0.1209 -0.0689444 0.0420344 -0.12095 -0.0689795 0.0405638 -0.121 -0.0689964 0.0389261 -0.12105 -0.0689977 0.0371354 -0.1211 -0.068986 0.0352068 -0.12115 -0.0689631 0.0331566 -0.1212 -0.0689306 0.0310013 -0.12125 -0.06889 0.0287574 -0.1213 -0.0688424 0.0264405 -0.12135 -0.0687887 0.0240656 -0.1214 -0.0687298 0.0216464 -0.12145 -0.0686663 0.0191953 -0.1215 -0.0685989 0.0167234 -0.12155 -0.068528 0.0142405 -0.1216 -0.0684541 0.0117549 -0.12165 -0.0683776 0.00927361 -0.1217 -0.0682987 0.00680238 -0.12175 -0.0682178 0.00434588 -0.1218 -0.068135 0.00190769 -0.12185 -0.0680505 -0.00050957 -0.1219 -0.0679646 -0.00290417 -0.12195 -0.0678774 -0.00527512 -0.122 -0.067789 -0.00762222 -0.12205 -0.0676995 -0.00994594 -0.1221 -0.067609 -0.0122475 -0.12215 -0.0675176 -0.0145288 -0.1222 -0.0674254 -0.0167928 -0.12225 -0.0673324 -0.0190433 -0.1223 -0.0672387 -0.0212856 -0.12235 -0.0671444 -0.0235268 -0.1224 -0.0670494 -0.0257761 -0.12245 -0.0669539 -0.028046 -0.1225 -0.0668579 -0.0303527 -0.12255 -0.0667613 -0.0327169 -0.1226 -0.0666643 -0.0351657 -0.12265 -0.0665668 -0.0377323 -0.1227 -0.066469 -0.0404573 -0.12275 -0.0663707 -0.043387 -0.1228 -0.066272 -0.0465689 -0.12285 -0.066173 -0.0500411 -0.1229 -0.0660737 -0.0538113 -0.12295 -0.065974 -0.0578245 -0.123 -0.0658741 -0.061926 -0.12305 -0.0657738 -0.0658508 -0.1231 -0.0656733 -0.0692821 -0.12315 -0.0655725 -0.0719808 -0.1232 -0.0654715 -0.0738918 -0.12325 -0.0653702 -0.075132 -0.1233 -0.0652687 -0.075889 -0.12335 -0.065167 -0.076335 -0.1234 -0.0650651 -0.076594 -0.12345 -0.0649631 -0.076744 -0.1235 -0.0648608 -0.0768315 -0.12355 -0.0647584 -0.0768831 -0.1236 -0.0646559 -0.0769138 -0.12365 -0.0645532 -0.0769322 -0.1237 -0.0644504 -0.0769433 -0.12375 -0.0643475 -0.0769499 -0.1238 -0.0642444 -0.0769538 -0.12385 -0.0641413 -0.076956 -0.1239 -0.0640381 -0.0769571 -0.12395 -0.0639348 -0.0769575 -0.124 -0.0638314 -0.0769574 -0.12405 -0.063728 -0.076957 -0.1241 -0.0636245 -0.0769564 -0.12415 -0.063521 -0.0769556 -0.1242 -0.0634175 -0.0769547 -0.12425 -0.0633139 -0.0769537 -0.1243 -0.0632103 -0.0769527 -0.12435 -0.0631067 -0.0769515 -0.1244 -0.0630031 -0.0769504 -0.12445 -0.0628996 -0.0769492 -0.1245 -0.062796 -0.0769479 -0.12455 -0.0626925 -0.0769466 -0.1246 -0.062589 -0.0769453 -0.12465 -0.0624855 -0.0769439 -0.1247 -0.0623821 -0.0769425 -0.12475 -0.0622787 -0.0769411 -0.1248 -0.0621754 -0.0769396 -0.12485 -0.0620722 -0.0769382 -0.1249 -0.061969 -0.0769366 -0.12495 -0.0618659 -0.0769351 -0.125 -0.0617629 -0.0769335 -0.12505 -0.06166 -0.0769318 -0.1251 -0.0615572 -0.0769302 -0.12515 -0.0614545 -0.0769285 -0.1252 -0.0613519 -0.0769267 -0.12525 -0.0612494 -0.0769249 -0.1253 -0.061147 -0.0769231 -0.12535 -0.0610447 -0.0769213 -0.1254 -0.0609426 -0.0769194 -0.12545 -0.0608405 -0.0769174 -0.1255 -0.0607387 -0.0769154 -0.12555 -0.0606369 -0.0769134 -0.1256 -0.0605353 -0.0769114 -0.12565 -0.0604338 -0.0769093 -0.1257 -0.0603324 -0.0769071 -0.12575 -0.0602312 -0.0769049 -0.1258 -0.0601302 -0.0769027 -0.12585 -0.0600293 -0.0769004 -0.1259 -0.0599285 -0.076898 -0.12595 -0.0598279 -0.0768956 -0.126 -0.0597274 -0.0768932 -0.12605 -0.0596271 -0.0768907 -0.1261 -0.0595269 -0.0768881 -0.12615 -0.0594268 -0.0768855 -0.1262 -0.059327 -0.0768829 -0.12625 -0.0592272 -0.0768801 -0.1263 -0.0591276 -0.0768774 -0.12635 -0.0590281 -0.0768745 -0.1264 -0.0589288 -0.0768716 -0.12645 -0.0588297 -0.0768687 -0.1265 -0.0587306 -0.0768657 -0.12655 -0.0586317 -0.0768626 -0.1266 -0.0585329 -0.0768594 -0.12665 -0.0584343 -0.0768562 -0.1267 -0.0583357 -0.0768529 -0.12675 -0.0582373 -0.0768495 -0.1268 -0.058139 -0.0768461 -0.12685 -0.0580408 -0.0768426 -0.1269 -0.0579427 -0.076839 -0.12695 -0.0578447 -0.0768353 -0.127 -0.0577468 -0.0768316 -0.12705 -0.057649 -0.0768278 -0.1271 -0.0575512 -0.0768239 -0.12715 -0.0574535 -0.0768199 -0.1272 -0.0573559 -0.0768158 -0.12725 -0.0572584 -0.0768116 -0.1273 -0.0571608 -0.0768073 -0.12735 -0.0570634 -0.076803 -0.1274 -0.0569659 -0.0767985 -0.12745 -0.0568685 -0.076794 -0.1275 -0.056771 -0.0767894 -0.12755 -0.0566736 -0.0767846 -0.1276 -0.0565761 -0.0767798 -0.12765 -0.0564786 -0.0767748 -0.1277 -0.0563811 -0.0767698 -0.12775 -0.0562835 -0.0767646 -0.1278 -0.0561859 -0.0767593 -0.12785 -0.0560881 -0.076754 -0.1279 -0.0559903 -0.0767485 -0.12795 -0.0558923 -0.0767428 -0.128 -0.0557942 -0.0767371 -0.12805 -0.055696 -0.0767313 -0.1281 -0.0555976 -0.0767253 -0.12815 -0.055499 -0.0767192 -0.1282 -0.0554002 -0.0767129 -0.12825 -0.0553012 -0.0767066 -0.1283 -0.0552019 -0.0767001 -0.12835 -0.0551023 -0.0766935 -0.1284 -0.0550025 -0.0766867 -0.12845 -0.0549023 -0.0766798 -0.1285 -0.0548018 -0.0766728 -0.12855 -0.0547009 -0.0766656 -0.1286 -0.0545996 -0.0766583 -0.12865 -0.0544978 -0.0766508 -0.1287 -0.0543956 -0.0766432 -0.12875 -0.0542928 -0.0766354 -0.1288 -0.0541895 -0.0766275 -0.12885 -0.0540857 -0.0766195 -0.1289 -0.0539812 -0.0766112 -0.12895 -0.053876 -0.0766028 -0.129 -0.0537701 -0.0765943 -0.12905 -0.0536635 -0.0765856 -0.1291 -0.053556 -0.0765767 -0.12915 -0.0534476 -0.0765677 -0.1292 -0.0533384 -0.0765585 -0.12925 -0.0532281 -0.0765491 -0.1293 -0.0531168 -0.0765396 -0.12935 -0.0530043 -0.0765299 -0.1294 -0.0528906 -0.07652 -0.12945 -0.0527756 -0.07651 -0.1295 -0.0526593 -0.0764997 -0.12955 -0.0525414 -0.0764893 -0.1296 -0.052422 -0.0764787 -0.12965 -0.0523009 -0.076468 -0.1297 -0.052178 -0.076457 -0.12975 -0.0520532 -0.0764459 -0.1298 -0.0519263 -0.0764345 -0.12985 -0.0517971 -0.076423 -0.1299 -0.0516656 -0.0764113 -0.12995 -0.0515315 -0.0763994 -0.13 -0.0513947 -0.0763874 -0.13005 -0.0512549 -0.0763751 -0.1301 -0.0511119 -0.0763626 -0.13015 -0.0509655 -0.07635 -0.1302 -0.0508153 -0.0763371 -0.13025 -0.0506611 -0.0763241 -0.1303 -0.0505025 -0.0763108 -0.13035 -0.0503392 -0.0762974 -0.1304 -0.0501708 -0.0762837 -0.13045 -0.0499968 -0.0762699 -0.1305 -0.0498166 -0.0762558 -0.13055 -0.0496297 -0.0762416 -0.1306 -0.0494356 -0.0762271 -0.13065 -0.0492333 -0.0762124 -0.1307 -0.0490223 -0.0761976 -0.13075 -0.0488015 -0.0761825 -0.1308 -0.0485699 -0.0761672 -0.13085 -0.0483263 -0.0761517 -0.1309 -0.0480694 -0.076136 -0.13095 -0.0477977 -0.0761201 -0.131 -0.0475093 -0.076104 -0.13105 -0.0472022 -0.0760877 -0.1311 -0.0468741 -0.0760711 -0.13115 -0.046522 -0.0760544 -0.1312 -0.0461429 -0.0760374 -0.13125 -0.0457327 -0.0760202 -0.1313 -0.045287 -0.0760028 -0.13135 -0.0448002 -0.0759852 -0.1314 -0.0442659 -0.0759674 -0.13145 -0.0436761 -0.0759493 -0.1315 -0.0430212 -0.0759311 -0.13155 -0.0422895 -0.0759126 -0.1316 -0.0414667 -0.0758939 -0.13165 -0.0405348 -0.0758749 -0.1317 -0.0394718 -0.0758557 -0.13175 -0.03825 -0.0758364 -0.1318 -0.0368348 -0.0758167 -0.13185 -0.0351833 -0.0757969 -0.1319 -0.0332418 -0.0757768 -0.13195 -0.030945 -0.0757565 -0.132 -0.0282151 -0.0757359 -0.13205 -0.0249643 -0.0757151 -0.1321 -0.0211034 -0.0756941 -0.13215 -0.016561 -0.0756728 -0.1322 -0.0113194 -0.0756512 -0.13225 -0.0054674 -0.0756294 -0.1323 0.000744799 -0.0756074 -0.13235 0.00689151 -0.075585 -0.1324 0.0124443 -0.0755624 -0.13245 0.0169254 -0.0755395 -0.1325 0.0200556 -0.0755163 -0.13255 0.0218026 -0.0754928 -0.1326 0.0223214 -0.075469 -0.13265 0.0218539 -0.0754448 -0.1327 0.0206479 -0.0754203 -0.13275 0.0189153 -0.0753955 -0.1328 0.0168217 -0.0753702 -0.13285 0.0144897 -0.0753445 -0.1329 0.0120083 -0.0753183 -0.13295 0.00944129 -0.0752916 -0.133 0.00683424 -0.0752644 -0.13305 0.00421986 -0.0752364 -0.1331 0.00162145 -0.0752077 -0.13315 -0.000944509 -0.0751781 -0.1332 -0.00346651 -0.0751475 -0.13325 -0.00593676 -0.0751155 -0.1333 -0.00835024 -0.075082 -0.13335 -0.010704 -0.0750465 -0.1334 -0.0129966 -0.0750087 -0.13345 -0.015228 -0.0749679 -0.1335 -0.017399 -0.0749233 -0.13355 -0.0195113 -0.074874 -0.1336 -0.0215671 -0.0748188 -0.13365 -0.0235696 -0.0747562 -0.1337 -0.0255224 -0.0746843 -0.13375 -0.02743 -0.0746008 -0.1338 -0.0292975 -0.0745026 -0.13385 -0.0311308 -0.0743861 -0.1339 -0.0329363 -0.0742468 -0.13395 -0.0347211 -0.0740789 -0.134 -0.0364931 -0.0738756 -0.13405 -0.03826 -0.0736281 -0.1341 -0.0400299 -0.0733256 -0.13415 -0.0418103 -0.0729549 -0.1342 -0.0436077 -0.0724995 -0.13425 -0.0454269 -0.0719393 -0.1343 -0.0472697 -0.071249 -0.13435 -0.0491342 -0.0703978 -0.1344 -0.0510131 -0.0693471 -0.13445 -0.052893 -0.0680495 -0.1345 -0.0547536 -0.0664459 -0.13455 -0.0565687 -0.0644623 -0.1346 -0.0583075 -0.0620058 -0.13465 -0.0599385 -0.0589577 -0.1347 -0.0614334 -0.0551625 -0.13475 -0.0627712 -0.0504081 -0.1348 -0.0639411 -0.0443874 -0.13485 -0.0649426 -0.0366223 -0.1349 -0.0657843 -0.0263324 -0.13495 -0.0664811 -0.0123533 -0.135 -0.067051 0.00610967 -0.13505 -0.0675124 0.0261989 -0.1351 -0.0678829 0.0401528 -0.13515 -0.0681779 0.0453153 -0.1352 -0.0684105 0.0461534 -0.13525 -0.0685917 0.0457957 -0.1353 -0.0687303 0.0450644 -0.13535 -0.0688338 0.0441036 -0.1354 -0.0689079 0.0429425 -0.13545 -0.0689575 0.0415941 -0.1355 -0.0689866 0.04007 -0.13555 -0.0689983 0.038383 -0.1356 -0.0689954 0.0365475 -0.13565 -0.06898 0.0345792 -0.1357 -0.0689539 0.0324944 -0.13575 -0.0689188 0.0303097 -0.1358 -0.0688759 0.0280414 -0.13585 -0.0688263 0.0257048 -0.1359 -0.0687708 0.0233147 -0.13595 -0.0687104 0.0208842 -0.136 -0.0686457 0.0184255 -0.13605 -0.0685771 0.0159493 -0.1361 -0.0685053 0.0134647 -0.13615 -0.0684305 0.0109797 -0.1362 -0.0683532 0.00850099 -0.13625 -0.0682737 0.00603392 -0.1363 -0.0681921 0.00358279 -0.13635 -0.0681088 0.00115089 -0.1364 -0.0680239 -0.00125945 -0.13645 -0.0679375 -0.00364673 -0.1365 -0.0678499 -0.00601022 -0.13655 -0.0677612 -0.00834994 -0.1366 -0.0676713 -0.0106666 -0.13665 -0.0675806 -0.0129616 -0.1367 -0.0674889 -0.0152372 -0.13675 -0.0673964 -0.0174964 -0.1368 -0.0673032 -0.0197437 -0.13685 -0.0672093 -0.0219848 -0.1369 -0.0671148 -0.0242274 -0.13695 -0.0670197 -0.0264817 -0.137 -0.066924 -0.0287611 -0.13705 -0.0668278 -0.0310833 -0.1371 -0.0667311 -0.0334707 -0.13715 -0.0666339 -0.0359523 -0.1372 -0.0665363 -0.0385637 -0.13725 -0.0664383 -0.0413474 -0.1373 -0.0663399 -0.0443509 -0.13735 -0.0662412 -0.0476202 -0.1374 -0.0661421 -0.0511868 -0.13745 -0.0660426 -0.0550428 -0.1375 -0.0659428 -0.0591056 -0.13755 -0.0658428 -0.0631848 -0.1376 -0.0657424 -0.0669889 -0.13765 -0.0656418 -0.0702097 -0.1377 -0.065541 -0.0726589 -0.13775 -0.0654399 -0.0743425 -0.1378 -0.0653385 -0.0754112 -0.13785 -0.065237 -0.0760547 -0.1379 -0.0651352 -0.0764315 -0.13795 -0.0650333 -0.0766498 -0.138 -0.0649312 -0.0767765 -0.13805 -0.0648289 -0.0768506 -0.1381 -0.0647265 -0.0768944 -0.13815 -0.0646239 -0.0769205 -0.1382 -0.0645211 -0.0769362 -0.13825 -0.0644183 -0.0769457 -0.1383 -0.0643153 -0.0769514 -0.13835 -0.0642123 -0.0769547 -0.1384 -0.0641091 -0.0769565 -0.13845 -0.0640059 -0.0769573 -0.1385 -0.0639025 -0.0769575 -0.13855 -0.0637992 -0.0769573 -0.1386 -0.0636957 -0.0769568 -0.13865 -0.0635922 -0.0769562 -0.1387 -0.0634887 -0.0769553 -0.13875 -0.0633851 -0.0769544 -0.1388 -0.0632816 -0.0769534 -0.13885 -0.063178 -0.0769523 -0.1389 -0.0630744 -0.0769512 -0.13895 -0.0629708 -0.07695 -0.139 -0.0628672 -0.0769488 -0.13905 -0.0627637 -0.0769475 -0.1391 -0.0626601 -0.0769462 -0.13915 -0.0625567 -0.0769449 -0.1392 -0.0624532 -0.0769435 -0.13925 -0.0623498 -0.0769421 -0.1393 -0.0622465 -0.0769407 -0.13935 -0.0621432 -0.0769392 -0.1394 -0.06204 -0.0769377 -0.13945 -0.0619368 -0.0769361 -0.1395 -0.0618338 -0.0769346 -0.13955 -0.0617308 -0.076933 -0.1396 -0.0616279 -0.0769313 -0.13965 -0.0615251 -0.0769296 -0.1397 -0.0614224 -0.0769279 -0.13975 -0.0613199 -0.0769262 -0.1398 -0.0612174 -0.0769244 -0.13985 -0.061115 -0.0769225 -0.1399 -0.0610128 -0.0769207 -0.13995 -0.0609107 -0.0769188 -0.14 -0.0608087 -0.0769168 -0.14005 -0.0607069 -0.0769148 -0.1401 -0.0606052 -0.0769128 -0.14015 -0.0605036 -0.0769107 -0.1402 -0.0604021 -0.0769086 -0.14025 -0.0603008 -0.0769064 -0.1403 -0.0601997 -0.0769042 -0.14035 -0.0600987 -0.0769019 -0.1404 -0.0599978 -0.0768996 -0.14045 -0.0598971 -0.0768973 -0.1405 -0.0597965 -0.0768949 -0.14055 -0.0596961 -0.0768924 -0.1406 -0.0595958 -0.0768899 -0.14065 -0.0594956 -0.0768873 -0.1407 -0.0593956 -0.0768847 -0.14075 -0.0592958 -0.076882 -0.1408 -0.0591961 -0.0768793 -0.14085 -0.0590966 -0.0768765 -0.1409 -0.0589971 -0.0768736 -0.14095 -0.0588979 -0.0768707 -0.141 -0.0587987 -0.0768677 -0.14105 -0.0586997 -0.0768647 -0.1411 -0.0586009 -0.0768616 -0.14115 -0.0585021 -0.0768584 -0.1412 -0.0584035 -0.0768552 -0.14125 -0.058305 -0.0768519 -0.1413 -0.0582066 -0.0768485 -0.14135 -0.0581083 -0.076845 -0.1414 -0.0580102 -0.0768415 -0.14145 -0.0579121 -0.0768379 -0.1415 -0.0578141 -0.0768342 -0.14155 -0.0577163 -0.0768304 -0.1416 -0.0576185 -0.0768265 -0.14165 -0.0575207 -0.0768226 -0.1417 -0.0574231 -0.0768186 -0.14175 -0.0573255 -0.0768145 -0.1418 -0.0572279 -0.0768103 -0.14185 -0.0571304 -0.076806 -0.1419 -0.0570329 -0.0768016 -0.14195 -0.0569355 -0.0767971 -0.142 -0.056838 -0.0767926 -0.14205 -0.0567406 -0.0767879 -0.1421 -0.0566432 -0.0767831 -0.14215 -0.0565457 -0.0767782 -0.1422 -0.0564482 -0.0767733 -0.14225 -0.0563506 -0.0767682 -0.1423 -0.056253 -0.076763 -0.14235 -0.0561554 -0.0767577 -0.1424 -0.0560576 -0.0767523 -0.14245 -0.0559597 -0.0767467 -0.1425 -0.0558617 -0.0767411 -0.14255 -0.0557636 -0.0767353 -0.1426 -0.0556653 -0.0767294 -0.14265 -0.0555668 -0.0767234 -0.1427 -0.0554682 -0.0767172 -0.14275 -0.0553693 -0.076711 -0.1428 -0.0552702 -0.0767046 -0.14285 -0.0551709 -0.076698 -0.1429 -0.0550712 -0.0766914 -0.14295 -0.0549713 -0.0766846 -0.143 -0.054871 -0.0766776 -0.14305 -0.0547703 -0.0766706 -0.1431 -0.0546693 -0.0766633 -0.14315 -0.0545679 -0.076656 -0.1432 -0.054466 -0.0766485 -0.14325 -0.0543636 -0.0766408 -0.1433 -0.0542607 -0.076633 -0.14335 -0.0541572 -0.076625 -0.1434 -0.0540531 -0.0766169 -0.14345 -0.0539484 -0.0766086 -0.1435 -0.053843 -0.0766002 -0.14355 -0.0537369 -0.0765916 -0.1436 -0.05363 -0.0765829 -0.14365 -0.0535223 -0.0765739 -0.1437 -0.0534136 -0.0765649 -0.14375 -0.0533041 -0.0765556 -0.1438 -0.0531935 -0.0765462 -0.14385 -0.0530818 -0.0765366 -0.1439 -0.0529689 -0.0765268 -0.14395 -0.0528549 -0.0765169 -0.144 -0.0527395 -0.0765068 -0.14405 -0.0526227 -0.0764965 -0.1441 -0.0525043 -0.076486 -0.14415 -0.0523844 -0.0764754 -0.1442 -0.0522628 -0.0764646 -0.14425 -0.0521393 -0.0764535 -0.1443 -0.0520138 -0.0764424 -0.14435 -0.0518862 -0.076431 -0.1444 -0.0517564 -0.0764194 -0.14445 -0.0516241 -0.0764076 -0.1445 -0.0514891 -0.0763957 -0.14455 -0.0513514 -0.0763836 -0.1446 -0.0512106 -0.0763712 -0.14465 -0.0510666 -0.0763587 -0.1447 -0.050919 -0.076346 -0.14475 -0.0507676 -0.0763331 -0.1448 -0.0506121 -0.0763199 -0.14485 -0.0504521 -0.0763066 -0.1449 -0.0502872 -0.0762931 -0.14495 -0.0501171 -0.0762794 -0.145 -0.0499412 -0.0762655 -0.14505 -0.049759 -0.0762514 -0.1451 -0.0495699 -0.0762371 -0.14515 -0.0493733 -0.0762225 -0.1452 -0.0491685 -0.0762078 -0.14525 -0.0489545 -0.0761929 -0.1453 -0.0487304 -0.0761777 -0.14535 -0.0484952 -0.0761624 -0.1454 -0.0482476 -0.0761468 -0.14545 -0.0479863 -0.0761311 -0.1455 -0.0477095 -0.0761151 -0.14555 -0.0474156 -0.0760989 -0.1456 -0.0471022 -0.0760825 -0.14565 -0.0467669 -0.0760659 -0.1457 -0.0464068 -0.0760491 -0.14575 -0.0460184 -0.0760321 -0.1458 -0.0455977 -0.0760148 -0.14585 -0.0451398 -0.0759974 -0.1459 -0.0446389 -0.0759797 -0.14595 -0.0440882 -0.0759618 -0.146 -0.0434792 -0.0759437 -0.14605 -0.0428017 -0.0759253 -0.1461 -0.0420433 -0.0759067 -0.14615 -0.0411885 -0.075888 -0.1462 -0.0402183 -0.075869 -0.14625 -0.0391089 -0.0758497 -0.1463 -0.0378309 -0.0758303 -0.14635 -0.036347 -0.0758106 -0.1464 -0.0346113 -0.0757906 -0.14645 -0.0325665 -0.0757705 -0.1465 -0.0301435 -0.0757501 -0.14655 -0.0272607 -0.0757295 -0.1466 -0.0238287 -0.0757086 -0.14665 -0.0197612 -0.0756875 -0.1467 -0.0149986 -0.0756661 -0.14675 -0.00955029 -0.0756445 -0.1468 -0.00355042 -0.0756226 -0.14685 0.00269424 -0.0756004 -0.1469 0.00871338 -0.075578 -0.14695 0.0139759 -0.0755553 -0.147 0.0180536 -0.0755323 -0.14705 0.0207449 -0.075509 -0.1471 0.0220859 -0.0754854 -0.14715 0.0222693 -0.0754615 -0.1472 0.0215459 -0.0754372 -0.14725 0.0201549 -0.0754126 -0.1473 0.0182941 -0.0753876 -0.14735 0.0161147 -0.0753622 -0.1474 0.0137279 -0.0753364 -0.14745 0.0112139 -0.0753101 -0.1475 0.00863014 -0.0752832 -0.14755 0.0060178 -0.0752557 -0.1476 0.00340627 -0.0752275 -0.14765 0.000816476 -0.0751986 -0.1477 -0.0017368 -0.0751687 -0.14775 -0.00424334 -0.0751376 -0.1478 -0.0066963 -0.0751052 -0.14785 -0.00909137 -0.0750712 -0.1479 -0.0114261 -0.075035 -0.14795 -0.0136996 -0.0749963 -0.148 -0.0159121 -0.0749544 -0.14805 -0.0180645 -0.0749084 -0.1481 -0.0201588 -0.0748575 -0.14815 -0.0221977 -0.0748002 -0.1482 -0.0241842 -0.0747349 -0.14825 -0.0261224 -0.0746596 -0.1483 -0.028017 -0.0745718 -0.14835 -0.0298731 -0.0744684 -0.1484 -0.0316969 -0.0743453 -0.14845 -0.0334952 -0.0741978 -0.1485 -0.0352752 -0.0740197 -0.14855 -0.0370447 -0.0738035 -0.1486 -0.0388117 -0.0735401 -0.14865 -0.0405841 -0.0732179 -0.1487 -0.0423692 -0.0728227 -0.14875 -0.044173 -0.072337 -0.1488 -0.0459995 -0.0717391 -0.14885 -0.0478495 -0.0710023 -0.1489 -0.0497196 -0.0700933 -0.14895 -0.0516006 -0.0689712 -0.149 -0.0534769 -0.067585 -0.14905 -0.0553264 -0.0658715 -0.1491 -0.0571211 -0.0637513 -0.14915 -0.0588296 -0.0611244 -0.1492 -0.0604209 -0.057862 -0.14925 -0.0618685 -0.0537936 -0.1493 -0.0631546 -0.048683 -0.14935 -0.0642715 -0.0421803 -0.1494 -0.0652218 -0.0337294 -0.14945 -0.0660166 -0.0224266 -0.1495 -0.0666717 -0.00705544 -0.14955 -0.0672058 0.0125199 -0.1496 -0.067637 0.0315537 -0.14965 -0.0679824 0.0425458 -0.1497 -0.0682566 0.0458273 -0.14975 -0.0684721 0.0461053 -0.1498 -0.0686391 0.045596 -0.14985 -0.0687661 0.0447871 -0.1499 -0.0688598 0.043762 -0.14995 -0.0689258 0.0425413 -0.15 -0.0689687 0.0411367 -0.15005 -0.068992 0.0395603 -0.1501 -0.0689989 0.0378253 -0.15015 -0.0689918 0.0359466 -0.1502 -0.0689729 0.0339402 -0.15025 -0.0689439 0.0318225 -0.1503 -0.0689062 0.02961 -0.15035 -0.0688611 0.0273187 -0.1504 -0.0688095 0.0249639 -0.15045 -0.0687525 0.0225598 -0.1505 -0.0686907 0.0201193 -0.15055 -0.0686247 0.0176541 -0.1506 -0.068555 0.0151743 -0.15065 -0.0684822 0.0126888 -0.1507 -0.0684066 0.0102051 -0.15075 -0.0683286 0.00772952 -0.1508 -0.0682484 0.00526701 -0.15085 -0.0681663 0.00282158 -0.1509 -0.0680824 0.000396195 -0.15095 -0.0679971 -0.00200707 -0.151 -0.0679103 -0.00438697 -0.15105 -0.0678223 -0.00674301 -0.1511 -0.0677332 -0.00907542 -0.15115 -0.0676431 -0.0113851 -0.1512 -0.067552 -0.0136738 -0.15125 -0.0674601 -0.0159439 -0.1513 -0.0673674 -0.0181989 -0.15135 -0.067274 -0.0204436 -0.1514 -0.0671799 -0.0226842 -0.15145 -0.0670852 -0.0249292 -0.1515 -0.0669899 -0.0271897 -0.15155 -0.066894 -0.0294804 -0.1516 -0.0667977 -0.0318202 -0.15165 -0.0667008 -0.0342336 -0.1517 -0.0666035 -0.0367516 -0.15175 -0.0665058 -0.0394119 -0.1518 -0.0664077 -0.042259 -0.15185 -0.0663091 -0.0453408 -0.1519 -0.0662103 -0.0487008 -0.15195 -0.0661111 -0.0523613 -0.152 -0.0660115 -0.0562953 -0.15205 -0.0659117 -0.0603891 -0.1521 -0.0658115 -0.064417 -0.15215 -0.0657111 -0.0680691 -0.1522 -0.0656104 -0.0710606 -0.15225 -0.0655094 -0.0732614 -0.1523 -0.0654083 -0.074733 -0.15235 -0.0653069 -0.0756493 -0.1524 -0.0652053 -0.0761949 -0.15245 -0.0651034 -0.0765128 -0.1525 -0.0650014 -0.0766969 -0.15255 -0.0648993 -0.076804 -0.1526 -0.0647969 -0.0768668 -0.15265 -0.0646944 -0.076904 -0.1527 -0.0645918 -0.0769263 -0.15275 -0.064489 -0.0769397 -0.1528 -0.0643862 -0.0769478 -0.15285 -0.0642832 -0.0769526 -0.1529 -0.0641801 -0.0769553 -0.15295 -0.0640769 -0.0769568 -0.153 -0.0639736 -0.0769574 -0.15305 -0.0638703 -0.0769575 -0.1531 -0.0637669 -0.0769572 -0.15315 -0.0636634 -0.0769567 -0.1532 -0.0635599 -0.0769559 -0.15325 -0.0634564 -0.0769551 -0.1533 -0.0633528 -0.0769541 -0.15335 -0.0632492 -0.0769531 -0.1534 -0.0631457 -0.076952 -0.15345 -0.0630421 -0.0769508 -0.1535 -0.0629385 -0.0769496 -0.15355 -0.0628349 -0.0769484 -0.1536 -0.0627314 -0.0769471 -0.15365 -0.0626278 -0.0769458 -0.1537 -0.0625244 -0.0769444 -0.15375 -0.0624209 -0.0769431 -0.1538 -0.0623175 -0.0769416 -0.15385 -0.0622142 -0.0769402 -0.1539 -0.062111 -0.0769387 -0.15395 -0.0620078 -0.0769372 -0.154 -0.0619046 -0.0769357 -0.15405 -0.0618016 -0.0769341 -0.1541 -0.0616987 -0.0769325 -0.15415 -0.0615958 -0.0769308 -0.1542 -0.0614931 -0.0769291 -0.15425 -0.0613904 -0.0769274 -0.1543 -0.0612879 -0.0769256 -0.15435 -0.0611854 -0.0769238 -0.1544 -0.0610831 -0.076922 -0.15445 -0.0609809 -0.0769201 -0.1545 -0.0608789 -0.0769182 -0.15455 -0.0607769 -0.0769162 -0.1546 -0.0606751 -0.0769142 -0.15465 -0.0605734 -0.0769121 -0.1547 -0.0604719 -0.0769101 -0.15475 -0.0603705 -0.0769079 -0.1548 -0.0602693 -0.0769057 -0.15485 -0.0601681 -0.0769035 -0.1549 -0.0600672 -0.0769012 -0.15495 -0.0599663 -0.0768989 -0.155 -0.0598657 -0.0768965 -0.15505 -0.0597651 -0.0768941 -0.1551 -0.0596647 -0.0768916 -0.15515 -0.0595645 -0.0768891 -0.1552 -0.0594644 -0.0768865 -0.15525 -0.0593645 -0.0768839 -0.1553 -0.0592647 -0.0768812 -0.15535 -0.059165 -0.0768784 -0.1554 -0.0590655 -0.0768756 -0.15545 -0.0589661 -0.0768727 -0.1555 -0.0588669 -0.0768698 -0.15555 -0.0587678 -0.0768668 -0.1556 -0.0586688 -0.0768637 -0.15565 -0.05857 -0.0768606 -0.1557 -0.0584713 -0.0768574 -0.15575 -0.0583727 -0.0768541 -0.1558 -0.0582743 -0.0768508 -0.15585 -0.0581759 -0.0768474 -0.1559 -0.0580777 -0.0768439 -0.15595 -0.0579796 -0.0768404 -0.156 -0.0578815 -0.0768367 -0.15605 -0.0577836 -0.076833 -0.1561 -0.0576857 -0.0768292 -0.15615 -0.0575879 -0.0768253 -0.1562 -0.0574902 -0.0768214 -0.15625 -0.0573926 -0.0768173 -0.1563 -0.057295 -0.0768132 -0.15635 -0.0571975 -0.076809 -0.1564 -0.0571 -0.0768046 -0.15645 -0.0570025 -0.0768002 -0.1565 -0.0569051 -0.0767957 -0.15655 -0.0568076 -0.0767911 -0.1566 -0.0567102 -0.0767864 -0.15665 -0.0566127 -0.0767816 -0.1567 -0.0565153 -0.0767767 -0.15675 -0.0564178 -0.0767717 -0.1568 -0.0563202 -0.0767666 -0.15685 -0.0562226 -0.0767613 -0.1569 -0.0561249 -0.076756 -0.15695 -0.0560271 -0.0767505 -0.157 -0.0559291 -0.076745 -0.15705 -0.0558311 -0.0767393 -0.1571 -0.0557329 -0.0767335 -0.15715 -0.0556346 -0.0767275 -0.1572 -0.0555361 -0.0767215 -0.15725 -0.0554374 -0.0767153 -0.1573 -0.0553384 -0.076709 -0.15735 -0.0552392 -0.0767026 -0.1574 -0.0551398 -0.076696 -0.15745 -0.0550401 -0.0766893 -0.1575 -0.05494 -0.0766824 -0.15755 -0.0548396 -0.0766754 -0.1576 -0.0547388 -0.0766683 -0.15765 -0.0546377 -0.0766611 -0.1577 -0.0545361 -0.0766536 -0.15775 -0.054434 -0.0766461 -0.1578 -0.0543315 -0.0766384 -0.15785 -0.0542284 -0.0766305 -0.1579 -0.0541248 -0.0766225 -0.15795 -0.0540205 -0.0766143 -0.158 -0.0539156 -0.076606 -0.15805 -0.05381 -0.0765975 -0.1581 -0.0537036 -0.0765889 -0.15815 -0.0535965 -0.0765801 -0.1582 -0.0534885 -0.0765711 -0.15825 -0.0533795 -0.076562 -0.1583 -0.0532697 -0.0765527 -0.15835 -0.0531587 -0.0765432 -0.1584 -0.0530467 -0.0765336 -0.15845 -0.0529335 -0.0765238 -0.1585 -0.052819 -0.0765138 -0.15855 -0.0527032 -0.0765036 -0.1586 -0.0525859 -0.0764933 -0.15865 -0.0524671 -0.0764827 -0.1587 -0.0523466 -0.076472 -0.15875 -0.0522244 -0.0764611 -0.1588 -0.0521003 -0.0764501 -0.15885 -0.0519742 -0.0764388 -0.1589 -0.0518459 -0.0764274 -0.15895 -0.0517153 -0.0764157 -0.159 -0.0515822 -0.0764039 -0.15905 -0.0514465 -0.0763919 -0.1591 -0.0513078 -0.0763797 -0.15915 -0.051166 -0.0763673 -0.1592 -0.0510209 -0.0763547 -0.15925 -0.0508722 -0.076342 -0.1593 -0.0507195 -0.076329 -0.15935 -0.0505627 -0.0763158 -0.1594 -0.0504012 -0.0763024 -0.15945 -0.0502347 -0.0762889 -0.1595 -0.0500628 -0.0762751 -0.15955 -0.049885 -0.0762611 -0.1596 -0.0497008 -0.0762469 -0.15965 -0.0495094 -0.0762326 -0.1597 -0.0493103 -0.076218 -0.15975 -0.0491027 -0.0762032 -0.1598 -0.0488857 -0.0761882 -0.15985 -0.0486582 -0.076173 -0.1599 -0.0484193 -0.0761576 -0.15995 -0.0481676 -0.0761419 -0.16 -0.0479016 -0.0761261 -0.16005 -0.0476197 -0.0761101 -0.1601 -0.0473199 -0.0760938 -0.16015 -0.047 -0.0760774 -0.1602 -0.0466573 -0.0760607 -0.16025 -0.0462888 -0.0760438 -0.1603 -0.0458908 -0.0760267 -0.16035 -0.045459 -0.0760094 -0.1604 -0.0449884 -0.0759919 -0.16045 -0.0444727 -0.0759741 -0.1605 -0.0439048 -0.0759561 -0.16055 -0.0432756 -0.0759379 -0.1606 -0.0425743 -0.0759195 -0.16065 -0.0417876 -0.0759009 -0.1607 -0.0408991 -0.0758821 -0.16075 -0.0398882 -0.075863 -0.1608 -0.0387297 -0.0758437 -0.16085 -0.0373918 -0.0758241 -0.1609 -0.0358348 -0.0758044 -0.16095 -0.0340093 -0.0757844 -0.161 -0.0318545 -0.0757641 -0.16105 -0.0292972 -0.0757437 -0.1611 -0.0262528 -0.075723 -0.16115 -0.0226311 -0.075702 -0.1612 -0.0183507 -0.0756808 -0.16125 -0.0133685 -0.0756594 -0.1613 -0.00772615 -0.0756376 -0.16135 -0.0016083 -0.0756157 -0.1614 0.00462223 -0.0755934 -0.16145 0.0104608 -0.0755709 -0.1615 0.0153903 -0.0755481 -0.16155 0.0190449 -0.0755251 -0.1616 0.0213015 -0.0755017 -0.16165 0.022256 -0.075478 -0.1617 0.022129 -0.075454 -0.16175 0.0211732 -0.0754296 -0.1618 0.0196166 -0.0754049 -0.16185 0.0176422 -0.0753797 -0.1619 0.0153877 -0.0753542 -0.16195 0.0129538 -0.0753282 -0.162 0.0104127 -0.0753017 -0.16205 0.00781629 -0.0752747 -0.1621 0.0052015 -0.075247 -0.16215 0.00259483 -0.0752186 -0.1622 1.50943e-05 -0.0751894 -0.16225 -0.00252452 -0.0751591 -0.1623 -0.00501494 -0.0751277 -0.16235 -0.00745019 -0.0750948 -0.1624 -0.00982661 -0.0750601 -0.16245 -0.0121423 -0.0750232 -0.1625 -0.0143967 -0.0749836 -0.16255 -0.0165902 -0.0749405 -0.1626 -0.0187243 -0.0748931 -0.16265 -0.020801 -0.0748403 -0.1627 -0.0228231 -0.0747807 -0.16275 -0.0247941 -0.0747126 -0.1628 -0.0267182 -0.0746337 -0.16285 -0.0286001 -0.0745414 -0.1629 -0.0304455 -0.0744323 -0.16295 -0.0322606 -0.0743021 -0.163 -0.0340524 -0.0741458 -0.16305 -0.0358282 -0.0739567 -0.1631 -0.0375961 -0.0737269 -0.16315 -0.039364 -0.0734465 -0.1632 -0.0411396 -0.0731031 -0.16325 -0.0429299 -0.0726818 -0.1633 -0.0447405 -0.0721636 -0.16335 -0.0465745 -0.0715255 -0.1634 -0.0484314 -0.0707388 -0.16345 -0.0503061 -0.0697681 -0.1635 -0.0521876 -0.0685696 -0.16355 -0.0540583 -0.0670887 -0.1636 -0.0558939 -0.0652577 -0.16365 -0.0576651 -0.0629913 -0.1637 -0.0593402 -0.0601814 -0.16375 -0.0608891 -0.0566882 -0.1638 -0.0622879 -0.052324 -0.16385 -0.0635214 -0.0468237 -0.1639 -0.0645856 -0.039786 -0.16395 -0.0654859 -0.0305619 -0.164 -0.0662352 -0.0181204 -0.16405 -0.0668505 -0.00130892 -0.1641 -0.0673506 0.0189177 -0.16415 -0.0677533 0.0360395 -0.1642 -0.068075 0.0441573 -0.16425 -0.0683296 0.0460749 -0.1643 -0.068529 0.0459918 -0.16435 -0.0686827 0.0453692 -0.1644 -0.0687986 0.044489 -0.16445 -0.0688832 0.0434014 -0.1645 -0.0689415 0.0421221 -0.16455 -0.0689779 0.0406626 -0.1646 -0.0689958 0.0390351 -0.16465 -0.0689981 0.0372536 -0.1647 -0.0689871 0.0353334 -0.16475 -0.0689648 0.0332904 -0.1648 -0.068933 0.0311414 -0.16485 -0.0688928 0.0289026 -0.1649 -0.0688456 0.0265899 -0.16495 -0.0687923 0.0242182 -0.165 -0.0687337 0.0218015 -0.16505 -0.0686705 0.0193521 -0.1651 -0.0686033 0.0168812 -0.16515 -0.0685326 0.0143988 -0.1652 -0.0684589 0.0119131 -0.16525 -0.0683825 0.00943135 -0.1653 -0.0683038 0.00695933 -0.16535 -0.068223 0.00450177 -0.1654 -0.0681403 0.00206232 -0.16545 -0.0680559 -0.00035633 -0.1655 -0.0679701 -0.0027524 -0.16555 -0.067883 -0.00512488 -0.1656 -0.0677946 -0.00747348 -0.16565 -0.0677052 -0.00979867 -0.1657 -0.0676148 -0.0121016 -0.16575 -0.0675234 -0.0143841 -0.1658 -0.0674313 -0.0166491 -0.16585 -0.0673383 -0.0189003 -0.1659 -0.0672447 -0.021143 -0.16595 -0.0671504 -0.0233839 -0.166 -0.0670555 -0.0256324 -0.16605 -0.06696 -0.0279006 -0.1661 -0.066864 -0.0302043 -0.16615 -0.0667675 -0.0325642 -0.1662 -0.0666705 -0.0350066 -0.16625 -0.0665731 -0.0375646 -0.1663 -0.0664752 -0.0402782 -0.16635 -0.066377 -0.0431934 -0.1664 -0.0662783 -0.0463579 -0.16645 -0.0661793 -0.0498109 -0.1665 -0.06608 -0.053563 -0.16655 -0.0659804 -0.0575642 -0.1666 -0.0658804 -0.0616669 -0.16665 -0.0657802 -0.0656124 -0.1667 -0.0656797 -0.0690838 -0.16675 -0.0655789 -0.0718329 -0.1668 -0.0654779 -0.073792 -0.16685 -0.0653766 -0.0750694 -0.1669 -0.0652752 -0.0758516 -0.16695 -0.0651735 -0.0763133 -0.167 -0.0650716 -0.0765814 -0.16705 -0.0649696 -0.0767367 -0.1671 -0.0648674 -0.0768273 -0.16715 -0.064765 -0.0768805 -0.1672 -0.0646624 -0.0769122 -0.16725 -0.0645598 -0.0769312 -0.1673 -0.064457 -0.0769427 -0.16735 -0.064354 -0.0769496 -0.1674 -0.064251 -0.0769536 -0.16745 -0.0641479 -0.0769559 -0.1675 -0.0640447 -0.0769571 -0.16755 -0.0639414 -0.0769575 -0.1676 -0.063838 -0.0769574 -0.16765 -0.0637346 -0.0769571 -0.1677 -0.0636311 -0.0769564 -0.16775 -0.0635276 -0.0769557 -0.1678 -0.0634241 -0.0769548 -0.16785 -0.0633205 -0.0769538 -0.1679 -0.0632169 -0.0769527 -0.16795 -0.0631133 -0.0769516 -0.168 -0.0630097 -0.0769504 -0.16805 -0.0629061 -0.0769492 -0.1681 -0.0628026 -0.076948 -0.16815 -0.062699 -0.0769467 -0.1682 -0.0625955 -0.0769454 -0.16825 -0.0624921 -0.076944 -0.1683 -0.0623887 -0.0769426 -0.16835 -0.0622853 -0.0769412 -0.1684 -0.062182 -0.0769397 -0.16845 -0.0620787 -0.0769382 -0.1685 -0.0619756 -0.0769367 -0.16855 -0.0618725 -0.0769352 -0.1686 -0.0617695 -0.0769336 -0.16865 -0.0616666 -0.0769319 -0.1687 -0.0615637 -0.0769303 -0.16875 -0.061461 -0.0769286 -0.1688 -0.0613584 -0.0769268 -0.16885 -0.0612559 -0.0769251 -0.1689 -0.0611535 -0.0769232 -0.16895 -0.0610512 -0.0769214 -0.169 -0.0609491 -0.0769195 -0.16905 -0.060847 -0.0769176 -0.1691 -0.0607451 -0.0769156 -0.16915 -0.0606434 -0.0769136 -0.1692 -0.0605417 -0.0769115 -0.16925 -0.0604402 -0.0769094 -0.1693 -0.0603389 -0.0769072 -0.16935 -0.0602377 -0.076905 -0.1694 -0.0601366 -0.0769028 -0.16945 -0.0600357 -0.0769005 -0.1695 -0.0599349 -0.0768982 -0.16955 -0.0598343 -0.0768958 -0.1696 -0.0597338 -0.0768933 -0.16965 -0.0596334 -0.0768908 -0.1697 -0.0595333 -0.0768883 -0.16975 -0.0594332 -0.0768857 -0.1698 -0.0593333 -0.076883 -0.16985 -0.0592336 -0.0768803 -0.1699 -0.0591339 -0.0768775 -0.16995 -0.0590345 -0.0768747 -0.17 -0.0589352 -0.0768718 -0.17005 -0.058836 -0.0768689 -0.1701 -0.0587369 -0.0768658 -0.17015 -0.058638 -0.0768628 -0.1702 -0.0585392 -0.0768596 -0.17025 -0.0584405 -0.0768564 -0.1703 -0.058342 -0.0768531 -0.17035 -0.0582436 -0.0768497 -0.1704 -0.0581453 -0.0768463 -0.17045 -0.058047 -0.0768428 -0.1705 -0.0579489 -0.0768392 -0.17055 -0.0578509 -0.0768356 -0.1706 -0.057753 -0.0768318 -0.17065 -0.0576552 -0.076828 -0.1707 -0.0575574 -0.0768241 -0.17075 -0.0574598 -0.0768201 -0.1708 -0.0573621 -0.076816 -0.17085 -0.0572646 -0.0768119 -0.1709 -0.057167 -0.0768076 -0.17095 -0.0570696 -0.0768033 -0.171 -0.0569721 -0.0767988 -0.17105 -0.0568747 -0.0767943 -0.1711 -0.0567772 -0.0767897 -0.17115 -0.0566798 -0.0767849 -0.1712 -0.0565823 -0.0767801 -0.17125 -0.0564848 -0.0767751 -0.1713 -0.0563873 -0.0767701 -0.17135 -0.0562897 -0.0767649 -0.1714 -0.0561921 -0.0767597 -0.17145 -0.0560943 -0.0767543 -0.1715 -0.0559965 -0.0767488 -0.17155 -0.0558986 -0.0767432 -0.1716 -0.0558005 -0.0767375 -0.17165 -0.0557023 -0.0767316 -0.1717 -0.0556039 -0.0767257 -0.17175 -0.0555053 -0.0767196 -0.1718 -0.0554065 -0.0767133 -0.17185 -0.0553075 -0.076707 -0.1719 -0.0552082 -0.0767005 -0.17195 -0.0551087 -0.0766939 -0.172 -0.0550089 -0.0766871 -0.17205 -0.0549087 -0.0766803 -0.1721 -0.0548082 -0.0766732 -0.17215 -0.0547073 -0.0766661 -0.1722 -0.054606 -0.0766588 -0.17225 -0.0545043 -0.0766513 -0.1723 -0.0544021 -0.0766437 -0.17235 -0.0542994 -0.0766359 -0.1724 -0.0541961 -0.076628 -0.17245 -0.0540923 -0.07662 -0.1725 -0.0539878 -0.0766118 -0.17255 -0.0538827 -0.0766034 -0.1726 -0.0537769 -0.0765949 -0.17265 -0.0536703 -0.0765862 -0.1727 -0.0535629 -0.0765773 -0.17275 -0.0534546 -0.0765683 -0.1728 -0.0533454 -0.0765591 -0.17285 -0.0532351 -0.0765497 -0.1729 -0.0531239 -0.0765402 -0.17295 -0.0530115 -0.0765305 -0.173 -0.0528979 -0.0765207 -0.17305 -0.052783 -0.0765106 -0.1731 -0.0526667 -0.0765004 -0.17315 -0.052549 -0.07649 -0.1732 -0.0524297 -0.0764794 -0.17325 -0.0523087 -0.0764687 -0.1733 -0.0521859 -0.0764577 -0.17335 -0.0520612 -0.0764466 -0.1734 -0.0519344 -0.0764353 -0.17345 -0.0518054 -0.0764238 -0.1735 -0.0516741 -0.0764121 -0.17355 -0.0515402 -0.0764002 -0.1736 -0.0514035 -0.0763881 -0.17365 -0.0512639 -0.0763759 -0.1737 -0.0511211 -0.0763634 -0.17375 -0.0509749 -0.0763508 -0.1738 -0.050825 -0.0763379 -0.17385 -0.050671 -0.0763249 -0.1739 -0.0505128 -0.0763117 -0.17395 -0.0503498 -0.0762982 -0.174 -0.0501817 -0.0762846 -0.17405 -0.050008 -0.0762707 -0.1741 -0.0498282 -0.0762567 -0.17415 -0.0496418 -0.0762425 -0.1742 -0.0494482 -0.076228 -0.17425 -0.0492465 -0.0762134 -0.1743 -0.049036 -0.0761985 -0.17435 -0.0488158 -0.0761835 -0.1744 -0.048585 -0.0761682 -0.17445 -0.0483422 -0.0761527 -0.1745 -0.0480862 -0.076137 -0.17455 -0.0478154 -0.0761211 -0.1746 -0.0475282 -0.076105 -0.17465 -0.0472224 -0.0760887 -0.1747 -0.0468956 -0.0760722 -0.17475 -0.0465452 -0.0760554 -0.1748 -0.0461679 -0.0760385 -0.17485 -0.0457599 -0.0760213 -0.1749 -0.0453165 -0.0760039 -0.17495 -0.0448326 -0.0759863 -0.175 -0.0443015 -0.0759685 -0.17505 -0.0437155 -0.0759505 -0.1751 -0.0430651 -0.0759322 -0.17515 -0.0423387 -0.0759137 -0.1752 -0.0415221 -0.075895 -0.17525 -0.0405978 -0.0758761 -0.1753 -0.0395439 -0.075857 -0.17535 -0.0383331 -0.0758376 -0.1754 -0.0369315 -0.075818 -0.17545 -0.0352965 -0.0757982 -0.1755 -0.0333753 -0.0757781 -0.17555 -0.0311033 -0.0757578 -0.1756 -0.0284035 -0.0757372 -0.17565 -0.0251886 -0.0757164 -0.1757 -0.021369 -0.0756954 -0.17575 -0.0168713 -0.0756741 -0.1758 -0.011673 -0.0756526 -0.17585 -0.00585431 -0.0756308 -0.1759 0.000345945 -0.0756088 -0.17595 0.00651217 -0.0755864 -0.176 0.0121184 -0.0755639 -0.17605 0.0166787 -0.075541 -0.1761 0.0198984 -0.0755178 -0.17615 0.0217303 -0.0754943 -0.1762 0.0223205 -0.0754705 -0.17625 0.0219082 -0.0754464 -0.1763 0.0207423 -0.0754219 -0.17635 0.0190379 -0.0753971 -0.1764 0.0169632 -0.0753718 -0.17645 0.0146435 -0.0753461 -0.1765 0.0121695 -0.07532 -0.17655 0.00960633 -0.0752933 -0.1766 0.00700074 -0.0752661 -0.17665 0.00438605 -0.0752382 -0.1767 0.00178606 -0.0752096 -0.17675 -0.000782349 -0.07518 -0.1768 -0.00330742 -0.0751494 -0.17685 -0.00578114 -0.0751176 -0.1769 -0.00819833 -0.0750842 -0.17695 -0.0105559 -0.0750489 -0.177 -0.0128525 -0.0750112 -0.17705 -0.0150878 -0.0749706 -0.1771 -0.0172626 -0.0749262 -0.17715 -0.0193785 -0.0748773 -0.1772 -0.0214378 -0.0748225 -0.17725 -0.0234436 -0.0747605 -0.1773 -0.0253995 -0.0746892 -0.17735 -0.0273098 -0.0746065 -0.1774 -0.0291797 -0.0745093 -0.17745 -0.031015 -0.0743941 -0.1775 -0.032822 -0.0742564 -0.17755 -0.034608 -0.0740906 -0.1776 -0.0363805 -0.0738898 -0.17765 -0.0381475 -0.0736453 -0.1777 -0.039917 -0.0733467 -0.17775 -0.0416965 -0.0729808 -0.1778 -0.0434927 -0.0725314 -0.17785 -0.0453103 -0.0719785 -0.1779 -0.0471517 -0.0712974 -0.17795 -0.049015 -0.0704575 -0.178 -0.0508933 -0.0694208 -0.17805 -0.0527736 -0.0681406 -0.1781 -0.0546362 -0.0665584 -0.17815 -0.0564551 -0.0646016 -0.1782 -0.0581997 -0.0621784 -0.17825 -0.0598385 -0.0591722 -0.1783 -0.0613427 -0.0554301 -0.17835 -0.062691 -0.0507446 -0.1784 -0.0638717 -0.0448165 -0.17845 -0.0648837 -0.0371817 -0.1785 -0.0657352 -0.0270836 -0.17855 -0.0664407 -0.013377 -0.1786 -0.0670181 0.00482233 -0.17865 -0.0674859 0.0250182 -0.1787 -0.0678617 0.0395546 -0.17875 -0.0681611 0.0451671 -0.1788 -0.0683973 0.0461524 -0.17885 -0.0685815 0.0458326 -0.1789 -0.0687226 0.0451183 -0.17895 -0.0688281 0.0441709 -0.179 -0.068904 0.0430222 -0.17905 -0.068955 0.0416853 -0.1791 -0.0689853 0.040172 -0.17915 -0.068998 0.0384949 -0.1792 -0.068996 0.0366685 -0.17925 -0.0689813 0.0347081 -0.1793 -0.0689559 0.0326303 -0.17935 -0.0689213 0.0304515 -0.1794 -0.0688788 0.028188 -0.17945 -0.0688296 0.0258553 -0.1795 -0.0687745 0.0234682 -0.17955 -0.0687144 0.0210399 -0.1796 -0.0686499 0.0185827 -0.17965 -0.0685816 0.0161073 -0.1797 -0.0685099 0.013623 -0.17975 -0.0684354 0.0111378 -0.1798 -0.0683582 0.00865851 -0.17985 -0.0682788 0.00619055 -0.1799 -0.0681973 0.00373831 -0.17995 -0.0681141 0.0013051 -0.18 -0.0680293 -0.00110666 -0.18005 -0.0679431 -0.00349544 -0.1801 -0.0678555 -0.00586046 -0.18015 -0.0677668 -0.00820168 -0.1802 -0.0676771 -0.0105198 -0.18025 -0.0675864 -0.0128161 -0.1803 -0.0674948 -0.0150928 -0.18035 -0.0674024 -0.017353 -0.1804 -0.0673092 -0.0196009 -0.18045 -0.0672153 -0.0218422 -0.1805 -0.0671209 -0.0240844 -0.18055 -0.0670258 -0.0263376 -0.1806 -0.0669301 -0.0286149 -0.18065 -0.0668339 -0.0309337 -0.1807 -0.0667373 -0.0333162 -0.18075 -0.0666401 -0.0357909 -0.1808 -0.0665426 -0.0383928 -0.18085 -0.0664446 -0.0411642 -0.1809 -0.0663462 -0.0441522 -0.18095 -0.0662475 -0.0474034 -0.181 -0.0661484 -0.0509507 -0.18105 -0.066049 -0.0547898 -0.1811 -0.0659492 -0.0588438 -0.18115 -0.0658492 -0.0629299 -0.1812 -0.0657488 -0.0667611 -0.18125 -0.0656483 -0.0700266 -0.1813 -0.0655474 -0.0725268 -0.18135 -0.0654463 -0.0742556 -0.1814 -0.065345 -0.0753577 -0.18145 -0.0652435 -0.0760231 -0.1815 -0.0651417 -0.0764131 -0.18155 -0.0650398 -0.0766392 -0.1816 -0.0649377 -0.0767703 -0.18165 -0.0648354 -0.076847 -0.1817 -0.064733 -0.0768922 -0.18175 -0.0646304 -0.0769192 -0.1818 -0.0645277 -0.0769355 -0.18185 -0.0644248 -0.0769452 -0.1819 -0.0643219 -0.0769511 -0.18195 -0.0642188 -0.0769545 -0.182 -0.0641157 -0.0769564 -0.18205 -0.0640124 -0.0769573 -0.1821 -0.0639091 -0.0769575 -0.18215 -0.0638057 -0.0769574 -0.1822 -0.0637023 -0.0769569 -0.18225 -0.0635988 -0.0769562 -0.1823 -0.0634953 -0.0769554 -0.18235 -0.0633917 -0.0769545 -0.1824 -0.0632882 -0.0769535 -0.18245 -0.0631846 -0.0769524 -0.1825 -0.063081 -0.0769513 -0.18255 -0.0629774 -0.0769501 -0.1826 -0.0628738 -0.0769488 -0.18265 -0.0627703 -0.0769476 -0.1827 -0.0626667 -0.0769463 -0.18275 -0.0625632 -0.076945 -0.1828 -0.0624598 -0.0769436 -0.18285 -0.0623564 -0.0769422 -0.1829 -0.062253 -0.0769407 -0.18295 -0.0621497 -0.0769393 -0.183 -0.0620465 -0.0769378 -0.18305 -0.0619434 -0.0769362 -0.1831 -0.0618403 -0.0769347 -0.18315 -0.0617373 -0.0769331 -0.1832 -0.0616345 -0.0769314 -0.18325 -0.0615317 -0.0769297 -0.1833 -0.061429 -0.076928 -0.18335 -0.0613264 -0.0769263 -0.1834 -0.0612239 -0.0769245 -0.18345 -0.0611216 -0.0769227 -0.1835 -0.0610193 -0.0769208 -0.18355 -0.0609172 -0.0769189 -0.1836 -0.0608152 -0.0769169 -0.18365 -0.0607134 -0.076915 -0.1837 -0.0606116 -0.0769129 -0.18375 -0.06051 -0.0769108 -0.1838 -0.0604086 -0.0769087 -0.18385 -0.0603073 -0.0769066 -0.1839 -0.0602061 -0.0769043 -0.18395 -0.0601051 -0.0769021 -0.184 -0.0600042 -0.0768998 -0.18405 -0.0599035 -0.0768974 -0.1841 -0.0598029 -0.076895 -0.18415 -0.0597024 -0.0768926 -0.1842 -0.0596022 -0.0768901 -0.18425 -0.059502 -0.0768875 -0.1843 -0.059402 -0.0768849 -0.18435 -0.0593022 -0.0768822 -0.1844 -0.0592024 -0.0768795 -0.18445 -0.0591029 -0.0768767 -0.1845 -0.0590035 -0.0768738 -0.18455 -0.0589042 -0.0768709 -0.1846 -0.058805 -0.0768679 -0.18465 -0.058706 -0.0768649 -0.1847 -0.0586071 -0.0768618 -0.18475 -0.0585084 -0.0768586 -0.1848 -0.0584098 -0.0768554 -0.18485 -0.0583113 -0.0768521 -0.1849 -0.0582129 -0.0768487 -0.18495 -0.0581146 -0.0768452 -0.185 -0.0580164 -0.0768417 -0.18505 -0.0579183 -0.0768381 -0.1851 -0.0578204 -0.0768344 -0.18515 -0.0577225 -0.0768306 -0.1852 -0.0576247 -0.0768268 -0.18525 -0.0575269 -0.0768229 -0.1853 -0.0574293 -0.0768189 -0.18535 -0.0573317 -0.0768147 -0.1854 -0.0572341 -0.0768106 -0.18545 -0.0571366 -0.0768063 -0.1855 -0.0570391 -0.0768019 -0.18555 -0.0569417 -0.0767974 -0.1856 -0.0568442 -0.0767929 -0.18565 -0.0567468 -0.0767882 -0.1857 -0.0566494 -0.0767834 -0.18575 -0.0565519 -0.0767786 -0.1858 -0.0564544 -0.0767736 -0.18585 -0.0563569 -0.0767685 -0.1859 -0.0562593 -0.0767633 -0.18595 -0.0561616 -0.076758 -0.186 -0.0560638 -0.0767526 -0.18605 -0.055966 -0.0767471 -0.1861 -0.055868 -0.0767414 -0.18615 -0.0557698 -0.0767357 -0.1862 -0.0556716 -0.0767298 -0.18625 -0.0555731 -0.0767238 -0.1863 -0.0554745 -0.0767176 -0.18635 -0.0553756 -0.0767114 -0.1864 -0.0552765 -0.076705 -0.18645 -0.0551772 -0.0766985 -0.1865 -0.0550776 -0.0766918 -0.18655 -0.0549776 -0.076685 -0.1866 -0.0548774 -0.0766781 -0.18665 -0.0547768 -0.076671 -0.1867 -0.0546758 -0.0766638 -0.18675 -0.0545743 -0.0766564 -0.1868 -0.0544725 -0.0766489 -0.18685 -0.0543701 -0.0766413 -0.1869 -0.0542672 -0.0766335 -0.18695 -0.0541638 -0.0766255 -0.187 -0.0540598 -0.0766174 -0.18705 -0.0539551 -0.0766092 -0.1871 -0.0538498 -0.0766007 -0.18715 -0.0537437 -0.0765922 -0.1872 -0.0536368 -0.0765834 -0.18725 -0.0535292 -0.0765745 -0.1873 -0.0534206 -0.0765654 -0.18735 -0.0533111 -0.0765562 -0.1874 -0.0532005 -0.0765468 -0.18745 -0.0530889 -0.0765372 -0.1875 -0.0529762 -0.0765275 -0.18755 -0.0528622 -0.0765175 -0.1876 -0.0527469 -0.0765074 -0.18765 -0.0526301 -0.0764972 -0.1877 -0.0525119 -0.0764867 -0.18775 -0.0523921 -0.0764761 -0.1878 -0.0522706 -0.0764653 -0.18785 -0.0521472 -0.0764543 -0.1879 -0.0520219 -0.0764431 -0.18795 -0.0518944 -0.0764317 -0.188 -0.0517647 -0.0764201 -0.18805 -0.0516326 -0.0764084 -0.1881 -0.0514978 -0.0763965 -0.18815 -0.0513603 -0.0763843 -0.1882 -0.0512197 -0.076372 -0.18825 -0.0510759 -0.0763595 -0.1883 -0.0509285 -0.0763468 -0.18835 -0.0507774 -0.0763339 -0.1884 -0.0506221 -0.0763208 -0.18845 -0.0504624 -0.0763075 -0.1885 -0.0502979 -0.076294 -0.18855 -0.0501281 -0.0762803 -0.1886 -0.0499526 -0.0762664 -0.18865 -0.0497708 -0.0762523 -0.1887 -0.0495822 -0.076238 -0.18875 -0.0493861 -0.0762235 -0.1888 -0.0491818 -0.0762088 -0.18885 -0.0489684 -0.0761938 -0.1889 -0.048745 -0.0761787 -0.18895 -0.0485105 -0.0761634 -0.189 -0.0482638 -0.0761478 -0.18905 -0.0480034 -0.0761321 -0.1891 -0.0477276 -0.0761161 -0.18915 -0.0474348 -0.0761 -0.1892 -0.0471228 -0.0760836 -0.18925 -0.046789 -0.076067 -0.1893 -0.0464305 -0.0760502 -0.18935 -0.046044 -0.0760332 -0.1894 -0.0456255 -0.0760159 -0.18945 -0.0451701 -0.0759985 -0.1895 -0.0446722 -0.0759808 -0.18955 -0.0441249 -0.0759629 -0.1896 -0.0435199 -0.0759448 -0.18965 -0.0428471 -0.0759265 -0.1897 -0.0420943 -0.0759079 -0.18975 -0.0412461 -0.0758892 -0.1898 -0.0402839 -0.0758702 -0.18985 -0.0391843 -0.075851 -0.1899 -0.0379179 -0.0758315 -0.18995 -0.0364485 -0.0758118 -0.19 -0.0347303 -0.0757919 -0.19005 -0.0327072 -0.0757718 -0.1901 -0.0303105 -0.0757514 -0.19015 -0.0274596 -0.0757308 -0.1902 -0.0240654 -0.0757099 -0.19025 -0.0200405 -0.0756888 -0.1903 -0.0153229 -0.0756674 -0.19035 -0.00991585 -0.0756458 -0.1904 -0.00394391 -0.075624 -0.19045 0.00229778 -0.0756018 -0.1905 0.00834726 -0.0755794 -0.19055 0.0136726 -0.0755567 -0.1906 0.0178345 -0.0755338 -0.19065 0.0206152 -0.0755105 -0.1907 0.0220375 -0.0754869 -0.19075 0.0222874 -0.075463 -0.1908 0.0216142 -0.0754388 -0.19085 0.0202593 -0.0754142 -0.1909 0.0184234 -0.0753892 -0.19095 0.0162606 -0.0753639 -0.191 0.0138844 -0.075338 -0.19105 0.0113765 -0.0753117 -0.1911 0.00879586 -0.0752849 -0.19115 0.00618436 -0.0752575 -0.1912 0.00357208 -0.0752294 -0.19125 0.000980406 -0.0752005 -0.1913 -0.00157554 -0.0751706 -0.19135 -0.00408529 -0.0751396 -0.1914 -0.00654182 -0.0751073 -0.19145 -0.00894066 -0.0750734 -0.1915 -0.0112793 -0.0750374 -0.19155 -0.0135567 -0.0749988 -0.1916 -0.015773 -0.0749572 -0.19165 -0.0179292 -0.0749115 -0.1917 -0.0200272 -0.0748609 -0.19175 -0.0220695 -0.074804 -0.1918 -0.0240592 -0.0747393 -0.19185 -0.0260004 -0.0746648 -0.1919 -0.0278975 -0.0745779 -0.19195 -0.029756 -0.0744755 -0.192 -0.0315817 -0.0743538 -0.19205 -0.0333813 -0.074208 -0.1921 -0.0351623 -0.074032 -0.19215 -0.0369322 -0.0738186 -0.1922 -0.0386991 -0.0735585 -0.19225 -0.040471 -0.0732404 -0.1923 -0.042255 -0.0728504 -0.19235 -0.0440575 -0.072371 -0.1924 -0.0458825 -0.071781 -0.19245 -0.0477311 -0.0710539 -0.1925 -0.0496001 -0.0701571 -0.19255 -0.0514807 -0.0690499 -0.1926 -0.053358 -0.0676823 -0.19265 -0.05521 -0.0659918 -0.1927 -0.0570091 -0.0639003 -0.19275 -0.058724 -0.0613091 -0.1928 -0.0603236 -0.0580917 -0.19285 -0.061781 -0.0540808 -0.1929 -0.0630778 -0.0490454 -0.19295 -0.0642054 -0.042645 -0.193 -0.0651661 -0.0343407 -0.19305 -0.0659703 -0.0232546 -0.1931 -0.0666338 -0.00817363 -0.19315 -0.067175 0.0112048 -0.1932 -0.0676123 0.0305262 -0.19325 -0.0679627 0.0421266 -0.1933 -0.068241 0.045748 -0.19335 -0.0684599 0.0461212 -0.1934 -0.0686298 0.0456391 -0.19345 -0.0687591 0.0448454 -0.1935 -0.0688547 0.0438333 -0.19355 -0.0689224 0.0426246 -0.1936 -0.0689665 0.0412314 -0.19365 -0.068991 0.0396655 -0.1937 -0.0689989 0.0379402 -0.19375 -0.0689926 0.0360702 -0.1938 -0.0689744 0.0340714 -0.19385 -0.068946 0.0319603 -0.1939 -0.0689088 0.0297534 -0.19395 -0.0688641 0.0274666 -0.194 -0.068813 0.0251155 -0.19405 -0.0687563 0.0227141 -0.1941 -0.0686947 0.0202756 -0.19415 -0.068629 0.0178116 -0.1942 -0.0685596 0.0153324 -0.19425 -0.068487 0.0128471 -0.1943 -0.0684115 0.0103631 -0.19435 -0.0683336 0.00788679 -0.1944 -0.0682536 0.00542332 -0.19445 -0.0681716 0.0029767 -0.1945 -0.0680878 0.000549974 -0.19455 -0.0680025 -0.00185474 -0.1946 -0.0679159 -0.00423615 -0.19465 -0.067828 -0.00659371 -0.1947 -0.0677389 -0.00892761 -0.19475 -0.0676489 -0.0112387 -0.1948 -0.0675579 -0.0135286 -0.19485 -0.067466 -0.0157998 -0.1949 -0.0673734 -0.0180557 -0.19495 -0.06728 -0.0203008 -0.195 -0.0671859 -0.0225415 -0.19505 -0.0670912 -0.0247859 -0.1951 -0.066996 -0.0270451 -0.19515 -0.0669001 -0.0293333 -0.1952 -0.0668038 -0.0316693 -0.19525 -0.066707 -0.0340772 -0.1953 -0.0666097 -0.0365874 -0.19535 -0.066512 -0.0392374 -0.1954 -0.0664139 -0.0420712 -0.19545 -0.0663154 -0.0451367 -0.1955 -0.0662166 -0.0484779 -0.19555 -0.0661174 -0.0521194 -0.1956 -0.0660179 -0.0560383 -0.19565 -0.065918 -0.0601275 -0.1957 -0.0658179 -0.0641683 -0.19575 -0.0657175 -0.0678539 -0.1958 -0.0656168 -0.0708934 -0.19585 -0.0655159 -0.0731445 -0.1959 -0.0654147 -0.074658 -0.19595 -0.0653133 -0.0756038 -0.196 -0.0652117 -0.0761682 -0.19605 -0.0651099 -0.0764973 -0.1961 -0.0650079 -0.076688 -0.19615 -0.0649058 -0.0767987 -0.1962 -0.0648035 -0.0768637 -0.19625 -0.064701 -0.0769022 -0.1963 -0.0645984 -0.0769252 -0.19635 -0.0644956 -0.0769391 -0.1964 -0.0643927 -0.0769474 -0.19645 -0.0642897 -0.0769524 -0.1965 -0.0641866 -0.0769552 -0.19655 -0.0640835 -0.0769567 -0.1966 -0.0639802 -0.0769574 -0.19665 -0.0638769 -0.0769575 -0.1967 -0.0637735 -0.0769572 -0.19675 -0.06367 -0.0769567 -0.1968 -0.0635665 -0.076956 -0.19685 -0.063463 -0.0769551 -0.1969 -0.0633594 -0.0769542 -0.19695 -0.0632558 -0.0769531 -0.197 -0.0631522 -0.076952 -0.19705 -0.0630487 -0.0769509 -0.1971 -0.0629451 -0.0769497 -0.19715 -0.0628415 -0.0769485 -0.1972 -0.062738 -0.0769472 -0.19725 -0.0626344 -0.0769459 -0.1973 -0.062531 -0.0769445 -0.19735 -0.0624275 -0.0769432 -0.1974 -0.0623241 -0.0769417 -0.19745 -0.0622208 -0.0769403 -0.1975 -0.0621175 -0.0769388 -0.19755 -0.0620143 -0.0769373 -0.1976 -0.0619112 -0.0769358 -0.19765 -0.0618082 -0.0769342 -0.1977 -0.0617052 -0.0769326 -0.19775 -0.0616024 -0.0769309 -0.1978 -0.0614996 -0.0769292 -0.19785 -0.0613969 -0.0769275 -0.1979 -0.0612944 -0.0769257 -0.19795 -0.061192 -0.0769239 -0.198 -0.0610896 -0.0769221 -0.19805 -0.0609874 -0.0769202 -0.1981 -0.0608854 -0.0769183 -0.19815 -0.0607834 -0.0769163 -0.1982 -0.0606816 -0.0769143 -0.19825 -0.0605799 -0.0769123 -0.1983 -0.0604784 -0.0769102 -0.19835 -0.060377 -0.0769081 -0.1984 -0.0602757 -0.0769059 -0.19845 -0.0601746 -0.0769036 -0.1985 -0.0600736 -0.0769014 -0.19855 -0.0599728 -0.0768991 -0.1986 -0.0598721 -0.0768967 -0.19865 -0.0597715 -0.0768943 -0.1987 -0.0596711 -0.0768918 -0.19875 -0.0595709 -0.0768893 -0.1988 -0.0594708 -0.0768867 -0.19885 -0.0593708 -0.076884 -0.1989 -0.059271 -0.0768813 -0.19895 -0.0591714 -0.0768786 -0.199 -0.0590718 -0.0768758 -0.19905 -0.0589725 -0.0768729 -0.1991 -0.0588732 -0.07687 -0.19915 -0.0587741 -0.076867 -0.1992 -0.0586751 -0.0768639 -0.19925 -0.0585763 -0.0768608 -0.1993 -0.0584776 -0.0768576 -0.19935 -0.058379 -0.0768544 -0.1994 -0.0582805 -0.076851 -0.19945 -0.0581822 -0.0768476 -0.1995 -0.0580839 -0.0768441 -0.19955 -0.0579858 -0.0768406 -0.1996 -0.0578878 -0.076837 -0.19965 -0.0577898 -0.0768332 -0.1997 -0.0576919 -0.0768295 -0.19975 -0.0575942 -0.0768256 -0.1998 -0.0574965 -0.0768216 -0.19985 -0.0573988 -0.0768176 -0.1999 -0.0573012 -0.0768134 -0.19995 -0.0572037 -0.0768092 -0.2 -0.0571062 -0.0768049 -0.20005 -0.0570087 -0.0768005 -0.2001 -0.0569113 -0.076796 -0.20015 -0.0568138 -0.0767914 -0.2002 -0.0567164 -0.0767867 -0.20025 -0.0566189 -0.0767819 -0.2003 -0.0565215 -0.076777 -0.20035 -0.056424 -0.076772 -0.2004 -0.0563264 -0.0767669 -0.20045 -0.0562288 -0.0767617 -0.2005 -0.0561311 -0.0767563 -0.20055 -0.0560333 -0.0767509 -0.2006 -0.0559354 -0.0767453 -0.20065 -0.0558374 -0.0767396 -0.2007 -0.0557392 -0.0767338 -0.20075 -0.0556409 -0.0767279 -0.2008 -0.0555424 -0.0767219 -0.20085 -0.0554436 -0.0767157 -0.2009 -0.0553447 -0.0767094 -0.20095 -0.0552456 -0.076703 -0.201 -0.0551461 -0.0766964 -0.20105 -0.0550464 -0.0766897 -0.2011 -0.0549464 -0.0766829 -0.20115 -0.054846 -0.0766759 -0.2012 -0.0547453 -0.0766688 -0.20125 -0.0546441 -0.0766615 -0.2013 -0.0545426 -0.0766541 -0.20135 -0.0544406 -0.0766466 -0.2014 -0.054338 -0.0766389 -0.20145 -0.054235 -0.076631 -0.2015 -0.0541314 -0.076623 -0.20155 -0.0540272 -0.0766149 -0.2016 -0.0539223 -0.0766066 -0.20165 -0.0538167 -0.0765981 -0.2017 -0.0537104 -0.0765894 -0.20175 -0.0536033 -0.0765807 -0.2018 -0.0534954 -0.0765717 -0.20185 -0.0533865 -0.0765626 -0.2019 -0.0532767 -0.0765533 -0.20195 -0.0531658 -0.0765438 -0.202 -0.0530539 -0.0765342 -0.20205 -0.0529407 -0.0765244 -0.2021 -0.0528263 -0.0765144 -0.20215 -0.0527106 -0.0765043 -0.2022 -0.0525934 -0.0764939 -0.20225 -0.0524747 -0.0764834 -0.2023 -0.0523544 -0.0764727 -0.20235 -0.0522323 -0.0764618 -0.2024 -0.0521083 -0.0764508 -0.20245 -0.0519823 -0.0764395 -0.2025 -0.0518542 -0.0764281 -0.20255 -0.0517237 -0.0764165 -0.2026 -0.0515908 -0.0764047 -0.20265 -0.0514552 -0.0763927 -0.2027 -0.0513167 -0.0763805 -0.20275 -0.0511752 -0.0763681 -0.2028 -0.0510303 -0.0763556 -0.20285 -0.0508818 -0.0763428 -0.2029 -0.0507294 -0.0763298 -0.20295 -0.0505728 -0.0763167 -0.203 -0.0504116 -0.0763033 -0.20305 -0.0502455 -0.0762897 -0.2031 -0.050074 -0.076276 -0.20315 -0.0498965 -0.076262 -0.2032 -0.0497127 -0.0762478 -0.20325 -0.0495218 -0.0762335 -0.2033 -0.0493232 -0.0762189 -0.20335 -0.0491162 -0.0762041 -0.2034 -0.0488998 -0.0761891 -0.20345 -0.0486731 -0.076174 -0.2035 -0.0484349 -0.0761586 -0.20355 -0.048184 -0.0761429 -0.2036 -0.047919 -0.0761271 -0.20365 -0.0476382 -0.0761111 -0.2037 -0.0473396 -0.0760949 -0.20375 -0.047021 -0.0760784 -0.2038 -0.0466799 -0.0760618 -0.20385 -0.0463131 -0.0760449 -0.2039 -0.0459171 -0.0760278 -0.20395 -0.0454876 -0.0760105 -0.204 -0.0450196 -0.075993 -0.20405 -0.044507 -0.0759752 -0.2041 -0.0439427 -0.0759573 -0.20415 -0.0433177 -0.0759391 -0.2042 -0.0426214 -0.0759207 -0.20425 -0.0418406 -0.0759021 -0.2043 -0.040959 -0.0758833 -0.20435 -0.0399567 -0.0758642 -0.2044 -0.0388085 -0.0758449 -0.20445 -0.0374831 -0.0758254 -0.2045 -0.0359413 -0.0758056 -0.20455 -0.0341346 -0.0757857 -0.2046 -0.0320028 -0.0757654 -0.20465 -0.0294736 -0.075745 -0.2047 -0.0264629 -0.0757243 -0.20475 -0.0228805 -0.0757033 -0.2048 -0.018644 -0.0756822 -0.20485 -0.0137064 -0.0756607 -0.2049 -0.0081024 -0.075639 -0.20495 -0.00200591 -0.0756171 -0.205 0.00423148 -0.0755949 -0.20505 0.0101111 -0.0755724 -0.2051 0.0151118 -0.0755496 -0.20515 0.0188539 -0.0755265 -0.2052 0.0211985 -0.0755032 -0.20525 0.0222301 -0.0754795 -0.2053 0.0221644 -0.0754555 -0.20535 0.0212542 -0.0754312 -0.2054 0.0197298 -0.0754064 -0.20545 0.0177775 -0.0753814 -0.2055 0.0155375 -0.0753558 -0.20555 0.0131126 -0.0753299 -0.2056 0.0105766 -0.0753034 -0.20565 0.00798248 -0.0752764 -0.2057 0.00536797 -0.0752488 -0.20575 0.00276016 -0.0752204 -0.2058 0.000178262 -0.0751912 -0.20585 -0.00236421 -0.0751611 -0.2059 -0.00485797 -0.0751297 -0.20595 -0.00729687 -0.0750969 -0.206 -0.00967711 -0.0750624 -0.20605 -0.0119967 -0.0750257 -0.2061 -0.014255 -0.0749862 -0.20615 -0.0164524 -0.0749434 -0.2062 -0.0185902 -0.0748963 -0.20625 -0.0206704 -0.0748439 -0.2063 -0.022696 -0.0747847 -0.20635 -0.0246701 -0.0747172 -0.2064 -0.026597 -0.0746391 -0.20645 -0.0284815 -0.0745477 -0.2065 -0.030329 -0.0744398 -0.20655 -0.0321458 -0.0743112 -0.2066 -0.0339388 -0.0741566 -0.20665 -0.0357155 -0.0739698 -0.2067 -0.0374836 -0.0737429 -0.20675 -0.0392513 -0.073466 -0.2068 -0.0410262 -0.0731271 -0.20685 -0.0428154 -0.0727113 -0.2069 -0.0446246 -0.0721999 -0.20695 -0.046457 -0.0715702 -0.207 -0.0483125 -0.070794 -0.20705 -0.0501864 -0.0698362 -0.2071 -0.0520679 -0.0686537 -0.20715 -0.0539399 -0.0671926 -0.2072 -0.0557786 -0.0653862 -0.20725 -0.0575548 -0.0631505 -0.2073 -0.059237 -0.060379 -0.20735 -0.0607948 -0.0569343 -0.2074 -0.0622036 -0.0526324 -0.20745 -0.063448 -0.0472145 -0.2075 -0.0645228 -0.0402906 -0.20755 -0.0654333 -0.0312321 -0.2076 -0.0661917 -0.0190333 -0.20765 -0.066815 -0.00251541 -0.2077 -0.0673218 0.0176269 -0.20775 -0.0677302 0.0352019 -0.2078 -0.0680566 0.0438834 -0.20785 -0.0683152 0.0460408 -0.2079 -0.0685178 0.0460191 -0.20795 -0.0686741 0.0454175 -0.208 -0.0687923 0.0445515 -0.20805 -0.0688786 0.0434765 -0.2081 -0.0689385 0.042209 -0.20815 -0.0689761 0.0407606 -0.2082 -0.0689951 0.0391435 -0.20825 -0.0689983 0.0373714 -0.2083 -0.0689881 0.0354594 -0.20835 -0.0689666 0.0334238 -0.2084 -0.0689353 0.031281 -0.20845 -0.0688956 0.0290475 -0.2085 -0.0688488 0.026739 -0.20855 -0.0687959 0.0243707 -0.2086 -0.0687376 0.0219564 -0.20865 -0.0686746 0.0195088 -0.2087 -0.0686077 0.017039 -0.20875 -0.0685372 0.014557 -0.2088 -0.0684637 0.0120713 -0.20885 -0.0683875 0.00958912 -0.2089 -0.0683089 0.00711633 -0.20895 -0.0682282 0.00465773 -0.209 -0.0681456 0.00221704 -0.20905 -0.0680614 -0.00020300 -0.2091 -0.0679756 -0.00260055 -0.20915 -0.0678886 -0.00497454 -0.2092 -0.0678003 -0.00732466 -0.20925 -0.0677109 -0.00965131 -0.2093 -0.0676206 -0.0119556 -0.20935 -0.0675293 -0.0142394 -0.2094 -0.0674372 -0.0165054 -0.20945 -0.0673443 -0.0187573 -0.2095 -0.0672507 -0.0210003 -0.20955 -0.0671564 -0.0232411 -0.2096 -0.0670616 -0.0254888 -0.20965 -0.0669661 -0.0277553 -0.2097 -0.0668701 -0.0300562 -0.20975 -0.0667736 -0.0324118 -0.2098 -0.0666767 -0.0348481 -0.20985 -0.0665793 -0.0373976 -0.2099 -0.0664814 -0.0400999 -0.20995 -0.0663832 -0.0430009 -0.21 -0.0662846 -0.0461482 -0.21005 -0.0661857 -0.0495821 -0.2101 -0.0660864 -0.0533158 -0.21015 -0.0659867 -0.0573042 -0.2102 -0.0658868 -0.0614071 -0.21025 -0.0657866 -0.065372 -0.2103 -0.0656861 -0.0688825 -0.21035 -0.0655853 -0.0716817 -0.2104 -0.0654843 -0.0736894 -0.21045 -0.0653831 -0.0750049 -0.2105 -0.0652816 -0.075813 -0.21055 -0.06518 -0.0762907 -0.2106 -0.0650781 -0.0765683 -0.21065 -0.0649761 -0.0767291 -0.2107 -0.0648739 -0.0768228 -0.21075 -0.0647715 -0.0768779 -0.2108 -0.064669 -0.0769107 -0.21085 -0.0645663 -0.0769303 -0.2109 -0.0644635 -0.0769421 -0.21095 -0.0643606 -0.0769492 -0.211 -0.0642576 -0.0769534 -0.21105 -0.0641544 -0.0769558 -0.2111 -0.0640512 -0.076957 -0.21115 -0.0639479 -0.0769575 -0.2112 -0.0638446 -0.0769575 -0.21125 -0.0637412 -0.0769571 -0.2113 -0.0636377 -0.0769565 -0.21135 -0.0635342 -0.0769557 -0.2114 -0.0634307 -0.0769548 -0.21145 -0.0633271 -0.0769538 -0.2115 -0.0632235 -0.0769528 -0.21155 -0.0631199 -0.0769517 -0.2116 -0.0630163 -0.0769505 -0.21165 -0.0629127 -0.0769493 -0.2117 -0.0628092 -0.0769481 -0.21175 -0.0627056 -0.0769468 -0.2118 -0.0626021 -0.0769455 -0.21185 -0.0624987 -0.0769441 -0.2119 -0.0623952 -0.0769427 -0.21195 -0.0622919 -0.0769413 -0.212 -0.0621886 -0.0769398 -0.21205 -0.0620853 -0.0769383 -0.2121 -0.0619821 -0.0769368 -0.21215 -0.061879 -0.0769353 -0.2122 -0.061776 -0.0769337 -0.21225 -0.0616731 -0.076932 -0.2123 -0.0615703 -0.0769304 -0.21235 -0.0614675 -0.0769287 -0.2124 -0.0613649 -0.0769269 -0.21245 -0.0612624 -0.0769252 -0.2125 -0.06116 -0.0769234 -0.21255 -0.0610577 -0.0769215 -0.2126 -0.0609556 -0.0769196 -0.21265 -0.0608535 -0.0769177 -0.2127 -0.0607516 -0.0769157 -0.21275 -0.0606498 -0.0769137 -0.2128 -0.0605482 -0.0769116 -0.21285 -0.0604467 -0.0769095 -0.2129 -0.0603453 -0.0769074 -0.21295 -0.0602441 -0.0769052 -0.213 -0.060143 -0.0769029 -0.21305 -0.0600421 -0.0769007 -0.2131 -0.0599413 -0.0768983 -0.21315 -0.0598407 -0.0768959 -0.2132 -0.0597402 -0.0768935 -0.21325 -0.0596398 -0.076891 -0.2133 -0.0595396 -0.0768885 -0.21335 -0.0594396 -0.0768859 -0.2134 -0.0593397 -0.0768832 -0.21345 -0.0592399 -0.0768805 -0.2135 -0.0591403 -0.0768777 -0.21355 -0.0590408 -0.0768749 -0.2136 -0.0589415 -0.076872 -0.21365 -0.0588423 -0.0768691 -0.2137 -0.0587432 -0.076866 -0.21375 -0.0586443 -0.076863 -0.2138 -0.0585455 -0.0768598 -0.21385 -0.0584468 -0.0768566 -0.2139 -0.0583483 -0.0768533 -0.21395 -0.0582498 -0.07685 -0.214 -0.0581515 -0.0768465 -0.21405 -0.0580533 -0.076843 -0.2141 -0.0579552 -0.0768395 -0.21415 -0.0578572 -0.0768358 -0.2142 -0.0577593 -0.0768321 -0.21425 -0.0576614 -0.0768283 -0.2143 -0.0575637 -0.0768244 -0.21435 -0.057466 -0.0768204 -0.2144 -0.0573683 -0.0768163 -0.21445 -0.0572708 -0.0768121 -0.2145 -0.0571733 -0.0768079 -0.21455 -0.0570758 -0.0768036 -0.2146 -0.0569783 -0.0767991 -0.21465 -0.0568809 -0.0767946 -0.2147 -0.0567834 -0.07679 -0.21475 -0.056686 -0.0767852 -0.2148 -0.0565885 -0.0767804 -0.21485 -0.056491 -0.0767755 -0.2149 -0.0563935 -0.0767704 -0.21495 -0.0562959 -0.0767653 -0.215 -0.0561983 -0.07676 -0.21505 -0.0561006 -0.0767547 -0.2151 -0.0560027 -0.0767492 -0.21515 -0.0559048 -0.0767436 -0.2152 -0.0558067 -0.0767378 -0.21525 -0.0557085 -0.076732 -0.2153 -0.0556101 -0.076726 -0.21535 -0.0555116 -0.07672 -0.2154 -0.0554128 -0.0767137 -0.21545 -0.0553138 -0.0767074 -0.2155 -0.0552146 -0.0767009 -0.21555 -0.055115 -0.0766943 -0.2156 -0.0550152 -0.0766876 -0.21565 -0.0549151 -0.0766807 -0.2157 -0.0548146 -0.0766737 -0.21575 -0.0547138 -0.0766665 -0.2158 -0.0546125 -0.0766592 -0.21585 -0.0545108 -0.0766518 -0.2159 -0.0544086 -0.0766442 -0.21595 -0.0543059 -0.0766364 -0.216 -0.0542027 -0.0766285 -0.21605 -0.0540989 -0.0766205 -0.2161 -0.0539945 -0.0766123 -0.21615 -0.0538894 -0.0766039 -0.2162 -0.0537836 -0.0765954 -0.21625 -0.0536771 -0.0765867 -0.2163 -0.0535697 -0.0765779 -0.21635 -0.0534615 -0.0765689 -0.2164 -0.0533523 -0.0765597 -0.21645 -0.0532422 -0.0765503 -0.2165 -0.053131 -0.0765408 -0.21655 -0.0530187 -0.0765311 -0.2166 -0.0529052 -0.0765213 -0.21665 -0.0527903 -0.0765113 -0.2167 -0.0526742 -0.076501 -0.21675 -0.0525565 -0.0764907 -0.2168 -0.0524373 -0.0764801 -0.21685 -0.0523164 -0.0764693 -0.2169 -0.0521938 -0.0764584 -0.21695 -0.0520692 -0.0764473 -0.217 -0.0519426 -0.076436 -0.21705 -0.0518137 -0.0764245 -0.2171 -0.0516825 -0.0764128 -0.21715 -0.0515488 -0.076401 -0.2172 -0.0514123 -0.0763889 -0.21725 -0.0512729 -0.0763767 -0.2173 -0.0511303 -0.0763642 -0.21735 -0.0509843 -0.0763516 -0.2174 -0.0508346 -0.0763388 -0.21745 -0.050681 -0.0763257 -0.2175 -0.050523 -0.0763125 -0.21755 -0.0503603 -0.0762991 -0.2176 -0.0501926 -0.0762855 -0.21765 -0.0500192 -0.0762716 -0.2177 -0.0498399 -0.0762576 -0.21775 -0.0496539 -0.0762434 -0.2178 -0.0494607 -0.0762289 -0.21785 -0.0492596 -0.0762143 -0.2179 -0.0490497 -0.0761995 -0.21795 -0.0488302 -0.0761844 -0.218 -0.0486 -0.0761692 -0.21805 -0.048358 -0.0761537 -0.2181 -0.0481029 -0.076138 -0.21815 -0.0478332 -0.0761222 -0.2182 -0.047547 -0.0761061 -0.21825 -0.0472424 -0.0760898 -0.2183 -0.0469171 -0.0760732 -0.21835 -0.0465683 -0.0760565 -0.2184 -0.0461928 -0.0760396 -0.21845 -0.0457868 -0.0760224 -0.2185 -0.0453459 -0.0760051 -0.21855 -0.0448647 -0.0759875 -0.2186 -0.0443368 -0.0759697 -0.21865 -0.0437546 -0.0759516 -0.2187 -0.0431086 -0.0759334 -0.21875 -0.0423875 -0.0759149 -0.2188 -0.0415771 -0.0758962 -0.21885 -0.0406602 -0.0758773 -0.2189 -0.0396153 -0.0758582 -0.21895 -0.0384155 -0.0758388 -0.219 -0.0370272 -0.0758192 -0.21905 -0.0354085 -0.0757994 -0.2191 -0.0335073 -0.0757794 -0.21915 -0.0312598 -0.0757591 -0.2192 -0.0285898 -0.0757385 -0.21925 -0.0254104 -0.0757178 -0.2193 -0.0216318 -0.0756968 -0.21935 -0.0171787 -0.0756755 -0.2194 -0.012024 -0.075654 -0.21945 -0.00623961 -0.0756322 -0.2195 -5.30047e-05 -0.0756102 -0.21955 0.00613054 -0.0755879 -0.2196 0.0117882 -0.0755653 -0.21965 0.0164264 -0.0755424 -0.2197 0.0197355 -0.0755193 -0.21975 0.0216529 -0.0754958 -0.2198 0.0223155 -0.075472 -0.21985 0.0219594 -0.0754479 -0.2199 0.0208347 -0.0754235 -0.21995 0.019159 -0.0753987 -0.22 0.0171037 -0.0753734 -0.22005 0.0147966 -0.0753478 -0.2201 0.0123302 -0.0753217 -0.22015 0.0097712 -0.0752951 -0.2202 0.0071672 -0.0752679 -0.22025 0.00455229 -0.07524 -0.2203 0.00195081 -0.0752114 -0.22035 -0.000620011 -0.0751819 -0.2204 -0.00314811 -0.0751514 -0.22045 -0.00562528 -0.0751197 -0.2205 -0.00804619 -0.0750864 -0.22055 -0.0104076 -0.0750512 -0.2206 -0.0127081 -0.0750137 -0.22065 -0.0149473 -0.0749732 -0.2207 -0.0171259 -0.0749292 -0.22075 -0.0192455 -0.0748806 -0.2208 -0.0213084 -0.0748262 -0.22085 -0.0233174 -0.0747647 -0.2209 -0.0252764 -0.0746941 -0.22095 -0.0271895 -0.0746121 -0.221 -0.0290618 -0.074516 -0.22105 -0.030899 -0.0744021 -0.2211 -0.0327077 -0.074266 -0.22115 -0.0344947 -0.0741021 -0.2212 -0.0362679 -0.0739037 -0.22125 -0.038035 -0.0736624 -0.2213 -0.0398041 -0.0733676 -0.22135 -0.0415828 -0.0730064 -0.2214 -0.0433777 -0.0725629 -0.22145 -0.0451939 -0.0720173 -0.2215 -0.0470338 -0.0713452 -0.22155 -0.0488958 -0.0705164 -0.2216 -0.0507735 -0.0694936 -0.22165 -0.0526542 -0.0682304 -0.2217 -0.0545186 -0.0666695 -0.22175 -0.0563412 -0.064739 -0.2218 -0.0580915 -0.0623487 -0.22185 -0.0597379 -0.0593837 -0.2219 -0.0612514 -0.0556939 -0.22195 -0.0626101 -0.0510762 -0.222 -0.0638016 -0.0452387 -0.22205 -0.0648242 -0.0377312 -0.2221 -0.0656855 -0.0278203 -0.22215 -0.0663998 -0.0143815 -0.2222 -0.0669848 0.00354571 -0.22225 -0.067459 0.0238126 -0.2223 -0.0678402 0.0389168 -0.22235 -0.068144 0.0450012 -0.2224 -0.0683839 0.046147 -0.22245 -0.0685711 0.0458682 -0.2225 -0.0687148 0.0451713 -0.22255 -0.0688224 0.0442374 -0.2226 -0.0688999 0.043101 -0.22265 -0.0689524 0.0417758 -0.2227 -0.0689839 0.0402734 -0.22275 -0.0689977 0.0386063 -0.2228 -0.0689965 0.0367889 -0.22285 -0.0689825 0.0348366 -0.2229 -0.0689578 0.0327658 -0.22295 -0.0689237 0.0305929 -0.223 -0.0688817 0.0283343 -0.22305 -0.0688329 0.0260056 -0.2231 -0.0687782 0.0236215 -0.22315 -0.0687184 0.0211955 -0.2232 -0.0686541 0.0187398 -0.22325 -0.068586 0.0162652 -0.2233 -0.0685146 0.0137812 -0.22335 -0.0684402 0.0112959 -0.2234 -0.0683632 0.00881608 -0.22345 -0.0682839 0.00634726 -0.2235 -0.0682026 0.0038939 -0.22355 -0.0681195 0.0014594 -0.2236 -0.0680348 -0.00095378 -0.22365 -0.0679486 -0.00334405 -0.2237 -0.0678611 -0.00571059 -0.22375 -0.0677725 -0.00805331 -0.2238 -0.0676828 -0.0103728 -0.22385 -0.0675922 -0.0126705 -0.2239 -0.0675006 -0.0149484 -0.22395 -0.0674083 -0.0172095 -0.224 -0.0673151 -0.0194581 -0.22405 -0.0672213 -0.0216996 -0.2241 -0.0671269 -0.0239414 -0.22415 -0.0670318 -0.0261936 -0.2242 -0.0669362 -0.0284689 -0.22425 -0.0668401 -0.0307845 -0.2243 -0.0667434 -0.0331621 -0.22435 -0.0666463 -0.0356299 -0.2244 -0.0665488 -0.0382226 -0.22445 -0.0664508 -0.0409818 -0.2245 -0.0663525 -0.0439546 -0.22455 -0.0662538 -0.0471878 -0.2246 -0.0661547 -0.0507158 -0.22465 -0.0660553 -0.0545376 -0.2247 -0.0659556 -0.0585822 -0.22475 -0.0658555 -0.0626739 -0.2248 -0.0657552 -0.066531 -0.22485 -0.0656547 -0.0698404 -0.2249 -0.0655538 -0.0723915 -0.22495 -0.0654528 -0.0741662 -0.225 -0.0653515 -0.0753025 -0.22505 -0.0652499 -0.0759904 -0.2251 -0.0651482 -0.0763941 -0.22515 -0.0650463 -0.0766282 -0.2252 -0.0649442 -0.0767639 -0.22525 -0.0648419 -0.0768432 -0.2253 -0.0647395 -0.07689 -0.22535 -0.0646369 -0.0769179 -0.2254 -0.0645342 -0.0769347 -0.22545 -0.0644314 -0.0769448 -0.2255 -0.0643284 -0.0769508 -0.22555 -0.0642254 -0.0769543 -0.2256 -0.0641222 -0.0769563 -0.22565 -0.064019 -0.0769572 -0.2257 -0.0639157 -0.0769575 -0.22575 -0.0638123 -0.0769574 -0.2258 -0.0637089 -0.0769569 -0.22585 -0.0636054 -0.0769563 -0.2259 -0.0635019 -0.0769555 -0.22595 -0.0633983 -0.0769545 -0.226 -0.0632948 -0.0769535 -0.22605 -0.0631912 -0.0769525 -0.2261 -0.0630876 -0.0769513 -0.22615 -0.062984 -0.0769501 -0.2262 -0.0628804 -0.0769489 -0.22625 -0.0627769 -0.0769477 -0.2263 -0.0626733 -0.0769464 -0.22635 -0.0625698 -0.076945 -0.2264 -0.0624664 -0.0769437 -0.22645 -0.062363 -0.0769423 -0.2265 -0.0622596 -0.0769408 -0.22655 -0.0621563 -0.0769394 -0.2266 -0.0620531 -0.0769379 -0.22665 -0.0619499 -0.0769363 -0.2267 -0.0618469 -0.0769348 -0.22675 -0.0617439 -0.0769332 -0.2268 -0.061641 -0.0769315 -0.22685 -0.0615382 -0.0769299 -0.2269 -0.0614355 -0.0769281 -0.22695 -0.0613329 -0.0769264 -0.227 -0.0612304 -0.0769246 -0.22705 -0.0611281 -0.0769228 -0.2271 -0.0610258 -0.0769209 -0.22715 -0.0609237 -0.076919 -0.2272 -0.0608217 -0.0769171 -0.22725 -0.0607198 -0.0769151 -0.2273 -0.0606181 -0.0769131 -0.22735 -0.0605165 -0.076911 -0.2274 -0.0604151 -0.0769089 -0.22745 -0.0603137 -0.0769067 -0.2275 -0.0602126 -0.0769045 -0.22755 -0.0601115 -0.0769022 -0.2276 -0.0600106 -0.0768999 -0.22765 -0.0599099 -0.0768976 -0.2277 -0.0598093 -0.0768952 -0.22775 -0.0597088 -0.0768927 -0.2278 -0.0596085 -0.0768902 -0.22785 -0.0595084 -0.0768877 -0.2279 -0.0594084 -0.076885 -0.22795 -0.0593085 -0.0768824 -0.228 -0.0592088 -0.0768796 -0.22805 -0.0591092 -0.0768769 -0.2281 -0.0590098 -0.076874 -0.22815 -0.0589105 -0.0768711 -0.2282 -0.0588113 -0.0768681 -0.22825 -0.0587123 -0.0768651 -0.2283 -0.0586134 -0.076862 -0.22835 -0.0585147 -0.0768588 -0.2284 -0.058416 -0.0768556 -0.22845 -0.0583175 -0.0768523 -0.2285 -0.0582191 -0.0768489 -0.22855 -0.0581208 -0.0768455 -0.2286 -0.0580227 -0.0768419 -0.22865 -0.0579246 -0.0768383 -0.2287 -0.0578266 -0.0768346 -0.22875 -0.0577287 -0.0768309 -0.2288 -0.0576309 -0.076827 -0.22885 -0.0575332 -0.0768231 -0.2289 -0.0574355 -0.0768191 -0.22895 -0.0573379 -0.076815 -0.229 -0.0572403 -0.0768108 -0.22905 -0.0571428 -0.0768065 -0.2291 -0.0570453 -0.0768022 -0.22915 -0.0569479 -0.0767977 -0.2292 -0.0568504 -0.0767932 -0.22925 -0.056753 -0.0767885 -0.2293 -0.0566556 -0.0767837 -0.22935 -0.0565581 -0.0767789 -0.2294 -0.0564606 -0.0767739 -0.22945 -0.0563631 -0.0767688 -0.2295 -0.0562655 -0.0767636 -0.22955 -0.0561678 -0.0767584 -0.2296 -0.05607 -0.076753 -0.22965 -0.0559722 -0.0767474 -0.2297 -0.0558742 -0.0767418 -0.22975 -0.0557761 -0.076736 -0.2298 -0.0556778 -0.0767302 -0.22985 -0.0555794 -0.0767242 -0.2299 -0.0554808 -0.076718 -0.22995 -0.0553819 -0.0767118 -0.23 -0.0552829 -0.0767054 -0.23005 -0.0551835 -0.0766989 -0.2301 -0.0550839 -0.0766922 -0.23015 -0.054984 -0.0766855 -0.2302 -0.0548838 -0.0766785 -0.23025 -0.0547832 -0.0766715 -0.2303 -0.0546822 -0.0766643 -0.23035 -0.0545808 -0.0766569 -0.2304 -0.054479 -0.0766494 -0.23045 -0.0543766 -0.0766418 -0.2305 -0.0542738 -0.076634 -0.23055 -0.0541704 -0.076626 -0.2306 -0.0540664 -0.0766179 -0.23065 -0.0539618 -0.0766097 -0.2307 -0.0538565 -0.0766013 -0.23075 -0.0537505 -0.0765927 -0.2308 -0.0536437 -0.076584 -0.23085 -0.053536 -0.0765751 -0.2309 -0.0534275 -0.076566 -0.23095 -0.0533181 -0.0765568 -0.231 -0.0532076 -0.0765474 -0.23105 -0.0530961 -0.0765378 -0.2311 -0.0529834 -0.0765281 -0.23115 -0.0528695 -0.0765182 -0.2312 -0.0527542 -0.0765081 -0.23125 -0.0526376 -0.0764978 -0.2313 -0.0525195 -0.0764874 -0.23135 -0.0523998 -0.0764768 -0.2314 -0.0522784 -0.076466 -0.23145 -0.0521551 -0.076455 -0.2315 -0.0520299 -0.0764438 -0.23155 -0.0519026 -0.0764324 -0.2316 -0.051773 -0.0764209 -0.23165 -0.051641 -0.0764091 -0.2317 -0.0515065 -0.0763972 -0.23175 -0.0513691 -0.0763851 -0.2318 -0.0512287 -0.0763728 -0.23185 -0.0510851 -0.0763603 -0.2319 -0.050938 -0.0763476 -0.23195 -0.0507871 -0.0763347 -0.232 -0.0506321 -0.0763216 -0.23205 -0.0504727 -0.0763083 -0.2321 -0.0503085 -0.0762948 -0.23215 -0.0501391 -0.0762812 -0.2322 -0.0499639 -0.0762673 -0.23225 -0.0497826 -0.0762532 -0.2323 -0.0495944 -0.0762389 -0.23235 -0.0493988 -0.0762244 -0.2324 -0.049195 -0.0762097 -0.23245 -0.0489823 -0.0761948 -0.2325 -0.0487595 -0.0761797 -0.23255 -0.0485258 -0.0761644 -0.2326 -0.0482799 -0.0761488 -0.23265 -0.0480204 -0.0761331 -0.2327 -0.0477457 -0.0761172 -0.23275 -0.047454 -0.076101 -0.2328 -0.0471432 -0.0760846 -0.23285 -0.0468109 -0.0760681 -0.2329 -0.0464541 -0.0760513 -0.23295 -0.0460696 -0.0760343 -0.233 -0.0456532 -0.076017 -0.23305 -0.0452003 -0.0759996 -0.2331 -0.0447053 -0.0759819 -0.23315 -0.0441614 -0.0759641 -0.2332 -0.0435603 -0.075946 -0.23325 -0.0428922 -0.0759277 -0.2333 -0.0421448 -0.0759091 -0.23335 -0.0413033 -0.0758904 -0.2334 -0.040349 -0.0758714 -0.23345 -0.0392589 -0.0758522 -0.2335 -0.0380042 -0.0758327 -0.23355 -0.0365489 -0.0758131 -0.2336 -0.0348482 -0.0757932 -0.23365 -0.0328464 -0.0757731 -0.2337 -0.0304757 -0.0757527 -0.23375 -0.0276564 -0.0757321 -0.2338 -0.0242994 -0.0757112 -0.23385 -0.020317 -0.0756902 -0.2339 -0.0156443 -0.0756688 -0.23395 -0.0102791 -0.0756472 -0.234 -0.00433624 -0.0756254 -0.23405 0.00190056 -0.0756032 -0.2341 0.00797818 -0.0755809 -0.23415 0.0133646 -0.0755582 -0.2342 0.0176097 -0.0755352 -0.23425 0.02048 -0.075512 -0.2343 0.0219844 -0.0754884 -0.23435 0.0223017 -0.0754646 -0.2344 0.0216798 -0.0754403 -0.23445 0.0203618 -0.0754158 -0.2345 0.0185515 -0.0753908 -0.23455 0.0164057 -0.0753655 -0.2346 0.0140403 -0.0753397 -0.23465 0.0115389 -0.0753134 -0.2347 0.00896146 -0.0752866 -0.23475 0.00635092 -0.0752592 -0.2348 0.00373797 -0.0752312 -0.23485 0.00114448 -0.0752023 -0.2349 -0.00141409 -0.0751725 -0.23495 -0.00392703 -0.0751417 -0.235 -0.0063871 -0.0751094 -0.23505 -0.0087897 -0.0750756 -0.2351 -0.0111322 -0.0750397 -0.23515 -0.0134135 -0.0750014 -0.2352 -0.0156337 -0.0749599 -0.23525 -0.0177937 -0.0749146 -0.2353 -0.0198953 -0.0748643 -0.23535 -0.021941 -0.0748079 -0.2354 -0.023934 -0.0747437 -0.23545 -0.0258782 -0.0746698 -0.2355 -0.027778 -0.0745838 -0.23555 -0.0296387 -0.0744826 -0.2356 -0.0314663 -0.0743622 -0.23565 -0.0332674 -0.0742181 -0.2357 -0.0350493 -0.0740443 -0.23575 -0.0368197 -0.0738335 -0.2358 -0.0385866 -0.0735767 -0.23585 -0.0403579 -0.0732627 -0.2359 -0.0421409 -0.0728777 -0.23595 -0.0439421 -0.0724046 -0.236 -0.0457656 -0.0718224 -0.23605 -0.0476127 -0.0711049 -0.2361 -0.0494806 -0.07022 -0.23615 -0.0513609 -0.0691276 -0.2362 -0.0532389 -0.0677783 -0.23625 -0.0550933 -0.0661104 -0.2363 -0.0568967 -0.0640471 -0.23635 -0.0586179 -0.0614912 -0.2364 -0.0602257 -0.0583181 -0.23645 -0.0616929 -0.0543638 -0.2365 -0.0630002 -0.0494023 -0.23655 -0.0641387 -0.0431022 -0.2366 -0.0651098 -0.0349409 -0.23665 -0.0659235 -0.0240662 -0.2367 -0.0665954 -0.00927274 -0.23675 -0.0671438 0.00989159 -0.2368 -0.0675872 0.0294637 -0.23685 -0.0679427 0.0416733 -0.2369 -0.0682252 0.0456569 -0.23695 -0.0684475 0.0461343 -0.237 -0.0686203 0.045681 -0.23705 -0.0687519 0.0449028 -0.2371 -0.0688495 0.0439037 -0.23715 -0.0689188 0.0427072 -0.2372 -0.0689644 0.0413254 -0.23725 -0.06899 0.0397701 -0.2373 -0.0689988 0.0380545 -0.23735 -0.0689934 0.0361933 -0.2374 -0.0689759 0.0342022 -0.23745 -0.0689481 0.0320978 -0.2375 -0.0689114 0.0298964 -0.23755 -0.0688672 0.0276143 -0.2376 -0.0688164 0.0252668 -0.23765 -0.06876 0.0228682 -0.2377 -0.0686988 0.0204317 -0.23775 -0.0686333 0.017969 -0.2378 -0.0685641 0.0154906 -0.23785 -0.0684917 0.0130054 -0.2379 -0.0684164 0.0105211 -0.23795 -0.0683387 0.00804412 -0.238 -0.0682587 0.0055797 -0.23805 -0.0681768 0.00313191 -0.2381 -0.0680932 0.000703842 -0.23815 -0.068008 -0.00170232 -0.2382 -0.0679214 -0.00408524 -0.23825 -0.0678336 -0.00644432 -0.2383 -0.0677446 -0.0087797 -0.23835 -0.0676546 -0.0110922 -0.2384 -0.0675637 -0.0133834 -0.23845 -0.0674719 -0.0156557 -0.2385 -0.0673793 -0.0179124 -0.23855 -0.0672859 -0.0201581 -0.2386 -0.0671919 -0.0223988 -0.23865 -0.0670973 -0.0246427 -0.2387 -0.067002 -0.0269005 -0.23875 -0.0669063 -0.0291864 -0.2388 -0.06681 -0.0315187 -0.23885 -0.0667132 -0.0339212 -0.2389 -0.0666159 -0.0364239 -0.23895 -0.0665183 -0.0390637 -0.239 -0.0664202 -0.0418844 -0.23905 -0.0663217 -0.0449337 -0.2391 -0.0662229 -0.0482563 -0.23915 -0.0661237 -0.0518787 -0.2392 -0.0660242 -0.055782 -0.23925 -0.0659244 -0.0598657 -0.2393 -0.0658243 -0.0639181 -0.23935 -0.0657239 -0.0676359 -0.2394 -0.0656232 -0.0707229 -0.23945 -0.0655223 -0.0730245 -0.2395 -0.0654212 -0.0745806 -0.23955 -0.0653198 -0.0755568 -0.2396 -0.0652182 -0.0761406 -0.23965 -0.0651164 -0.0764813 -0.2397 -0.0650144 -0.0766787 -0.23975 -0.0649123 -0.0767933 -0.2398 -0.06481 -0.0768605 -0.23985 -0.0647075 -0.0769003 -0.2399 -0.0646049 -0.0769241 -0.23995 -0.0645021 -0.0769384 -0.24 -0.0643993 -0.076947 -0.24005 -0.0642963 -0.0769521 -0.2401 -0.0641932 -0.0769551 -0.24015 -0.06409 -0.0769567 -0.2402 -0.0639868 -0.0769574 -0.24025 -0.0638834 -0.0769575 -0.2403 -0.06378 -0.0769573 -0.24035 -0.0636766 -0.0769567 -0.2404 -0.0635731 -0.076956 -0.24045 -0.0634696 -0.0769552 -0.2405 -0.063366 -0.0769542 -0.24055 -0.0632624 -0.0769532 -0.2406 -0.0631588 -0.0769521 -0.24065 -0.0630553 -0.076951 -0.2407 -0.0629517 -0.0769498 -0.24075 -0.0628481 -0.0769485 -0.2408 -0.0627445 -0.0769473 -0.24085 -0.062641 -0.076946 -0.2409 -0.0625375 -0.0769446 -0.24095 -0.0624341 -0.0769432 -0.241 -0.0623307 -0.0769418 -0.24105 -0.0622274 -0.0769404 -0.2411 -0.0621241 -0.0769389 -0.24115 -0.0620209 -0.0769374 -0.2412 -0.0619178 -0.0769359 -0.24125 -0.0618147 -0.0769343 -0.2413 -0.0617118 -0.0769327 -0.24135 -0.0616089 -0.076931 -0.2414 -0.0615061 -0.0769293 -0.24145 -0.0614035 -0.0769276 -0.2415 -0.0613009 -0.0769258 -0.24155 -0.0611985 -0.076924 -0.2416 -0.0610961 -0.0769222 -0.24165 -0.0609939 -0.0769203 -0.2417 -0.0608919 -0.0769184 -0.24175 -0.0607899 -0.0769165 -0.2418 -0.0606881 -0.0769145 -0.24185 -0.0605864 -0.0769124 -0.2419 -0.0604848 -0.0769103 -0.24195 -0.0603834 -0.0769082 -0.242 -0.0602821 -0.076906 -0.24205 -0.060181 -0.0769038 -0.2421 -0.06008 -0.0769015 -0.24215 -0.0599792 -0.0768992 -0.2422 -0.0598785 -0.0768968 -0.24225 -0.0597779 -0.0768944 -0.2423 -0.0596775 -0.0768919 -0.24235 -0.0595773 -0.0768894 -0.2424 -0.0594772 -0.0768868 -0.24245 -0.0593772 -0.0768842 -0.2425 -0.0592774 -0.0768815 -0.24255 -0.0591777 -0.0768788 -0.2426 -0.0590782 -0.076876 -0.24265 -0.0589788 -0.0768731 -0.2427 -0.0588795 -0.0768702 -0.24275 -0.0587804 -0.0768672 -0.2428 -0.0586814 -0.0768641 -0.24285 -0.0585826 -0.076861 -0.2429 -0.0584839 -0.0768578 -0.24295 -0.0583853 -0.0768546 -0.243 -0.0582868 -0.0768512 -0.24305 -0.0581884 -0.0768478 -0.2431 -0.0580902 -0.0768444 -0.24315 -0.057992 -0.0768408 -0.2432 -0.057894 -0.0768372 -0.24325 -0.057796 -0.0768335 -0.2433 -0.0576982 -0.0768297 -0.24335 -0.0576004 -0.0768258 -0.2434 -0.0575027 -0.0768219 -0.24345 -0.057405 -0.0768178 -0.2435 -0.0573074 -0.0768137 -0.24355 -0.0572099 -0.0768095 -0.2436 -0.0571124 -0.0768052 -0.24365 -0.0570149 -0.0768008 -0.2437 -0.0569175 -0.0767963 -0.24375 -0.05682 -0.0767917 -0.2438 -0.0567226 -0.076787 -0.24385 -0.0566252 -0.0767822 -0.2439 -0.0565277 -0.0767773 -0.24395 -0.0564302 -0.0767723 -0.244 -0.0563326 -0.0767672 -0.24405 -0.056235 -0.076762 -0.2441 -0.0561373 -0.0767567 -0.24415 -0.0560395 -0.0767512 -0.2442 -0.0559416 -0.0767457 -0.24425 -0.0558436 -0.07674 -0.2443 -0.0557454 -0.0767342 -0.24435 -0.0556471 -0.0767283 -0.2444 -0.0555486 -0.0767223 -0.24445 -0.0554499 -0.0767161 -0.2445 -0.055351 -0.0767098 -0.24455 -0.0552519 -0.0767034 -0.2446 -0.0551525 -0.0766968 -0.24465 -0.0550528 -0.0766901 -0.2447 -0.0549528 -0.0766833 -0.24475 -0.0548524 -0.0766763 -0.2448 -0.0547517 -0.0766692 -0.24485 -0.0546506 -0.076662 -0.2449 -0.0545491 -0.0766546 -0.24495 -0.0544471 -0.0766471 -0.245 -0.0543446 -0.0766394 -0.24505 -0.0542416 -0.0766315 -0.2451 -0.054138 -0.0766235 -0.24515 -0.0540338 -0.0766154 -0.2452 -0.053929 -0.0766071 -0.24525 -0.0538235 -0.0765986 -0.2453 -0.0537172 -0.07659 -0.24535 -0.0536102 -0.0765812 -0.2454 -0.0535023 -0.0765723 -0.24545 -0.0533935 -0.0765632 -0.2455 -0.0532837 -0.0765539 -0.24555 -0.0531729 -0.0765444 -0.2456 -0.053061 -0.0765348 -0.24565 -0.052948 -0.076525 -0.2457 -0.0528336 -0.076515 -0.24575 -0.052718 -0.0765049 -0.2458 -0.0526009 -0.0764946 -0.24585 -0.0524823 -0.0764841 -0.2459 -0.0523621 -0.0764734 -0.24595 -0.0522401 -0.0764625 -0.246 -0.0521162 -0.0764515 -0.24605 -0.0519904 -0.0764403 -0.2461 -0.0518624 -0.0764288 -0.24615 -0.0517321 -0.0764172 -0.2462 -0.0515993 -0.0764054 -0.24625 -0.0514639 -0.0763935 -0.2463 -0.0513256 -0.0763813 -0.24635 -0.0511843 -0.0763689 -0.2464 -0.0510396 -0.0763564 -0.24645 -0.0508913 -0.0763436 -0.2465 -0.0507392 -0.0763306 -0.24655 -0.0505829 -0.0763175 -0.2466 -0.050422 -0.0763041 -0.24665 -0.0502562 -0.0762906 -0.2467 -0.0500851 -0.0762769 -0.24675 -0.049908 -0.0762629 -0.2468 -0.0497246 -0.0762487 -0.24685 -0.0495342 -0.0762344 -0.2469 -0.0493361 -0.0762198 -0.24695 -0.0491296 -0.0762051 -0.247 -0.0489139 -0.0761901 -0.24705 -0.0486878 -0.0761749 -0.2471 -0.0484504 -0.0761595 -0.24715 -0.0482004 -0.0761439 -0.2472 -0.0479363 -0.0761281 -0.24725 -0.0476566 -0.0761121 -0.2473 -0.0473592 -0.0760959 -0.24735 -0.047042 -0.0760795 -0.2474 -0.0467023 -0.0760628 -0.24745 -0.0463373 -0.076046 -0.2475 -0.0459432 -0.0760289 -0.24755 -0.045516 -0.0760116 -0.2476 -0.0450506 -0.0759941 -0.24765 -0.0445411 -0.0759764 -0.2477 -0.0439803 -0.0759584 -0.24775 -0.0433595 -0.0759403 -0.2478 -0.0426681 -0.0759219 -0.24785 -0.0418931 -0.0759033 -0.2479 -0.0410185 -0.0758845 -0.24795 -0.0400246 -0.0758654 -0.248 -0.0388865 -0.0758461 -0.24805 -0.0375734 -0.0758266 -0.2481 -0.0360468 -0.0758069 -0.24815 -0.0342586 -0.0757869 -0.2482 -0.0321496 -0.0757667 -0.24825 -0.029648 -0.0757463 -0.2483 -0.0266706 -0.0757256 -0.24835 -0.0231274 -0.0757047 -0.2484 -0.0189345 -0.0756835 -0.24845 -0.0140416 -0.0756621 -0.2485 -0.00847659 -0.0756404 -0.24855 -0.0024029 -0.0756185 -0.2486 0.00383928 -0.0755963 -0.24865 0.00975785 -0.0755738 -0.2487 0.014828 -0.0755511 -0.24875 0.0186571 -0.075528 -0.2488 0.0210902 -0.0755047 -0.24885 0.0221997 -0.075481 -0.2489 0.0221964 -0.075457 -0.24895 0.0213327 -0.0754327 -0.249 0.0198414 -0.075408 -0.24905 0.0179116 -0.075383 -0.2491 0.0156866 -0.0753575 -0.24915 0.013271 -0.0753316 -0.2492 0.0107403 -0.0753051 -0.24925 0.00814859 -0.0752782 -0.2493 0.00553448 -0.0752506 -0.24935 0.00292559 -0.0752223 -0.2494 0.000341591 -0.0751931 -0.24945 -0.00220371 -0.075163 -0.2495 -0.00470078 -0.0751318 -0.24955 -0.0071433 -0.0750991 -0.2496 -0.00952736 -0.0750646 -0.24965 -0.0118508 -0.0750281 -0.2497 -0.014113 -0.0749888 -0.24975 -0.0163142 -0.0749462 -0.2498 -0.0184558 -0.0748994 -0.24985 -0.0205397 -0.0748474 -0.2499 -0.0225686 -0.0747887 -0.24995 -0.0245459 -0.0747218 -0.25 -0.0264756 -0.0746444 diff --git a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/moose_sim.py b/tests/python/Rallpacks/moose_vs_neuron/rallpack3/moose_sim.py deleted file mode 100644 index 476e1c63..00000000 --- a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/moose_sim.py +++ /dev/null @@ -1,329 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -"""moose_sim.py: - - A cable with 1000 compartments with HH-type channels in it. - -Last modified: Wed May 21, 2014 09:51AM - -""" - -__author__ = "Dilawar Singh" -__copyright__ = "Copyright 2013, NCBS Bangalore" -__credits__ = ["NCBS Bangalore", "Bhalla Lab"] -__license__ = "GPL" -__version__ = "1.0.0" -__maintainer__ = "Dilawar Singh" -__email__ = "dilawars@ncbs.res.in" -__status__ = "Development" - -import numpy as np - -import moose -from moose import utils -import time - -EREST_ACT = -65e-3 -per_ms = 1e3 -dt = 5e-5 -#dt = 1e-6 -cable = [] - - -class MooseCompartment(): - """A simple class for making MooseCompartment in moose""" - - def __init__(self, path, length, diameter, args): - """ Initialize moose-compartment """ - self.mc_ = None - self.path = path - # Following values are taken from Upi's chapter on Rallpacks - self.RM = args.get('RM', 4.0) - self.RA = args.get('RA', 1.0) - self.CM = args.get('CM', 0.01) - self.Em = args.get('Em', -0.065) - self.diameter = diameter - self.compLength = length - self.computeParams( ) - - try: - self.mc_ = moose.Compartment(self.path) - self.mc_.length = self.compLength - self.mc_.diameter = self.diameter - self.mc_.Ra = self.Ra - self.mc_.Rm = self.Rm - self.mc_.Cm = self.Cm - self.mc_.Em = self.Em - self.mc_.initVm = self.Em - - except Exception as e: - utils.dump("ERROR" - , [ "Can't create compartment with path %s " % path - , "Failed with error %s " % e - ] - ) - raise - #utils.dump('DEBUG', [ 'Compartment: {}'.format( self ) ] ) - - - def __repr__( self ): - msg = '{}: '.format( self.mc_.path ) - msg += '\n\t|- Length: {:1.4e}, Diameter: {:1.4e}'.format( - self.mc_.length, self.mc_.diameter - ) -# msg += '\n\t|- Cross-section: {:1.4e}, SurfaceArea: {:1.4e}'.format( -# self.crossSection, self.surfaceArea -# ) - msg += '\n\t|- Ra: {:1.3e}, Rm: {:1.3e}, Cm: {:1.3e}, Em: {:1.3e}'.format( - self.mc_.Ra, self.mc_.Rm, self.mc_.Cm, self.mc_.Em - ) - return msg - - def __str__( self ): - return self.__repr__( ) - - def computeParams( self ): - '''Compute essentials paramters for compartment. ''' - - self.surfaceArea = np.pi * self.compLength * self.diameter - self.crossSection = ( np.pi * self.diameter * self.diameter ) / 4.0 - self.Ra = ( self.RA * self.compLength ) / self.crossSection - self.Rm = ( self.RM / self.surfaceArea ) - self.Cm = ( self.CM * self.surfaceArea ) - -def alphaM(A, B, V0, v): - '''Compute alpha_m at point v - - aplha_m = A(v - v0 ) / (exp((v-V0)/B) - 1) - ''' - return (A*(v-V0) / (np.exp((v - V0)/B) -1 )) - -def alphaN(A, B, V0, v): - '''Compute alpha_n at point v - aplha_n = A(v-V0) / (exp((v-V0)/B) -1 ) - ''' - return alphaM(A, B, V0, v) - -def betaM(A, B, V0, v): - '''Compute beta_m at point v - ''' - return (A * np.exp((v-V0)/B)) - -def betaN(A, B, V0, v): - return betaM(A, B, V0, v) - -def alphaH(A, B, V0, v): - '''Compute alpha_h at point v - ''' - return (A * np.exp(( v - V0) / B)) - -def behaH(A, B, V0, v): - '''Compute beta_h at point v - ''' - return (A * np.exp((v-V0)/B) + 1) - -def create_na_chan(parent='/library', name='na', vmin=-110e-3, vmax=50e-3, vdivs=3000): - """Create a Hodhkin-Huxley Na channel under `parent`. - - vmin, vmax, vdivs: voltage range and number of divisions for gate tables - - """ - na = moose.HHChannel('%s/%s' % (parent, name)) - na.Xpower = 3 - na.Ypower = 1 - v = np.linspace(vmin, vmax, vdivs+1) - EREST_ACT - m_alpha = per_ms * (25 - v * 1e3) / (10 * (np.exp((25 - v * 1e3) / 10) - 1)) - m_beta = per_ms * 4 * np.exp(- v * 1e3/ 18) - m_gate = moose.element('%s/gateX' % (na.path)) - m_gate.min = vmin - m_gate.max = vmax - m_gate.divs = vdivs - m_gate.tableA = m_alpha - m_gate.tableB = m_alpha + m_beta - h_alpha = per_ms * 0.07 * np.exp(-v / 20e-3) - h_beta = per_ms * 1/(np.exp((30e-3 - v) / 10e-3) + 1) - h_gate = moose.element('%s/gateY' % (na.path)) - h_gate.min = vmin - h_gate.max = vmax - h_gate.divs = vdivs - h_gate.tableA = h_alpha - h_gate.tableB = h_alpha + h_beta - return na - -def create_k_chan(parent='/library', name='k', vmin=-120e-3, vmax=40e-3, vdivs=3000): - """Create a Hodhkin-Huxley K channel under `parent`. - - vmin, vmax, vdivs: voltage range and number of divisions for gate tables - - """ - k = moose.HHChannel('%s/%s' % (parent, name)) - k.Xpower = 4 - v = np.linspace(vmin, vmax, vdivs+1) - EREST_ACT - n_alpha = per_ms * (10 - v * 1e3)/(100 * (np.exp((10 - v * 1e3)/10) - 1)) - n_beta = per_ms * 0.125 * np.exp(- v * 1e3 / 80) - n_gate = moose.element('%s/gateX' % (k.path)) - n_gate.min = vmin - n_gate.max = vmax - n_gate.divs = vdivs - n_gate.tableA = n_alpha - n_gate.tableB = n_alpha + n_beta - return k - -def creaetHHComp(parent='/library', name='hhcomp', diameter=1e-6, length=1e-6): - """Create a compartment with Hodgkin-Huxley type ion channels (Na and - K). - - Returns a 3-tuple: (compartment, nachannel, kchannel) - - """ - compPath = '{}/{}'.format(parent, name) - mc = MooseCompartment( compPath, length, diameter, {}) - c = mc.mc_ - sarea = mc.surfaceArea - - if moose.exists('/library/na'): - moose.copy('/library/na', c.path, 'na') - else: - create_na_chan(parent = c.path) - - na = moose.element('%s/na' % (c.path)) - - # Na-conductance 120 mS/cm^2 - na.Gbar = 120e-3 * sarea * 1e4 - na.Ek = 115e-3 + EREST_ACT - - moose.connect(c, 'channel', na, 'channel') - if moose.exists('/library/k'): - moose.copy('/library/k', c.path, 'k') - else: - create_k_chan(parent = c.path) - - k = moose.element('%s/k' % (c.path)) - # K-conductance 36 mS/cm^2 - k.Gbar = 36e-3 * sarea * 1e4 - k.Ek = -12e-3 + EREST_ACT - moose.connect(c, 'channel', k, 'channel') - return (c, na, k) - -def makeCable(args): - global cable - ncomp = args['ncomp'] - moose.Neutral('/cable') - for i in range( ncomp ): - compName = 'hhcomp{}'.format(i) - hhComp = creaetHHComp( '/cable', compName ) - cable.append( hhComp[0] ) - - # connect the cable. - for i, hhc in enumerate(cable[0:-1]): - hhc.connect('axial', cable[i+1], 'raxial') - - -def setupDUT( dt ): - global cable - comp = cable[0] - data = moose.Neutral('/data') - pg = moose.PulseGen('/data/pg') - pg.firstWidth = 25e-3 - pg.firstLevel = 1e-10 - moose.connect(pg, 'output', comp, 'injectMsg') - setupClocks( dt ) - -def setupClocks( dt ): - moose.setClock(0, dt) - moose.setClock(1, dt) - -def setupSolver( hsolveDt ): - hsolvePath = '/hsolve' - hsolve = moose.HSolve( hsolvePath ) - hsolve.dt = hsolveDt - hsolve.target = '/cable' - moose.useClock(1, hsolvePath, 'process') - -def simulate( runTime, dt): - """ Simulate the cable """ - moose.useClock(0, '/cable/##', 'process') - moose.useClock(0, '/cable/##', 'init') - moose.useClock(1, '/##', 'process') - moose.reinit() - setupSolver( hsolveDt = dt ) - t = time.time( ) - moose.start( runTime ) - print( 'Time taken to simulate %f = %f' % ( runTime, time.time() - t ) ) - -def main(args): - global cable - dt = args['dt'] - makeCable(args) - setupDUT( dt ) - simulate( args['run_time'], dt ) - -if __name__ == '__main__': - import argparse - parser = argparse.ArgumentParser( - description = 'Rallpacks3: A cable with n compartment with HHChannel' - ) - parser.add_argument( '--tau' - , default = 0.04 - , type = float - , help = 'Time constant of membrane' - ) - parser.add_argument( '--run_time' - , default = 0.25 - , type = float - , help = 'Simulation run time' - ) - parser.add_argument( '--dt' - , default = 5e-5 - , type = float - , help = 'Step time during simulation' - ) - parser.add_argument( '--Em' - , default = -65e-3 - , type = float - , help = 'Resting potential of membrane' - ) - parser.add_argument( '--RA' - , default = 1.0 - , type = float - , help = 'Axial resistivity' - ) - parser.add_argument( '--lambda' - , default = 1e-3 - , type = float - , help = 'Lambda, what else?' - ) - parser.add_argument( '--x' - , default = 1e-3 - , type = float - , help = 'You should record membrane potential somewhere, right?' - ) - parser.add_argument( '--length' - , default = 1e-3 - , type = float - , help = 'Length of the cable' - ) - parser.add_argument( '--diameter' - , default = 1e-6 - , type = float - , help = 'Diameter of cable' - ) - parser.add_argument( '--inj' - , default = 1e-10 - , type = float - , help = 'Current injected at one end of the cable' - ) - parser.add_argument( '--ncomp' - , default = 1000 - , type = int - , help = 'No of compartment in cable' - ) - parser.add_argument( '--output' - , default = None - , type = str - , help = 'Store simulation results to this file' - ) - args = parser.parse_args() - main( vars(args) ) - diff --git a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/moose_vs_neuron0.png b/tests/python/Rallpacks/moose_vs_neuron/rallpack3/moose_vs_neuron0.png deleted file mode 100644 index 11ae1d14bf48d6375b429af88bc0c83d58d0aa26..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69909 zcmeFZ`9G9x_&+=|MhtGo*lRGDF_c2o2XH?f02_%IL%j3T%RT*>f{@CJXueT^&*3xZ$4f*uU;8R2d2;0u9>x$=HPiwq0T zK_D22g~|TI)H{=PVO6J2g?#^0J3TNajq7rka*z$9@7W~?|3~cO(RXxL;!$C3 zkNoz;3cXzaqe^Qo83k3ll`Y&`K6-4oIBSj<+A4D8OpIcZORB2p=HA4e5eG8VGxC(* zV)%j^Gp5g6kCmj($?So!F@D)pB5`(UwC-Db^z z7gpYr747V+p<`DA2Os%yj^6QUlOwFmG*_JexV8Ai6Hzh!*+koxzdq!RfmUWahON#K zrm8-agDgC zN!Vh#W5WaK`a9ZWORiCKW@ehjMrualo4r=ryoMe;EbSjz$O`)Tbn*MXhG+rBU}TiM zzbwRMd47uU{g%7;aHI_T*DKBJBOQO|b4W?R!?5OihUd)WqfQ%wf({rrbMHmgGe6F8 zE)-%W?9YU z%}|8!OiK0&95OR>P0X#g^dy1XB7t99LE!JuE`F|d_3`oP$r0W-Nc+R#9iba5C^TGE zf2+UXc<1UsKn&5N1 z?Hk5`3+MYmG_gj4eUCk54F0?zv)vV!Wg$avyh3+LOG}rBt_B8=Y#D4+ibA`g^Zy>~ zT65Z@fEn5cUVZWN^(PIhQ*~u!C!b40X0oP(1>y3HOzB6dmz{e@41i1MyfwwYUVgCJe%h{83^148M@&WtP+#k_~}gcjZCk4xrT+HhTbjB z&jWs+cD(Y=G-zd6FaHGN&qX@rW@ABa-yIFBf>(aA{ zg886$y`O{&pDOw9y%QX}<16~sa6K3uG+8kv>--m#or*i4pU9#*qsZX-N7=1s43|IE zg$`!y@$??cy82da>%ZTU?STGoJQvZKuKitXjNE1NuOWoLdMVAz1Ed#uC(!fX6g78T zX^8B*iY5I$e8^qKFq6NBL3`K#y$CG(e+|O(jQ`UaMj=lDunyI=4@W5)aDz@fxzs9m z=1zFCm?8S%(GniS&U6`z$(gAC1u+2>MxYVgj7ta}RiU8Eh0nU0())gls79 z74-Qt(tUDu;QBvX$}fMjywG2T@a!#Z)f@a{^Cgf|vdB#ci`!OO;|8AeN>jiM&J3A% zG11(ZQ_Ex$B!C$_VdcznUi;?E7F!zAZ<6S_1} z^DXVf{KT2b{v+$pf)*+x|DrQp9iYiIGsO@|PH$QJw{+)t9>hsBtpD%u5IRkluxSKX zTwYVNc*k%oX+#rhF!ArvYWaeJ{vs|82^cbZYrpT|EzNLlA)CrZKpKC1e25SAn)~sQ zq0N2)KS4te$zQWi)HG_~OxX zXfa{jko=eSUAw^xN3VBv4jC&hAw!p+gl*9b`t)k1+nx+1ov@jk{Xo8_VTJZ-5r@#^ z_52U6fIlW_zM^0^1K(zkjR+m4und2G;s2K=YK!q=OoHJWK_O^T+tH_0${z1fa{RH- zG__sNd*sGGxBo&z{n-Bs4f<<$<~Y40`I;f>tkvgGf#6BbnA>VpC?9~afy%XozjM|1 zZT@H9(Df~s#zVHtlVZmbVw=Tn+!7`S>b6`R47utxW)>%&?i{L9|L2Vt8$f4c=gRBO zp*>{*|AfvR3zIrgeW3|hyWfKH`H5FMFDS+CcqW*B(*IM-U<2SVwZs2-H9D`)IrD&< z5-`!}cI=N@z5h$Yp|4(HA78KOMQ-rmE7$*I^o5OrWo|oK+<0Q(S6XzL^VP3@YB4ac z(BGM#%P#(ZhX$0)$t&*+R*4DyxPa5?Z7v8NKr{Z3?90=jV_#ZSXGh}oM0xW(yPKsm zcIVpfPD90Zg&>Xkxe~9(`pTWA;o^{?LKJ3$$hg@g@>PmBf}v}EKI5p?*Pni~`Afi9 zR_F5c_RRvL4%=aWLEkq5jdZi@6-*4F99R3-L7)hvn;oL(t*Oqx&oW4aD5<8pOgSe1 zOZ|U`!v(eL&%OJk@3b@iFYq(I?T682WrQJ(c6;{zAJ?Le(==ZG8)JMUz&|YE+nL7q z*Big{fw7YLDkcB(>|hL(b?`G^E=pq~JZUSM(~u(>pYN$&`TJQDe3o#B-~I2tp*ii) z2SH@&zt++Llek5LKxAM2uL1Ww=2M3LJ09>wH#@NoLJ{0*!*5;#lxZ>fZ=r8_3w@32mO~5 zYlv+aLhyg>kj6a zKh}jIkf$BtEOQ*??+LiX+e~HF9+=60R}>Nq|{ zOlB+3DP?p8=p>rP_Kyu|`4`bT>5i~3fe-y8o0WoE##wJE(qbZ94qOLz?1Rmu_;# z`r068Y)o$ueB(56)7pd~fBk|!$DDVR&nw4N!(Xk*|9DZDPP?~`HkB(eKKFET=g^bT zS77MQ5K+Q3k)x*jvwq9sh#_wd3t_*-Q& zA+z#^%5Y{JK5=r+niV%RA`dCQd}`J6fq%KGzM+Q3j-G}C%w2slyFuFX;^Q&r8&jX3 zjIe|?Tc(~2#%l%-3sXU!?fp`{(B=2{H&Y8=!`4@MS+tfyf)5C$?0(O(Rz5Kz&7Q0; zl`#F==g>GB8F979EcBNe1XDlS-j>uI*A5X%CWk7u?8k@97%mrIL`P#8{!?IDNvOTj z`)`(#Ex#07^hRwD_pqvRC?%ufGz3HqSMU45e@6mpaQWkrW3FKAjT9H;*K(Yml4cN; zqgCPwFc3Q(mP5Aez0mkFbz8-`530o=otzFH)AQk!JYlyRu4$Lnuwz1&U3cVq`!%w^~?%T~R5T&q?-&NsjYTI{E1HP0Qj zX-^J-Q0Drl^mRFdUvmjn(e-n4PhCFnFMb~k`LLI9T~=jn?&A99!Jx^Y68lqs z0>fr+n+@;P4PLL9e)5*hia1I9P3PHcG|9{+cnT2RR&Kjug5ut+6aTNo;N9mM^?2}V zx2@SQ;8yM1mnmJc;bp>OIPMo8}$Y~FI;3fF^J zpZa{MeV@Y8CV$1N`liI}FTX5S-t`!=s2{~3efX91)o-V$mwQtLTOUbsie@UiH`T&einJ$D&Ddt4nO>FmbQ-_n%Mf_n4p&f4x?z`LSLn zB(vVyS^}v!7*@YLeiaIF{xfjwxBynam))2MaoEHRT{?H+>ocjckSR|nM9g3j<3H6O zDM2Rsu!G2iVfcm5)&ImU&x*?0K0AJ1^SI(CNC_WGISOL&6DcGb7H0Z1cP;92;YAFa zzuoO4u{nx}XskaF(pw|`?o^hX1O7s(&WhlX)rWq>{IbEI6{C=>V);blm(Tv(+x)RJ zVQ$VMFFLvh;jfIV?1Ak~vU$HfJ9~CuB&)DyhhF-R&dxLG%zPwf;_+k8+K1a$Ju=`+ zMh9RXavS73OYbT>*=h$A_*aVrg!b{_F>>%UAmHNeEh%J!KVQNsgiH7;4}a3bROm=Y z#}AzpY9#E=EgoVBOms6^pyHb7<4`u|Ouue;u>bu(dH>9bm-xXPTE9P5;82UpI*s0W z#0&dbUw;g-=*2HCu_%LOCKuS9RXV2Q2DG=kM0@ z6*rpgXmQ4?&ERqbW0*(_i|VP{lW~{GCZI z2`Os#&Y5`WBCOJ=D6D*B3#Fm!F&D!+H;+;e#l?g~+jgN}K z@7tY2m9KU*3mD9V&vSU1)4$r%>HnoI1@)FWCjg};pRq8_Y91E73t9W#Z78sounuDh3DuzB0D(w4e~0X^>6&*#$y zXy4b`l)hK8k=x2@QJy`;;e+0SPIW=@^}mz1dB0Bba+qJgzIy8F$J%X4*uIMno1;g% zgpixf3S6rsF2Jw{KEF$8Hc<7n3ZX=t$|CvWD060XKjK8_A6wwL5*^j}){o&7L&FzP zga<5dt#}dtePLVDz`gDARV#H-N=-Igx@`Zl$Dfrh9n45pBcib^WW0AqI3Wx*9lCD@ zFotx;N+~aD^Oi|iCg0(RIpX4Mq2Y}iTlTTvTWPlDr#tC#mrpscf%@6@X5V1knaUf7 zcp1_6H<{eht971=VRrlYV{_o1>a*l?CEQY-x5_@GXDAKP@E)T+Nw2K(DTM_?*Ai!^ ziEhoh>f(`eVp}$YSs$hC#_9LqDA8C_@$|8Sr_$a8DZQGrxTF({5qejT$AwM1nwJ+M zl&_j~uD`jB z!5@!1emxE~i|p76-!YpDedSOyg#hf1XXCjcOAdczovy3Sx+Z&A|47L3LHDCHlBuZH z+@~X5csHMSx6_FKNL=8E-CXGwD^Do2w#uEFFx(^K!DZ@Y#6&^{IT|O z!oND5;`(B{&s&|byBb!tAZ2TnI_CIpoB?N^ z_eE|0X@y~&W`%J0_F*r>EAFcz4(%W6dN`zF`G;?z!${0jw>nAyyJx}-1+6@!;d1ry z7AqeaQ(|;~>zFu3#Gcs)x8=}0^f77fFFwqDIyqHPW3Um0Dg%Ch4_O=7j zEj`>cLOYz3eUtLxt-rDlI_5CyfO6OI71<-ESklX{vI!UW>Evhpq0b3e;u(E#^Hq&U zEh90yNKfedXHB>$h@4c2K+AD0>3Yc4yD?~7WVDYXdtb5S z@rEx^ILdBrB4MY6mTodL_HaaMMpsGpnZa6__!n^VAMRDbp||)2jfo!uNosKO?=*^L zOqL9mbjwGa|HnB8_XjAAWeVi3a%_8!1ST!^j_Qni1{^}-bWm8Tq~ikg68Ni+4ewiw zl}Y`{Pa~S4>cJPiHhE)LENJu&p9YlFpwdw>6iuYw?dG#@K<=27bhn{UeIc@W+9`OQ8VIASE9ka|Z&xTSSQK2AxNtYN5N6hCnjzSc=5h?K zul`iUK1pY%2n>6bB#T-*C(4-PggEhxTW1k4HstogHp28fVHD>o;w7lfNpfWrMq-#N z#_385$D!{VQ3;+rfUmY*e1S%$F=Ka}8)3BTFq6xf5TzRDRg^|4^_FG%gG091l@D;n z-12ZONcb#|MSL5AWkX!O(Z3Xs95KhcVIi{Yb4s$!R$0I@e9Q3U5_oLMs0DX2%M~Hr zjM&>aM$n2=KkY}Nph9*2T2oh`rB~FvDvbSGog#vVoMbuM)+zxQkDx9g!cMKN%*xB{ z4BxaYR_)1i0;IXa0EY+6xH76Fg!ls2(83i2c^` z{j{*ML&Te-5v>}eVu{f6Jk#}sHC9*$Y!*VMjomgyKECms=SA4KrxPbcJFpiJ4H;cx z3Mfq8tYvwlZA5-@VciGjgOrvJMo2L~R;RSsq=fl#s8O=ZBLosSJ4WF&l%?9$?~#dN z26GjSi5d}SdET7=mGAvcmm?xLO38?eb0usBkr-?zW=uS{4`NL0=FO5pA2xDu^R^?KhtPr$N?_sz|u53Jx$GRWi-Y)NugQ+*+T^;t}a*%FoMw~+fc=VrSQy) zliM>P6KLczwMZhgbr%4Rz}NK=Eq16XWi zxwYxCx3^lqn6%a9cGqYZ8Ko1f?Dl4FBUGb=*u{u{W?GGR@4daf=_v7o>y4=GO*Z!B z;LL1m0$S7pRdzn_wFD@kx#><^8Pp@&N8s9Br{O!Jis}qZ5ZfU!oO{%H(GotRG?z!M z&EIKSExSqt=))%RLlS4*bL+N`XxU^JN%lsWBHu{x_9c+is6-k^g;r8;wMmZob&7Bg zEzr#GS~qSb*%385#WEqTu~GN)1cs~@KNYzAYK`9VUoXIoYa!7i!ux5IhV|FN;89m% z1rhv$`&pZ25Xb`RS&8E$?!g?zgjJ3eVtv3hE24FX0C6Ci;D12c=W?V?OnM82qyX^_ z4S6H{1FDpNEF!Y9 zU_=A^cAmt7_>mOuEcQ4!huz$ul~XHvPV%6siRaZ1p=*M%Uv?+G&E}YZ492}FLcyCLJAyE zK@^t6owV10I1@{E%9wQbM(t1t3hxYLb*9ZcYO&uFuYV%qjVj|7>H=h{Cam>?_8Ta) zYxxX!g@+S^e0DX-ZX#YN)7?07v3;Q+d)VgeA2vwUK1w!R?L#NduDwp40lx1f&{BUU z%7Iq?Rr55|Ektl9kdzXW6_!{5)MH(#F50z=eSvnD!%xeLU4$XjnCfcGx({=XeG8J1 z0G3yF7Yukaw6dK7sYhv4bDC8dSkm_`00LDl%ZuQQRmAqjZv;rlevj4fc@lGVJO`QT z^FRsE_b6O{Gt%fm+>I~<=Nd`gJOhCoDdsnLwR%2^Z1Oz0aMa(DreO#+S1Zls{^+@B zt&@tls-URVr9-X8TBELgv(~>?c5};b&fJH4c2+=wxkYBDlbL+UbM?pTz8CJvInlO@ z3|8`f3d-FL%hMm$oGjc54R)vAwq)I$na&!%sl^$K@)r|q^lRut3y@Vw9rM*%H|cYz z3zgJ9OJ*P20!N{pJUHP}5hL}WOC8DS?IZGFGEjV}4H^xHa~Tvn-D(fX6mNCk6;I>9TBBKhl*5eG~4a z{Q3PRvSM#ml`|tu$7npriePMK)^=wq4Hrs)9N-nu-P9*?uD;E=a_YqM^A>SX!8w&j zgzB)liaj}F`a65LU8)y=FJ4)&674|tFMn(Ij>iw5L1O+O!VV*P;2$iRM&+5my2*>r zk824*jgCg73h&;oO!NlJoJe&EKncL1MbZ$6RcZ+FBqA+@waG(N&>mrZB^ciq8DjML z=LP85pXpcMeAWi6LR##_Dh#ryeLzJSYSfk2dGuGy7djJPC4yg>2!*1#hbx35_S3X> zw|4TN5XmBzy5;5}KAf_nTY}kzRovA#SI0 zwTOlT0gVY2JdV_&K7DeEMqL)sQ)WdjMRs6FZa*xP z2u%uY?jZrc;Ga_v$_7w3MY2gtk$Tfsv-wWn?TjDP82)&w&@sr6xQTFR_yYkfu1^D& z=gn_qk2;VtbI)ecy~=CJNlhAwjv7f6-6D%lWb{d3L_}>B5+0K_jE>0J*0lLgW!Cg1 z3lqp@=+5f5=3TW(DcBY5wl?UnMpI?|Nn@yylvp_Ag~VF&>m)gC9Z|>uVYL2H;a1q8 zINNxFv`YL6!w8w*HjHHykI3m_fTH1y{DiNv_!2ZGZfon9O&lJJDSU3wGrj*e4fy|& zz1N?3rSyt zZb?aoq*33`IZ(va*e|TgW%qhM(%A{-;O5Wr`Z}8h2ORuK$Ey>)|^TeD}Y6wo?jsxCs*o`M}Pm_@jDiw2ccSMn& zhcpE(w*&fKcjq<&GaKw+g%3&Al6myzw&PINVc@$ie2pCmYL?8)P}U*0-B-{x?1~0n zZX>9!eItgeGubEav4n72}rq@O&v8xJ6)xDltvf7fw^2NjgiE;j<>;f z&30(%Vl0sFX7eP4X^*mBrsDgO)P_5)SZCQvNX(JqKvBVKDk)B!@HbGzeD7cKzb8j# z;NC3%oBM$%jJpsNrNhq{sX3;uVD>njUWjjP`iL-mK^f|Sx_TPn#W4XEvLEK;k_aZ} zG_;O&@|%&NT?pkg>aPMShx*HBU8J|rdJzFXJ|NbP>H3ZUuK1v>Z2oPIhNTeHj@+c& zPggM3OMRuwBsRrg5EX2C)I3gG93>pm!SGunj^0KfuaBJxFNVkFV>PDYHvhy`Tz>r< zzU8ff>t}ljT`S^27(HLW3efUZGI`pd($k$K@ zXpb6>y~eqgQg$Zb+XQ?zlVw zshOy{LV-deOX>=YUJ8%Bi$BHVl&9Q8H20(A#D|olMj#@Y?2G)iONV@pob-1IDWme6 z>*L~-6b1>R!PevG-a;wN1#Ti@HwUoyk)Z%frW(JX4^hLuT(*?_9FcVp`OSK~CtGgA zc>@qVMQY)0aooOYVf{7;nN5J)fLQ2bc8i*?=CBem(6gw}Tq=uEfRB6&J!i?Hw5cXI zuJ*gB+gc$S@al+dCwo&+u%?@MXEI#FY_8!Ewoe3sJ)~z6Kfs~Q$`^|PdzlGKcN%-$(Fl# z8&xaNB8A4UTtrA)u$)nPq6fK>_jF}BbpM;Fbm%-HY#;^JcM=GV_6h1v%2ta{;eu9( zqZ3vH0$k&hp<%`6*QKhn-%PSH1oviRIqTE;{fek`%>2(>+}Cxmm4(h_GoX4_%DH;IqA<>2vD zA`vOPWB*~FIQ3Guk2)BY__2U-+AVyahiFHU?BmQ&a%@*0kL%zeMqAuS!@>`!zgih0 zo#gu4Co{X!c}Zy7n-5cWnvHCQ6HmtWScK6N&tE97NfgAjxZ>f|vSWqu+MTASJ zu4weYxn2|#bRgn@VXE=`L*|S3#>_FFspdA_@;~^S!;2C6K>DlD*%?5NSs>XK!98_& zd{DD#Yb*>>9u(aOJqPk)=a7T(2RXDVoGUh>=)sezo!ATN3TfJ{>P-c{9_E2|L?8!3 z@A{)PGVAS$`6|AoN-$;aXsoycI~vQ?nx{$D-$j{3j%^Wkbk%@X#sNP-x$V1tHRqr{ zW**jZ?G^M~;pK{(E=hBFn7EEW5|uqHg_-A$2H6q!6O9Gn<<^iueRYtqnIiK|>A=hE ziQ*O3<+tJHmr1wShzg^WwLT%_;GUcyv77mUq%=@Ov+LKc9e50Dc_x6xH14u)dKpAA zN3B&`WMdU%4hUiqhL8uzS^~YZG;e|^So_>W{~@GyOUk|+zUv5&I0mDH&rQDb5RD?7 z`@pANCRm?)sp^nofkS$cb}GGMj&^WM^D88|QP$KJzar@#z6= z4~z(-pAzbcsoZgU%l4T`9Mm>i{F|i4&iySzgxNM&yY`)jBeoJt;h?x`=_O|VfnJ~K zA|!o8;u&Y}qZ92ZdZLhH7L+UDr!}KhnM?y^?$??U$RN;~8(P$+FX(;=SXOLa-$cBh=|3MX^jstbrDT5Ig z#Ub?{oJCt*W|(KNqx3Nv_D}oflL@)jT;O9Th&NOu{@LRmrWt(^B$3=wctoLkK<>7t z^YG(MD6(E^tcjNNJtm*q4w89B*TX||Y;~)~pm>f%Wr0^bb!)22cF-S~M=yqZwyFW- zFyQ)0Jd29uf6$TCRXLki-e$ZHr?CT*c<`I0J(FTt9;`}&EGHKpMFNd6z`phru^5(T z4x_(@y2=Vq4xJaE7q^G+r-_VM;0}mz;b*1^v-8Pkg?cKLp_h>XK>p-)EY|)?Eo%XF zHJ|qu_~D1nt3M1@KMknP7Qj7|T!qqp�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�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 diff --git a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/moose_vs_neuron1.png b/tests/python/Rallpacks/moose_vs_neuron/rallpack3/moose_vs_neuron1.png deleted file mode 100644 index 55d2529863bed16bd71d1417cfd16c1686581c98..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 66248 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 - - 1000 - - - 4.0739159584 - - - - - 1000 - - - 0.0450360774994 - - - - - 1000 - - - 3.56457614899 - - diff --git a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/neuron_sim.py b/tests/python/Rallpacks/moose_vs_neuron/rallpack3/neuron_sim.py deleted file mode 100644 index f0d8658c..00000000 --- a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/neuron_sim.py +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -"""rallpack3_moose_vs_neuron.py: - - This file compares moose and neuron for rallpack3. - -Last modified: Sun May 25, 2014 07:05AM - -""" -from __future__ import print_function - -__author__ = "Dilawar Singh" -__copyright__ = "Copyright 2013, NCBS Bangalore" -__credits__ = ["NCBS Bangalore", "Bhalla Lab"] -__license__ = "GPL" -__version__ = "1.0.0" -__maintainer__ = "Dilawar Singh" -__email__ = "dilawars@ncbs.res.in" -__status__ = "Development" - -import os -import re -import sys -import subprocess -import time -import datetime - -templateFile = './active_cable_template.nrn' - - -def getNeuronScript(args, template): - # set recording positions - compSize = args['length'] / args['ncomp'] - args['comp_length'] = compSize * 1e6 - args['0'] = (compSize / 2) * 1e3 - args['x'] = (compSize * args['ncomp'] * 1e3) - (compSize * 1e3 / 2) - args['diameter'] = args['diameter'] / 1e-6 - args['RA'] = args['RA'] * 100 - args['Em'] = args['Em'] * 1e3 - args['dt'] = args['dt'] * 1e3 - args['run_time'] = args['run_time'] * 1e3 - for k in args.keys(): - template = template.replace('||{}||'.format(k), '%s'%args[k]) - return template - -def main(args): - with open(templateFile, "r") as f: - templateTxt = f.read() - nrnText = getNeuronScript(args, templateTxt) - outFile = 'cable_in_neuron.hoc' - with open(outFile, 'w') as outF: - outF.write(nrnText) - - if os.path.isfile(outFile): - cmd = [ 'nrniv', '-nobanner', '-nogui', outFile ] - print("[STEP] Executing: {}".format(" ".join(cmd))) - t = time.time() - subprocess.check_call( cmd, shell=False) - simTime = time.time() - t - st = time.time() - stamp = datetime.datetime.fromtimestamp(st).strftime('%Y-%m-%d-%H%M%S') - with open('neuron.log', 'a') as logF: - logF.write('\n'.format(stamp)) - logF.write("\t\n") - logF.write("\t\t{}\n".format(args['ncomp'])) - logF.write("\t\n") - logF.write("\t\n") - logF.write("\t\t{}\n".format(simTime)) - logF.write("\t\n") - logF.write("\n") - else: - print("Can't write to {}".format(outFile)) - -if __name__ == '__main__': - import argparse - parser = argparse.ArgumentParser( - description = 'Rallpacks3: A cable with n compartment with HHChannel' - ) - parser.add_argument( '--tau' - , default = 0.04 - , type = float - , help = 'Time constant of membrane' - ) - parser.add_argument( '--run_time' - , default = 0.25 - , type = float - , help = 'Simulation run time' - ) - parser.add_argument( '--dt' - , default = 5e-5 - , type = float - , help = 'Step time during simulation' - ) - parser.add_argument( '--Em' - , default = -65e-3 - , type = float - , help = 'Resting potential of membrane' - ) - parser.add_argument( '--RA' - , default = 1.0 - , type = float - , help = 'Axial resistivity' - ) - parser.add_argument( '--lambda' - , default = 1e-3 - , type = float - , help = 'Lambda, what else?' - ) - parser.add_argument( '--x' - , default = 999 - , type = int - , help = 'Index of compartment at which membrane potential is recorded' - ) - parser.add_argument( '--length' - , default = 1e-3 - , type = float - , help = 'Length of the cable' - ) - parser.add_argument( '--diameter' - , default = 1e-6 - , type = float - , help = 'Diameter of cable' - ) - parser.add_argument( '--inj' - , default = 1e-10 - , type = float - , help = 'Current injected at one end of the cable' - ) - parser.add_argument( '--ncomp' - , default = 1000 - , type = int - , help = 'No of compartment in cable' - ) - parser.add_argument('--data' - , default = 'cable.out' - , type = str - , help = 'Data in text file' - ) - parser.add_argument( '--output' - , default = None - , type = str - , help = 'Store simulation results to this file' - ) - args = parser.parse_args() - main( vars(args) ) - diff --git a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/profile_neuron.sh b/tests/python/Rallpacks/moose_vs_neuron/rallpack3/profile_neuron.sh deleted file mode 100755 index da61576a..00000000 --- a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/profile_neuron.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash -echo "Profiling neuron simulator of rallpack3" -ncomp=50 -while [ $ncomp -lt 50000 ]; do - echo "Cable with compartment $ncomp" - python ./neuron_sim.py --ncomp $ncomp --data data/L$ncomp.out - ncomp=$(echo $ncomp+50 | bc) -done diff --git a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/profile_rallapck.py b/tests/python/Rallpacks/moose_vs_neuron/rallpack3/profile_rallapck.py deleted file mode 100755 index 4f451657..00000000 --- a/tests/python/Rallpacks/moose_vs_neuron/rallpack3/profile_rallapck.py +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -"""profile_rallapck.py: - -Last modified: Sat Jan 18, 2014 05:01PM - -""" -from __future__ import print_function - -__author__ = "Dilawar Singh" -__copyright__ = "Copyright 2013, NCBS Bangalore" -__credits__ = ["NCBS Bangalore", "Bhalla Lab"] -__license__ = "GPL" -__version__ = "1.0.0" -__maintainer__ = "Dilawar Singh" -__email__ = "dilawars@ncbs.res.in" -__status__ = "Development" - -import os -import sys -import subprocess -import pylab - -simclockList = {} -xvec = [] -yvecs = [] - -try: - from lxml import etree -except Exception as e: - from xml import etree - -def runRallpack3( startN = 10, stepSize = 50): - pass - -def simResult( elemXml ): - """ Get a single simXML and return a plottable entity - """ - timeStamp = elemXml.get("time_stamp") - global simclockList - global xvec - global yvecs - yvecs = [] - simclockList = {} - elementList = {} - for x in elemXml.iterchildren("elements"): - for y in x: - elementList[y.tag] = int(y.text) - if not elementList: - print("[INFO] Empty simulation. Ignoring ") - return None - for x in elemXml.iterchildren("times"): - for y in x: - simclockList[y.tag] = float( y.text ) - yvecs.append([]) - return elementList, simclockList - -def plotProfile(results, plots = []): - global xvec - global yvecs - xvec = [] - for r in results: - if r is None: - continue - xvec.append( r[0]['Compartment'] ) - for i, c in enumerate(r[1]): - yvecs[i].append( r[1][c] ) - - for i, yvec in enumerate(yvecs): - print(len(yvec), len(xvec)) - p, = pylab.plot(xvec, yvec, 'o') - plots.append(p) - -def processProfile ( profileFile ): - """ This function process the profile file given in xml format - """ - print("[STEP] Processing profile file {}".format( profileFile )) - with open( profileFile, "r") as f: - xmlTxt = f.read() - print("[INFO] Sorrounding xml with a single root tag") - xmlTxt = "{}".format( xmlTxt ) - tree = etree.fromstring( xmlTxt ) - results = [ simResult(x) for x in tree ] - return results - -def main( args ): - if args.get('input', None) is not None: - plots = [] - for inputFile in args['input']: - results = processProfile(inputFile) - plotProfile(results, plots) - #pylab.legend(plots, simclockList.keys()) - pylab.xlabel('No of compartment in active cable') - pylab.ylabel('Tiime spend by simulator') - pylab.title('Rallpack 3: Step size 10 compartments') - output = args.get('output', None) - if output is None: - pylab.show() - else: - print("[PLOT] Saving plots to {}".format(output)) - pylab.savefig(output) - else: - print("[TODO] Profile rallpack3") - -if __name__ == '__main__': - import argparse - # Argument parser. - description = '''Process profile file generated by Moose basecode ''' - parser = argparse.ArgumentParser(description=description) - parser.add_argument('-i', '--input' - , nargs = '+' - , help = 'Profile files in xml format.' - ) - parser.add_argument('-o', '--output' - , type = str - , help = 'I will store plot to this file.' - ) - args = vars(parser.parse_args()) - main( args ) diff --git a/tests/python/Rallpacks/profile_rallapck.py b/tests/python/Rallpacks/profile_rallapck.py deleted file mode 100755 index 7aae1538..00000000 --- a/tests/python/Rallpacks/profile_rallapck.py +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -"""profile_rallapck.py: - -Last modified: Sat Jan 18, 2014 05:01PM - -""" - -__author__ = "Dilawar Singh" -__copyright__ = "Copyright 2013, NCBS Bangalore" -__credits__ = ["NCBS Bangalore", "Bhalla Lab"] -__license__ = "GPL" -__version__ = "1.0.0" -__maintainer__ = "Dilawar Singh" -__email__ = "dilawars@ncbs.res.in" -__status__ = "Development" - -import os -import sys -import subprocess - -simclockList = {} -try: - from lxml import etree -except Exception as e: - from xml import etree - -def runRallpack3( startN = 10, stepSize = 50): - import rallpacks_cable_hhchannel as rallpack3 - comps = startN - while comps < 10000: - rallpack3.main( {'ncomp' : comps, 'output': 'rallpack3.png' - , 'dt' : 5e-5, 'run_time' : 0.25 } - ) - comps += stepSize - -def simResult( elemXml ): - """ Get a single simXML and return a plottable entity - """ - timeStamp = elemXml.get("time_stamp") - global simclockList - simclockList = {} - elementList = {} - for x in elemXml.iterchildren("elements"): - for y in x: - elementList[y.tag] = int(y.text) - if not elementList: - print("[INFO] Empty simulation. Ignoring ") - return None - for x in elemXml.iterchildren("times"): - for y in x: - simclockList[y.tag] = float( y.text ) - return elementList, simclockList - -def plotProfile(results, output=None): - import pylab - xvec = [] - yvecs = [[], [], []] - for r in results: - if r is None: - continue - xvec.append( r[0]['Compartment'] ) - for i, c in enumerate(r[1]): - yvecs[i].append( r[1][c] ) - - plots = [] - for i, yvec in enumerate(yvecs): - p, = pylab.plot(xvec, yvec, 'o') - plots.append(p) - - pylab.legend(plots, simclockList.keys()) - pylab.xlabel('No of compartment in active cable') - pylab.ylabel('Tiime spend by moose basecode') - pylab.title('Rallpack 3: Step size 10 compartments') - if output is None: - pylab.show() - else: - print("[PLOT] Saving plots to {}".format(output)) - pylab.savefig(output) - -def processProfile ( profileFile ): - """ This function process the profile file given in xml format - """ - print("[STEP] Processing profile file {}".format( profileFile )) - with open( profileFile, "r") as f: - xmlTxt = f.read() - print("[INFO] Sorrounding xml with a single root tag") - xmlTxt = "{}".format( xmlTxt ) - tree = etree.fromstring( xmlTxt ) - results = [ simResult(x) for x in tree ] - return results - -def main( args ): - if args.get('input', None) is not None: - results = processProfile( args['input'] ) - plotProfile(results, output=args.get('output', None)) - else: - print("[TODO] No input data file given to process. Run rallpack3 here.") - -if __name__ == '__main__': - import argparse - # Argument parser. - description = '''Process profile file generated by Moose basecode ''' - parser = argparse.ArgumentParser(description=description) - parser.add_argument('-i', '--input' - , required = False - , help = 'Profile file in xml format e.g. __moose__.dat. If not ' - ' given then I\' run the profile code to generate one.' - ) - parser.add_argument('-o', '--output' - , type = str - , help = 'I will store plot to this file.' - ) - args = vars(parser.parse_args()) - main( args ) diff --git a/tests/python/Rallpacks/rallpacks_cable_hhchannel.py b/tests/python/Rallpacks/rallpacks_cable_hhchannel.py deleted file mode 100644 index efad0d37..00000000 --- a/tests/python/Rallpacks/rallpacks_cable_hhchannel.py +++ /dev/null @@ -1,274 +0,0 @@ -# -*- coding: utf-8 -*- -"""rallpacks_cable_hhchannel.py: - -A cable with 1000 compartments with HH-type channels in it. - -Last modified: Wed May 21, 2014 09:51AM - -""" - -__author__ = "Dilawar Singh" -__copyright__ = "Copyright 2013, NCBS Bangalore" -__credits__ = ["NCBS Bangalore", "Bhalla Lab"] -__license__ = "GPL" -__version__ = "1.0.0" -__maintainer__ = "Dilawar Singh" -__email__ = "dilawars@ncbs.res.in" -__status__ = "Development" - -import moose -from moose import utils - -import time -import os -import numpy as np -import compartment as comp - - -EREST_ACT = -65e-3 -per_ms = 1e3 -dt = 5e-5 -cable = [] - -def alphaM(A, B, V0, v): - '''Compute alpha_m at point v - - aplha_m = A(v - v0 ) / (exp((v-V0)/B) - 1) - ''' - return (A*(v-V0) / (np.exp((v - V0)/B) -1 )) - -def alphaN(A, B, V0, v): - '''Compute alpha_n at point v - aplha_n = A(v-V0) / (exp((v-V0)/B) -1 ) - ''' - return alphaM(A, B, V0, v) - -def betaM(A, B, V0, v): - '''Compute beta_m at point v - ''' - return (A * np.exp((v-V0)/B)) - -def betaN(A, B, V0, v): - return betaM(A, B, V0, v) - -def alphaH(A, B, V0, v): - '''Compute alpha_h at point v - ''' - return (A * np.exp(( v - V0) / B)) - -def behaH(A, B, V0, v): - '''Compute beta_h at point v - ''' - return (A * np.exp((v-V0)/B) + 1) - -def createChannel(species, path, **kwargs): - """Create a channel """ - if species == 'na': - return sodiumChannel( path, **kwargs) - elif species == 'ca': - channel.Xpower = 4 - else: - utils.dump("FATAL", "Unsupported channel type: {}".format(species)) - raise RuntimeError("Unsupported species of chanel") - -def create_na_chan(parent='/library', name='na', vmin=-110e-3, vmax=50e-3, vdivs=3000): - """Create a Hodhkin-Huxley Na channel under `parent`. - - vmin, vmax, vdivs: voltage range and number of divisions for gate tables - - """ - na = moose.HHChannel('%s/%s' % (parent, name)) - na.Xpower = 3 - na.Ypower = 1 - v = np.linspace(vmin, vmax, vdivs+1) - EREST_ACT - m_alpha = per_ms * (25 - v * 1e3) / (10 * (np.exp((25 - v * 1e3) / 10) - 1)) - m_beta = per_ms * 4 * np.exp(- v * 1e3/ 18) - m_gate = moose.element('%s/gateX' % (na.path)) - m_gate.min = vmin - m_gate.max = vmax - m_gate.divs = vdivs - m_gate.tableA = m_alpha - m_gate.tableB = m_alpha + m_beta - h_alpha = per_ms * 0.07 * np.exp(-v / 20e-3) - h_beta = per_ms * 1/(np.exp((30e-3 - v) / 10e-3) + 1) - h_gate = moose.element('%s/gateY' % (na.path)) - h_gate.min = vmin - h_gate.max = vmax - h_gate.divs = vdivs - h_gate.tableA = h_alpha - h_gate.tableB = h_alpha + h_beta - return na - -def create_k_chan(parent='/library', name='k', vmin=-120e-3, vmax=40e-3, vdivs=3000): - """Create a Hodhkin-Huxley K channel under `parent`. - - vmin, vmax, vdivs: voltage range and number of divisions for gate tables - - """ - k = moose.HHChannel('%s/%s' % (parent, name)) - k.Xpower = 4 - v = np.linspace(vmin, vmax, vdivs+1) - EREST_ACT - n_alpha = per_ms * (10 - v * 1e3)/(100 * (np.exp((10 - v * 1e3)/10) - 1)) - n_beta = per_ms * 0.125 * np.exp(- v * 1e3 / 80) - n_gate = moose.element('%s/gateX' % (k.path)) - n_gate.min = vmin - n_gate.max = vmax - n_gate.divs = vdivs - n_gate.tableA = n_alpha - n_gate.tableB = n_alpha + n_beta - return k - -def creaetHHComp(parent='/library', name='hhcomp', diameter=1e-6, length=1e-6): - """Create a compartment with Hodgkin-Huxley type ion channels (Na and - K). - - Returns a 3-tuple: (compartment, nachannel, kchannel) - - """ - compPath = '{}/{}'.format(parent, name) - mc = comp.MooseCompartment( compPath, length, diameter, {}) - c = mc.mc_ - sarea = mc.surfaceArea - - if moose.exists('/library/na'): - moose.copy('/library/na', c.path, 'na') - else: - create_na_chan(parent = c.path) - - na = moose.element('%s/na' % (c.path)) - - # Na-conductance 120 mS/cm^2 - na.Gbar = 120e-3 * sarea * 1e4 - na.Ek = 115e-3 + EREST_ACT - - moose.connect(c, 'channel', na, 'channel') - if moose.exists('/library/k'): - moose.copy('/library/k', c.path, 'k') - else: - create_k_chan(parent = c.path) - - k = moose.element('%s/k' % (c.path)) - # K-conductance 36 mS/cm^2 - k.Gbar = 36e-3 * sarea * 1e4 - k.Ek = -12e-3 + EREST_ACT - moose.connect(c, 'channel', k, 'channel') - return (c, na, k) - -def makeCable(args): - global cable - ncomp = args['ncomp'] - moose.Neutral('/cable') - for i in range( ncomp ): - compName = 'hhcomp{}'.format(i) - hhComp = creaetHHComp( '/cable', compName ) - cable.append( hhComp[0] ) - - # connect the cable. - for i, hhc in enumerate(cable[0:-1]): - hhc.connect('axial', cable[i+1], 'raxial') - - -def setupDUT( dt ): - global cable - comp = cable[0] - data = moose.Neutral('/data') - pg = moose.PulseGen('/data/pg') - pg.firstWidth = 25e-3 - pg.firstLevel = 1e-10 - moose.connect(pg, 'output', comp, 'injectMsg') - setupClocks( dt ) - -def setupClocks( dt ): - moose.setClock(0, dt) - moose.setClock(1, dt) - -def setupSolver( hsolveDt ): - hsolvePath = '/hsolve' - hsolve = moose.HSolve( hsolvePath ) - hsolve.dt = hsolveDt - hsolve.target = '/cable' - moose.useClock(1, hsolvePath, 'process') - -def simulate( runTime, dt): - """ Simulate the cable """ - moose.reinit() - setupSolver( hsolveDt = dt ) - moose.start( runTime ) - -def main(args): - global cable - dt = args['dt'] - makeCable(args) - setupDUT( dt ) - t = time.time() - simulate( args['run_time'], dt ) - print( 'Time to run %f seconds ' % ( time.time() - t ) ) - -if __name__ == '__main__': - import argparse - parser = argparse.ArgumentParser( - description = 'Rallpacks3: A cable with n compartment with HHChannel' - ) - parser.add_argument( '--tau' - , default = 0.04 - , type = float - , help = 'Time constant of membrane' - ) - parser.add_argument( '--run_time' - , default = 0.25 - , type = float - , help = 'Simulation run time' - ) - parser.add_argument( '--dt' - , default = 5e-5 - , type = float - , help = 'Step time during simulation' - ) - parser.add_argument( '--Em' - , default = -65e-3 - , type = float - , help = 'Resting potential of membrane' - ) - parser.add_argument( '--RA' - , default = 1.0 - , type = float - , help = 'Axial resistivity' - ) - parser.add_argument( '--lambda' - , default = 1e-3 - , type = float - , help = 'Lambda, what else?' - ) - parser.add_argument( '--x' - , default = 1e-3 - , type = float - , help = 'You should record membrane potential somewhere, right?' - ) - parser.add_argument( '--length' - , default = 1e-3 - , type = float - , help = 'Length of the cable' - ) - parser.add_argument( '--diameter' - , default = 1e-6 - , type = float - , help = 'Diameter of cable' - ) - parser.add_argument( '--inj' - , default = 1e-10 - , type = float - , help = 'Current injected at one end of the cable' - ) - parser.add_argument( '--ncomp' - , default = 1000 - , type = int - , help = 'No of compartment in cable' - ) - parser.add_argument( '--output' - , default = None - , type = str - , help = 'Store simulation results to this file' - ) - args = parser.parse_args() - main( vars(args) ) - diff --git a/tests/python/Rallpacks/rallpacks_passive_cable.py b/tests/python/Rallpacks/rallpacks_passive_cable.py deleted file mode 100644 index 0d988dd9..00000000 --- a/tests/python/Rallpacks/rallpacks_passive_cable.py +++ /dev/null @@ -1,206 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -"""cable.py: A passive cable of n compartments. - -Last modified: Wed May 21, 2014 04:26AM - -""" - -__author__ = "Dilawar Singh" -__copyright__ = "Copyright 2013, NCBS Bangalore" -__credits__ = ["NCBS Bangalore", "Bhalla Lab"] -__license__ = "GPL" -__version__ = "1.0.0" -__maintainer__ = "Dilawar Singh" -__email__ = "dilawars@ncbs.res.in" -__status__ = "Development" - - -import compartment as comp - -import moose -import moose.utils as utils -import os -import pylab -import numpy as np - -class PasiveCable( ): - ''' Class representing a cable ''' - - def __init__(self, args): - ''' Initialize the cable ''' - self.length = float(args['length']) - self.ncomp = int(args['ncomp']) - self.diameter = float(args['diameter']) - - self.cablePath = '/cable' - self.tablePath = '/data' - moose.Neutral( self.cablePath ) - moose.Neutral( self.tablePath ) - # Store all moose-compartments in this list. - self.cable = [] - # Keep all simulation data in this list of tables. - self.tables = [] - # keep all stimulus in this list of tables. - self.stimTables = [] - self.makeCable( args ) - - def makeCable( self, args ): - ''' Make a cable out of n compartments ''' - for i in range( self.ncomp ): - compPath = '{}/comp{}'.format( self.cablePath, i) - l = self.length / self.ncomp - d = self.diameter - c = comp.MooseCompartment( compPath, l, d, args ) - self.cable.append(c) - self.connect( ) - utils.dump( "STEP" - , "Passive cable is connected and ready for simulation." - ) - - def connect( self ): - ''' Connect the cable ''' - utils.dump('STEP', 'Connecting cable ...') - for i, c1 in enumerate( self.cable[:-1] ): - c2 = self.cable[i+1].mc_ - c1.mc_.connect('axial', c2, 'raxial') - - def setupDUT( self ): - ''' Setup cable for recording ''' - - # Create a pulse input - moose.Neutral( self.tablePath ) - stim = moose.PulseGen( '{}/input'.format( self.tablePath) ) - stim.level[0] = 0.1e-9 - stim.width[0] = 0.25 - stim.delay[0] = 0.0 - - # Inject the current from stim to first compartment. - moose.connect( stim, 'output', self.cable[0].mc_, 'injectMsg' ) - - # Fill the data from stim into table. - inputTable = moose.Table( '{}/inputTable'.format( self.tablePath ) ) - self.stimTables.append( inputTable ) - moose.connect( inputTable, 'requestOut', stim, 'getOutputValue' ) - - def setupHSolve(self, path='/hsolve'): - """ Setup hsolve solver """ - hsolve = moose.HSolve( path ) - hsolve.dt = self.simDt - moose.useClock(1, path, 'process') - hsolve.target = self.cablePath - - - def simulate( self, simTime, simDt = 1e-3, plotDt = None ): - '''Simulate the cable ''' - - if plotDt is None: - plotDt = simDt / 2 - self.simDt = simDt - self.plotDt = plotDt - self.setupDUT( ) - - # Setup clocks - utils.dump("STEP", "Setting up the clocks ... ") - moose.setClock( 0, self.simDt ) - moose.setClock( 1, self.simDt ) - moose.setClock( 2, self.simDt ) - - ## Use clocksc - moose.useClock( 0, '/cable/##'.format(self.cablePath), 'process' ) - moose.useClock( 1, '/cable/##'.format(self.cablePath), 'init' ) - moose.useClock( 2, '{}/##'.format(self.tablePath), 'process' ) - - utils.dump("STEP" - , [ "Simulating cable for {} sec".format(simTime) - , " simDt: %s, plotDt: %s" % ( self.simDt, self.plotDt ) - ] - ) - self.setupHSolve( ) - moose.reinit( ) - utils.verify( ) - moose.start( simTime ) - -def main( args ): - cableLength = float(args['length']) - compNons = int(args['ncomp']) - compartmentSize = cableLength / compNons - cable = PasiveCable( args ) - first = 0 - last = int(int(args['x']) / compartmentSize) - 1 - table1 = utils.recordTarget('/data/table1', cable.cable[first].mc_, 'vm' ) - table2 = utils.recordTarget('/data/table2', cable.cable[last].mc_, 'vm' ) - - simTime = args['run_time'] - sim_dt = args['dt'] - outputFile = args['output'] - - cable.simulate( simTime, sim_dt ) - utils.plotTables([table1, table2] - , xscale = sim_dt - , file = outputFile - ) - utils.saveTables( [table1, table2 ] - , xscale = sim_dt - , file = 'data/rallpack2_moose.dat' - ) - #import moose.backend.spice as spice - #spice.toSpiceNetlist( output = 'cable.spice' ) - -if __name__ == '__main__': - import argparse - parser = argparse.ArgumentParser( - description = 'Rallpacks1: A cable with passive compartments' - ) - parser.add_argument( '--tau' - , default = 0.04 - , help = 'Time constant of membrane' - ) - parser.add_argument( '--run_time' - , default = 0.25 - , help = 'Simulation run time' - ) - parser.add_argument( '--dt' - , default = 5e-5 - , help = 'Step time during simulation' - ) - parser.add_argument( '--Em' - , default = -65e-3 - , help = 'Resting potential of membrane' - ) - parser.add_argument( '--RA' - , default = 1.0 - , help = 'Axial resistivity' - ) - parser.add_argument( '--lambda' - , default = 1e-3 - , help = 'Lambda, what else?' - ) - parser.add_argument( '--x' - , default = 1e-3 - , help = 'You should record membrane potential somewhere, right?' - ) - parser.add_argument( '--length' - , default = 1e-3 - , help = 'Length of the cable' - ) - parser.add_argument( '--diameter' - , default = 1e-6 - , help = 'Diameter of cable' - ) - parser.add_argument( '--inj' - , default = 1e-10 - , help = 'Current injected at one end of the cable' - ) - parser.add_argument( '--ncomp' - , default = 1000 - , help = 'No of compartment in cable' - ) - parser.add_argument( '--output' - , default = None - , help = 'Store simulation results to this file' - ) - args = parser.parse_args() - main( vars(args) ) - diff --git a/tests/python/Rallpacks/rallpacks_tree_cable.py b/tests/python/Rallpacks/rallpacks_tree_cable.py deleted file mode 100644 index c3ae7b5f..00000000 --- a/tests/python/Rallpacks/rallpacks_tree_cable.py +++ /dev/null @@ -1,250 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -"""tree_cable.py: A depth 10 binary tree like cable with following properties. - -Depth Number Length (microns) Diameter (microns) -========================================================================== -0 1 32.0 16.0 -1 2 25.4 10.08 -2 4 20.16 6.35 -3 8 16.0 4.0 -4 16 12.7 2.52 -5 32 10.08 1.587 -6 64 8.0 1.0 -7 128 6.35 0.63 -8 256 5.04 0.397 -9 512 4.0 0.25 - -The membrane properties are : -RA = 1.0 ohms meter = 100 ohms cm -RM = 4.0 ohms meter^2 = 40000 ohms cm^2 -CM = 0.01 Farads/meter^2 = 1.0 uf/cm^2 -EM = -0.065 Volts = -65 mV - -Last modified: Sat Jan 18, 2014 05:01PM - -""" -from __future__ import print_function - -__author__ = "Dilawar Singh" -__copyright__ = "Copyright 2013, NCBS Bangalore" -__credits__ = ["NCBS Bangalore", "Bhalla Lab"] -__license__ = "GPL" -__version__ = "1.0.0" -__maintainer__ = "Dilawar Singh" -__email__ = "dilawars@ncbs.res.in" -__status__ = "Development" - -import moose -import moose.utils as utils -import compartment as comp -import pylab -import numpy as np -import moose.backend.graphviz as graphviz - -def nextValuePowerOf2Law( d1, power=2.0/3.0 ): - ''' Given a value, compute the next value using 2^power law ''' - return pow(pow(d1, 1.0/power)/2.0, power) - -def testPowerLaw(): - """Test power law """ - l = [ 32.0 ] - d = [ 16.0 ] - print(nextValuePowerOf2Law( d[-1] )) - print(nextValuePowerOf2Law( l[-1], 1.0/3.0 )) - -class BinaryCable( ): - - def __init__(self, depth): - ''' init ''' - self.depth = depth - self.size = pow(2, self.depth) - 1 - self.compLenAtLevelZero = 32e-6 - self.compDiamAtLevelZero = 16.0e-6 - self.compLengthList = [ self.compLenAtLevelZero ] - self.compDiamList = [ self.compDiamAtLevelZero ] - self.cablePath = '/cable' - moose.Neutral(self.cablePath) - self.tablePath = '/data' - moose.Neutral(self.tablePath) - self.stimTables = [] - - def buildParameterLists(self): - ''' Build list of parameters in moose ''' - while len(self.compDiamList) < self.depth: - self.compDiamList.append( - nextValuePowerOf2Law(self.compDiamList[-1] ) - ) - while len(self.compLengthList) < self.depth: - self.compLengthList.append( - nextValuePowerOf2Law(self.compLengthList[-1], 1.0/3.0) - ) - - def buildCable(self, args): - ''' Build binary cable ''' - self.args = args - self.buildParameterLists() - # Cable is a list of lists. - self.cable = list() - for n, (l, d) in enumerate(zip(self.compLengthList, self.compDiamList)): - utils.dump("STEP" - , "Binary tree level {}: length {}, diameter {}".format( - n, l, d - ) - ) - noOfCompartments = pow(2, n) - compartmentList = [] - for i in range(noOfCompartments): - compPath = '{}/comp_{}_{}'.format(self.cablePath, n, i) - m = comp.MooseCompartment( compPath, l, d, args ) - compartmentList.append( m.mc_ ) - self.cable.append( compartmentList ) - self.connectCable() - - def connectCable(self): - ''' Connect the binary tree cable ''' - for i, parentList in enumerate(self.cable[:-1]): - childrenList = self.cable[i+1] - for ii, p in enumerate(parentList): - leftChild = childrenList[ 2*ii + 0 ] - rightChild = childrenList[ 2*ii + 1 ] - moose.connect( p, 'raxial', leftChild, 'axial') - moose.connect( p, 'raxial', rightChild, 'axial' ) - - def setupDUT( self ): - ''' Setup cable for recording ''' - - # Create a pulse input - moose.Neutral( self.tablePath ) - stim = moose.PulseGen( '{}/input'.format( self.tablePath) ) - stim.level[0] = self.args['inj'] - stim.width[0] = self.args['run_time'] - - # Inject the current from stim to first compartment. - moose.connect( stim, 'output', self.cable[0][0], 'injectMsg' ) - - # Fill the data from stim into table. - inputTable = moose.Table( '{}/inputTable'.format( self.tablePath ) ) - self.stimTables.append( inputTable ) - moose.connect( inputTable, 'requestOut', stim, 'getOutputValue' ) - - def recordAt( self, depth, index ): - ''' Parameter index is python list-like index. Index -1 is the last - elements in the list - ''' - utils.dump( "RECORD" - , "Adding probe at index {} and depth {}".format(index, depth) - ) - c = self.cable[depth][index] - t = moose.Table( '{}/output_at_{}'.format( self.tablePath, index )) - moose.connect( t, 'requestOut', c, 'getVm' ) - return t - - def setupSolver(self, path = '/hsolve'): - """Setting up HSolver """ - hsolve = moose.HSolve( path ) - hsolve.dt = self.simDt - moose.setClock(1, self.simDt) - moose.useClock(1, hsolve.path, 'process') - hsolve.target = self.cablePath - - def simulate(self, simTime, simDt, plotDt=None): - '''Simulate the cable - ''' - self.simDt = simDt - self.setupDUT( ) - - # Setup clocks - moose.setClock( 0, self.simDt ) - - # Use clocks - moose.useClock( 0, '/##', 'process' ) - moose.useClock( 0, '/##', 'init' ) - - utils.dump("STEP" - , [ "Simulating cable for {} sec".format(simTime) - , " simDt: %s" % self.simDt - ] - ) - utils.verify( ) - moose.reinit( ) - self.setupSolver( ) - moose.start( simTime ) - -def main( args ): - # d is depth of cable. - d = args['tree_depth'] - assert d > 0, "Cable depth can not be nagative" - binCable = BinaryCable( depth = d ) - binCable.buildCable( args ) - table0 = binCable.recordAt( depth = 0, index = 0 ) - table1 = binCable.recordAt( depth = d-1, index = -1) - print("[STIM] Simulating a cable with depth {}".format(d)) - binCable.simulate( simTime = args['run_time'], simDt = args['dt'] ) - #utils.plotTables( [ table0, table1 ] - # , file = args['output'] - # , xscale = args['dt'] - # ) - graphviz.writeGraphviz(__file__+".dot") #, compartment_shape='point') - -if __name__ == '__main__': - import argparse - parser = argparse.ArgumentParser( - description = 'Rallpacks1: A cable with passive compartments' - ) - parser.add_argument( '--tau' - , default = 0.04 - , help = 'Time constant of membrane' - ) - parser.add_argument( '--run_time' - , default = 0.25 - , help = 'Simulation run time' - ) - parser.add_argument( '--dt' - , default = 5e-5 - , help = 'Step time during simulation' - ) - parser.add_argument( '--Em' - , default = -65e-3 - , help = 'Resting potential of membrane' - ) - parser.add_argument( '--RA' - , default = 1.0 - , help = 'Axial resistivity' - ) - parser.add_argument( '--RM' - , default = 4.0 - , help = 'Membrane resistivity.' - ) - parser.add_argument( '--lambda' - , default = 1e-3 - , help = 'Lambda, what else?' - ) - parser.add_argument( '--x' - , default = 1e-3 - , help = 'You should record membrane potential somewhere, right?' - ) - parser.add_argument( '--length' - , default = 1e-3 - , help = 'Length of the cable' - ) - parser.add_argument( '--diameter' - , default = 1e-6 - , help = 'Diameter of cable' - ) - parser.add_argument( '--inj' - , default = 1e-10 - , help = 'Current injected at one end of the cable' - ) - parser.add_argument( '--tree_depth' - , default = 10 - , help = 'Depth of binary tree.' - ) - parser.add_argument( '--output' - , default = None - , help = 'Store simulation results to this file' - ) - - args = parser.parse_args() - main( vars(args) ) diff --git a/tests/python/abstrModelEqns9.py b/tests/python/abstrModelEqns9.py deleted file mode 100644 index 5745ff87..00000000 --- a/tests/python/abstrModelEqns9.py +++ /dev/null @@ -1,239 +0,0 @@ -# -*- coding: utf-8 -*- - -import re -import moose - -# Equations here are: -# Adot = 1 -6A + 5A^2 - A^3, or spread out as: -# Adot = k0a + k1a.A + k2a.A.A + k3a.A.A.A + k4a.Ca.A/(1+A+10*B) - k5a.A.B -# Bdot = k1b.A - k2b.B - - -def parseExpr( expr, params, hasCa ): - if hasCa: - expr = expr.replace( 'Ca', 'x0' ) - expr = expr.replace( 'A', 'x1' ) - expr = expr.replace( 'B', 'x2' ) - else: - expr = expr.replace( 'Ca', 'x0' ) # happens in the negFF model - expr = expr.replace( 'A', 'x0' ) # This is the usual case. - expr = expr.replace( 'B', 'x1' ) - - parts = re.split( 'k', expr ) - ret = parts[0] - for i in parts[1:]: - ret += str( params[ 'k' + i[:2] ] ) - ret += i[2:] - - if hasCa: - return 'x3*( ' + ret + ')' - else: - return 'x2*( ' + ret + ')' - -def makeChemProto( name, Aexpr, Bexpr, params ): - sw = params['stimWidth'] - diffLength = params['diffusionLength'] - dca = params['diffConstA'] * diffLength * diffLength - dcb = params['diffConstB'] * diffLength * diffLength - - # Objects - chem = moose.Neutral( '/library/' + name ) - compt = moose.CubeMesh( '/library/' + name + '/' + name ) - A = moose.Pool( compt.path + '/A' ) - B = moose.Pool( compt.path + '/B' ) - Z = moose.BufPool( compt.path + '/Z' ) - Ca = moose.BufPool( compt.path + '/Ca' ) - phase = moose.BufPool( compt.path + '/phase' ) - vel = moose.BufPool( compt.path + '/vel' ) - ampl = moose.BufPool( compt.path + '/ampl' ) - Adot = moose.Function( A.path + '/Adot' ) - Bdot = moose.Function( B.path + '/Bdot' ) - CaStim = moose.Function( Ca.path + '/CaStim' ) - A.diffConst = dca - B.diffConst = dcb - - # Equations - - Adot.expr = parseExpr( Aexpr, params, True ) - Bdot.expr = parseExpr( Bexpr, params, False ) - CaStim.expr = 'x2 * exp( -((x0 - t)^2)/(2* ' + str(sw*sw) + ') )' - - #print Adot.expr - #print Bdot.expr - #print CaStim.expr - - # Connections - Adot.x.num = 4 - moose.connect( Ca, 'nOut', Adot.x[0], 'input' ) - moose.connect( A, 'nOut', Adot.x[1], 'input' ) - moose.connect( B, 'nOut', Adot.x[2], 'input' ) - moose.connect( Z, 'nOut', Adot.x[3], 'input' ) - moose.connect( Adot, 'valueOut', A, 'increment' ) - - Bdot.x.num = 3 - if name[:5] == 'negFF': - moose.connect( Ca, 'nOut', Bdot.x[0], 'input' ) - print('Doing special msg') - else: - moose.connect( A, 'nOut', Bdot.x[0], 'input' ) - moose.connect( B, 'nOut', Bdot.x[1], 'input' ) - moose.connect( Z, 'nOut', Bdot.x[2], 'input' ) - moose.connect( Bdot, 'valueOut', B, 'increment' ) - - CaStim.x.num = 3 - moose.connect( phase, 'nOut', CaStim.x[0], 'input' ) - moose.connect( vel, 'nOut', CaStim.x[1], 'input' ) - moose.connect( ampl, 'nOut', CaStim.x[2], 'input' ) - moose.connect( CaStim, 'valueOut', Ca, 'setN' ) - - return compt - - -def makeBis( args = None ): - params = { - 'k0a':0.1, # Constant - 'k1a':-5.0, # Coeff for A - 'k2a':5.0, # Coeff for A^2 - 'k3a':-1.0, # Coeff for A^3 - 'k4a':10.0, # turnon of A by A and Ca - 'k5a':-5.0, # Turnoff of A by B - 'k1b':0.01, # turnon of B by A - 'k2b':-0.01, # Decay rate of B - 'diffusionLength':1.0e-6, # Diffusion characteristic length, used as voxel length too. - 'dendDiameter': 10e-6, # Diameter of section of dendrite in model - 'dendLength': 100e-6, # Length of section of dendrite in model - 'diffConstA':5.0, # Diffusion constant of A - 'diffConstB':2.0, # Diffusion constant of B - 'stimWidth' :1.0, # Stimulus width in seconds - 'stimAmplitude':1.0, # Stimulus amplitude, arb units. From FHN review - 'blankVoxelsAtEnd':10, # of voxels to leave blank at end of cylinder - 'preStimTime':10.0, # Time to run before turning on stimulus. - 'postStimTime':40.0, # Time to run after stimulus. ~3x decay time - 'settleTime':20.0, # Settling time of response, after stimulus. - # To include in analysis of total response over - # entire dendrite. - 'fnumber':1, # Number to append to fname - } - - for i in args: - params[i] = args[i] - - makeChemProto( 'bis', - 'k0a + k1a*A + k2a*A*A + k3a*A*A*A + k4a*Ca*A/(1+A+10*B) + k5a*A*B', - 'k1b*A*A + k2b*B', - params ) - return params - -def makeFHN( args = None ): - params = { - 'k_t':2.5, # Time-const. - 'k_a':0.7, # Coeff1 - 'k_b':0.8, # Coeff2 - 'kxa': 2.0, # Offset for V for FHN eqns. - 'kxb': 0.8, # Offset for W for FHN eqns. - 'diffusionLength':1.0e-6, # Diffusion characteristic length, used as voxel length too. - 'dendDiameter': 10e-6, # Diameter of section of dendrite in model - 'dendLength': 100e-6, # Length of section of dendrite in model - 'diffConstA':7.5, # Diffusion constant of A - 'diffConstB':5.0, # Diffusion constant of B - 'stimWidth' :1.0, # Stimulus width in seconds - 'stimAmplitude':0.4, # Stimulus amplitude, arb units. From FHN review - 'blankVoxelsAtEnd':10, # of voxels to leave blank at end of cylinder - 'preStimTime':10.0, # Time to run before turning on stimulus. - 'postStimTime':40.0, # Time to run after stimulus. ~3x decay time - 'settleTime':20.0, # Settling time of response, after stimulus. - # To include in analysis of total response over - # entire dendrite. - 'fnumber': 1, # Number to append to fname - } - - for i in args: - params[i] = args[i] - - makeChemProto( 'fhn', - '5.0*(A - kxa - (A-kxa)^3/3 - (B-kxb) + Ca)', - '(A-kxa + k_a - k_b*(B-kxb))/k_t', - params ) - # We do this to get the system to settle at the start. - B = moose.element( '/library/fhn/fhn/B' ) - B.nInit = 0.2 - return params - - -def makeNegFB( args = None ): - params = { - 'k1a':-0.1, # Coeff for decay of A, slow. - 'k2a':-0.2, # Coeff for turnoff of A by B, medium. - 'k3a':10.0, # turnon of A by Ca, fast. - 'k1b':0.2, # turnon of B by A, medium - 'k2b':-0.1, # Decay rate of B, slow - 'diffusionLength':1.0e-6, # Diffusion characteristic length, used as voxel length too. - 'dendDiameter': 10e-6, # Diameter of section of dendrite in model - 'dendLength': 100e-6, # Length of section of dendrite in model - 'diffConstA':0.5, # Diffusion constant of A - 'diffConstB':1.0, # Diffusion constant of B - 'stimWidth' :1.0, # Stimulus width in seconds - 'stimAmplitude':1.0, # Stimulus amplitude, arb units. From FHN review - 'blankVoxelsAtEnd':10, #of voxels to leave blank at end of cylinder - 'preStimTime':10.0, # Time to run before turning on stimulus. - 'postStimTime':40.0, # Time to run after stimulus. ~3x decay time - 'settleTime':20.0, # Settling time of response, after stimulus. - # To include in analysis of total response over - # entire dendrite. - 'fnumber':1, # Number to append to fname - } - - for i in args: - params[i] = args[i] - - makeChemProto( 'negFB', - 'k1a*A + k2a*A*B + k3a*Ca', - 'k1b*A + k2b*B', - params ) - return params - -# Was negFF2 in earlier versions of abstrModelEqns -def makeNegFF( args = None ): - params = { - 'k1a':-0.1, # Coeff for decay of A, slow. - 'k2a':-0.01, # Coeff for turnoff of A by B, medium. - 'k3a':10.0, # turnon of A by Ca, fast. - 'k4a':40.0, # amount of B inhibition of turnon of A by Ca. - 'k1b':2.0, # turnon of B by Ca, medium - 'k2b':-0.05, # Decay rate of B, slow - 'diffusionLength':1.0e-6, # Diffusion characteristic length, used as voxel length too. - 'dendDiameter': 10e-6, # Diameter of section of dendrite in model - 'dendLength': 100e-6, # Length of section of dendrite in model - 'diffConstA':0.02, # Diffusion constant of A - 'diffConstB':0.4, # Diffusion constant of B - 'stimWidth' :1.0, # Stimulus width in seconds - 'stimAmplitude':10.0, # Stimulus amplitude, arb units. From FHN review - 'blankVoxelsAtEnd':10, # of voxels to leave blank at end of cylinder - 'preStimTime':10.0, # Time to run before turning on stimulus. - 'postStimTime':40.0, # Time to run after stimulus. ~3x decay time - 'settleTime':20.0, # Settling time of response, after stimulus. - # To include in analysis of total response over - # entire dendrite. - 'fnumber':1, # Number to append to fname - } - - for i in args: - params[i] = args[i] - - makeChemProto( 'negFF', - 'k1a*A + k2a*A*B + k3a*Ca/(1+k4a*B*B)', - 'k1b*Ca + k2b*B', - params ) - - return params - -if __name__ == '__main__': - moose.Neutral( '/library' ) - print("Making Bistable model") - makeBis() - print("Making FHN model") - makeFHN() - print("Making Negative Feedback model") - makeNegFB() - print("Making Negative Feedforward models") - makeNegFF() diff --git a/tests/python/chem_models/acc27.g b/tests/python/chem_models/acc27.g deleted file mode 100644 index 04f97d20..00000000 --- a/tests/python/chem_models/acc27.g +++ /dev/null @@ -1,347 +0,0 @@ -// DOQCS : http://doqcs.ncbs.res.in/ -// Accession Name = MAPK_osc -// Accession Number = 27 -// Transcriber = Sridhar Hariharaputran, NCBS -// Developer = Boris N. Kholodenko -// Species = Xenopus -// Tissue = Oocyte extract -// Cell Compartment = Cytosol -// Notes = This MAPK model is based on Boris N. Kholodenko Eur J Biochem. (2000) 267(6):1583-8 for data from Xenopus oocytes extracts. - - //genesis -// kkit Version 11 flat dumpfile - -// Saved on Thu Dec 8 10:58:02 2005 - -include kkit {argv 1} - -FASTDT = 5e-05 -SIMDT = 0.005 -CONTROLDT = 10 -PLOTDT = 5 -MAXTIME = 6000 -TRANSIENT_TIME = 2 -VARIABLE_DT_FLAG = 1 -DEFAULT_VOL = 1.6667e-21 -VERSION = 11.0 -setfield /file/modpath value /home2/bhalla/scripts/modules -kparms - -//genesis - -initdump -version 3 -ignoreorphans 1 -simobjdump doqcsinfo filename accessname accesstype transcriber developer \ - citation species tissue cellcompartment methodology sources \ - model_implementation model_validation x y z -simobjdump table input output alloced step_mode stepsize x y z -simobjdump xtree path script namemode sizescale -simobjdump xcoredraw xmin xmax ymin ymax -simobjdump xtext editable -simobjdump xgraph xmin xmax ymin ymax overlay -simobjdump xplot pixflags script fg ysquish do_slope wy -simobjdump group xtree_fg_req xtree_textfg_req plotfield expanded movealone \ - link savename file version md5sum mod_save_flag x y z -simobjdump geometry size dim shape outside xtree_fg_req xtree_textfg_req x y \ - z -simobjdump kpool DiffConst CoInit Co n nInit mwt nMin vol slave_enable \ - geomname xtree_fg_req xtree_textfg_req x y z -simobjdump kreac kf kb notes xtree_fg_req xtree_textfg_req x y z -simobjdump kenz CoComplexInit CoComplex nComplexInit nComplex vol k1 k2 k3 \ - keepconc usecomplex notes xtree_fg_req xtree_textfg_req link x y z -simobjdump stim level1 width1 delay1 level2 width2 delay2 baselevel trig_time \ - trig_mode notes xtree_fg_req xtree_textfg_req is_running x y z -simobjdump xtab input output alloced step_mode stepsize notes editfunc \ - xtree_fg_req xtree_textfg_req baselevel last_x last_y is_running x y z -simobjdump kchan perm gmax Vm is_active use_nernst notes xtree_fg_req \ - xtree_textfg_req x y z -simobjdump transport input output alloced step_mode stepsize dt delay clock \ - kf xtree_fg_req xtree_textfg_req x y z -simobjdump proto x y z -simundump geometry /kinetics/geometry 0 1.6667e-21 3 sphere "" white black 10 \ - 9 0 -simundump group /kinetics/MAPK 0 yellow black x 0 0 "" MAPK \ - /home2/bhalla/scripts/modules/MAPK_0.g 0 0 0 1 10 0 -simundump kpool /kinetics/MAPK/MAPK 0 0 0.3 0.3 0.3 0.3 0 0 1 0 \ - /kinetics/geometry 35 yellow -8 -7 0 -simundump kpool /kinetics/MAPK/MKKK 0 0 0.1 0.1 0.1 0.1 0 0 1 0 \ - /kinetics/geometry 16 yellow -8 5 0 -simundump kpool /kinetics/MAPK/MKK 0 0 0.3 0.3 0.3 0.3 0 0 1 0 \ - /kinetics/geometry 60 yellow -8 -1 0 -simundump kpool /kinetics/MAPK/int1 0 0 0.001 0.001 0.001 0.001 0 0 1 0 \ - /kinetics/geometry 30 yellow -4 4 0 -simundump kenz /kinetics/MAPK/int1/2 0 0 0 0 0 0.001 156.25 1 0.25 0 1 "" red \ - 30 "" -4 5 0 -simundump kpool /kinetics/MAPK/MKKK-P 0 0 0 0 0 0 0 0 1 0 /kinetics/geometry \ - 51 yellow 0 5 0 -simundump kenz /kinetics/MAPK/MKKK-P/3 0 0 0 0 0 0.001 8.3333 0.1 0.025 0 1 \ - "" red 51 "" -4 2 0 -simundump kenz /kinetics/MAPK/MKKK-P/4 0 0 0 0 0 0.001 8.3333 0.1 0.025 0 1 \ - "" red 51 "" 4 2 0 -simundump kpool /kinetics/MAPK/int3 0 0 0.001 0.001 0.001 0.001 0 0 1 0 \ - /kinetics/geometry blue yellow -4 -2 0 -simundump kenz /kinetics/MAPK/int3/6 0 0 0 0 0 0.001 250 3 0.75 0 1 "" red \ - blue "" -4 -1 0 -simundump kpool /kinetics/MAPK/int5 0 0 0.001 0.001 0.001 0.001 0 0 1 0 \ - /kinetics/geometry 1 yellow -4 -8 0 -simundump kenz /kinetics/MAPK/int5/10 0 0 0 0 0 0.001 166.67 2 0.5 0 1 "" red \ - 1 "" -4 -7 0 -simundump kpool /kinetics/MAPK/MKK-P 0 0 0 0 0 0 0 0 1 0 /kinetics/geometry 5 \ - yellow 0 -1 0 -simundump kpool /kinetics/MAPK/MAPK-P 0 0 0 0 0 0 0 0 1 0 /kinetics/geometry \ - 55 yellow 0 -7 0 -simundump kpool /kinetics/MAPK/int2 0 0 0.001 0.001 0.001 0.001 0 0 1 0 \ - /kinetics/geometry 2 yellow 4 -2 0 -simundump kenz /kinetics/MAPK/int2/5 0 0 0 0 0 0.001 250 3 0.75 0 1 "" red 2 \ - "" 4 -1 0 -simundump kpool /kinetics/MAPK/int4 0 0 0.001 0.001 0.001 0.001 0 0 1 0 \ - /kinetics/geometry 17 yellow 4 -8 0 -simundump kenz /kinetics/MAPK/int4/9 0 0 0 0 0 0.001 166.67 2 0.5 0 1 "" red \ - 17 "" 4 -7 0 -simundump kpool /kinetics/MAPK/Ras-MKKKK 0 0 0.001 0.001 0.001 0.001 0 0 1 0 \ - /kinetics/geometry 47 yellow 6 8 0 -simundump kenz /kinetics/MAPK/Ras-MKKKK/1 0 0 0 0 0 0.001 1250 10 2.5 0 1 "" \ - red 47 "" -4 8 0 -simundump kpool /kinetics/MAPK/inactiveRas-MKKK 0 0 0 0 0 0 0 0 1 0 \ - /kinetics/geometry 30 yellow 11 8 0 -simundump kreac /kinetics/MAPK/Neg_feedback 0 1 0.009 "" white yellow 11 2 0 -simundump kpool /kinetics/MAPK/MKK-PP 0 0 0 0 0 0 0 0 1 0 /kinetics/geometry \ - 60 yellow 8 -1 0 -simundump kenz /kinetics/MAPK/MKK-PP/7 0 0 0 0 0 0.001 8.3333 0.1 0.025 0 1 \ - "" red 60 "" -4 -4 0 -simundump kenz /kinetics/MAPK/MKK-PP/8 0 0 0 0 0 0.001 8.3333 0.1 0.025 0 1 \ - "" red 60 "" 4 -4 0 -simundump kpool /kinetics/MAPK/MAPK-PP 0 0 0 0 0 0 0 0 1 0 /kinetics/geometry \ - 46 yellow 8 -7 0 -simundump doqcsinfo /kinetics/doqcsinfo 0 db27.g MAPK_osc pathway \ - "Sridhar Hariharaputran, NCBS" " Boris N. Kholodenko" "citation here" \ - Xenopus "Oocyte extract" Cytosol Hypothetical \ - "Boris N. Kholodenko Eur J Biochem. (2000) 267(6):1583-8 ( peer-reviewed publication )" \ - "Mathematically equivalent" "Qualitative predictions" 10 11 0 -simundump xgraph /graphs/conc1 0 0 6000 0 0.3 0 -simundump xgraph /graphs/conc2 0 0 6000 4.5157e-05 0.3 0 -simundump xplot /graphs/conc1/MAPK-PP.Co 3 524288 \ - "delete_plot.w ; edit_plot.D " 46 0 0 1 -simundump xplot /graphs/conc1/MAPK.Co 3 524288 \ - "delete_plot.w ; edit_plot.D " 35 0 0 1 -simundump xplot /graphs/conc2/Ras-MKKKK.Co 3 524288 \ - "delete_plot.w ; edit_plot.D " 47 0 0 1 -simundump xplot /graphs/conc2/MAPK.Co 3 524288 \ - "delete_plot.w ; edit_plot.D " 35 0 0 1 -simundump xplot /graphs/conc2/MKKK.Co 3 524288 \ - "delete_plot.w ; edit_plot.D " 16 0 0 1 -simundump xplot /graphs/conc2/MKK.Co 3 524288 \ - "delete_plot.w ; edit_plot.D " 60 0 0 1 -simundump xgraph /moregraphs/conc3 0 0 6000 0 1 0 -simundump xgraph /moregraphs/conc4 0 0 6000 0 1 0 -simundump xcoredraw /edit/draw 0 -10 13 -10 13 -simundump xtree /edit/draw/tree 0 \ - /kinetics/#[],/kinetics/#[]/#[],/kinetics/#[]/#[]/#[][TYPE!=proto],/kinetics/#[]/#[]/#[][TYPE!=linkinfo]/##[] \ - "edit_elm.D ; drag_from_edit.w " auto 0.6 -simundump xtext /file/notes 0 1 -xtextload /file/notes \ -"22 Jan 2002" \ -" " \ -" This model is based on Kholodenko, B.N." \ -" Eur. J. Biochem. 267, 1583-1588(2000)" \ -"" -addmsg /kinetics/MAPK/MKK-PP/7 /kinetics/MAPK/MAPK REAC sA B -addmsg /kinetics/MAPK/int5/10 /kinetics/MAPK/MAPK MM_PRD pA -addmsg /kinetics/MAPK/Ras-MKKKK/1 /kinetics/MAPK/MKKK REAC sA B -addmsg /kinetics/MAPK/int1/2 /kinetics/MAPK/MKKK MM_PRD pA -addmsg /kinetics/MAPK/MKKK-P/3 /kinetics/MAPK/MKK REAC sA B -addmsg /kinetics/MAPK/int3/6 /kinetics/MAPK/MKK MM_PRD pA -addmsg /kinetics/MAPK/int1 /kinetics/MAPK/int1/2 ENZYME n -addmsg /kinetics/MAPK/MKKK-P /kinetics/MAPK/int1/2 SUBSTRATE n -addmsg /kinetics/MAPK/Ras-MKKKK/1 /kinetics/MAPK/MKKK-P MM_PRD pA -addmsg /kinetics/MAPK/int1/2 /kinetics/MAPK/MKKK-P REAC sA B -addmsg /kinetics/MAPK/MKKK-P /kinetics/MAPK/MKKK-P/3 ENZYME n -addmsg /kinetics/MAPK/MKK /kinetics/MAPK/MKKK-P/3 SUBSTRATE n -addmsg /kinetics/MAPK/MKKK-P /kinetics/MAPK/MKKK-P/4 ENZYME n -addmsg /kinetics/MAPK/MKK-P /kinetics/MAPK/MKKK-P/4 SUBSTRATE n -addmsg /kinetics/MAPK/int3 /kinetics/MAPK/int3/6 ENZYME n -addmsg /kinetics/MAPK/MKK-P /kinetics/MAPK/int3/6 SUBSTRATE n -addmsg /kinetics/MAPK/int5 /kinetics/MAPK/int5/10 ENZYME n -addmsg /kinetics/MAPK/MAPK-P /kinetics/MAPK/int5/10 SUBSTRATE n -addmsg /kinetics/MAPK/MKKK-P/4 /kinetics/MAPK/MKK-P REAC sA B -addmsg /kinetics/MAPK/MKKK-P/3 /kinetics/MAPK/MKK-P MM_PRD pA -addmsg /kinetics/MAPK/int3/6 /kinetics/MAPK/MKK-P REAC sA B -addmsg /kinetics/MAPK/int2/5 /kinetics/MAPK/MKK-P MM_PRD pA -addmsg /kinetics/MAPK/MKK-PP/8 /kinetics/MAPK/MAPK-P REAC sA B -addmsg /kinetics/MAPK/MKK-PP/7 /kinetics/MAPK/MAPK-P MM_PRD pA -addmsg /kinetics/MAPK/int5/10 /kinetics/MAPK/MAPK-P REAC sA B -addmsg /kinetics/MAPK/int4/9 /kinetics/MAPK/MAPK-P MM_PRD pA -addmsg /kinetics/MAPK/int2 /kinetics/MAPK/int2/5 ENZYME n -addmsg /kinetics/MAPK/MKK-PP /kinetics/MAPK/int2/5 SUBSTRATE n -addmsg /kinetics/MAPK/int4 /kinetics/MAPK/int4/9 ENZYME n -addmsg /kinetics/MAPK/MAPK-PP /kinetics/MAPK/int4/9 SUBSTRATE n -addmsg /kinetics/MAPK/Neg_feedback /kinetics/MAPK/Ras-MKKKK REAC A B -addmsg /kinetics/MAPK/Ras-MKKKK /kinetics/MAPK/Ras-MKKKK/1 ENZYME n -addmsg /kinetics/MAPK/MKKK /kinetics/MAPK/Ras-MKKKK/1 SUBSTRATE n -addmsg /kinetics/MAPK/Neg_feedback /kinetics/MAPK/inactiveRas-MKKK REAC B A -addmsg /kinetics/MAPK/MAPK-PP /kinetics/MAPK/Neg_feedback SUBSTRATE n -addmsg /kinetics/MAPK/Ras-MKKKK /kinetics/MAPK/Neg_feedback SUBSTRATE n -addmsg /kinetics/MAPK/inactiveRas-MKKK /kinetics/MAPK/Neg_feedback PRODUCT n -addmsg /kinetics/MAPK/MKKK-P/4 /kinetics/MAPK/MKK-PP MM_PRD pA -addmsg /kinetics/MAPK/int2/5 /kinetics/MAPK/MKK-PP REAC sA B -addmsg /kinetics/MAPK/MKK-PP /kinetics/MAPK/MKK-PP/7 ENZYME n -addmsg /kinetics/MAPK/MAPK /kinetics/MAPK/MKK-PP/7 SUBSTRATE n -addmsg /kinetics/MAPK/MKK-PP /kinetics/MAPK/MKK-PP/8 ENZYME n -addmsg /kinetics/MAPK/MAPK-P /kinetics/MAPK/MKK-PP/8 SUBSTRATE n -addmsg /kinetics/MAPK/MKK-PP/8 /kinetics/MAPK/MAPK-PP MM_PRD pA -addmsg /kinetics/MAPK/int4/9 /kinetics/MAPK/MAPK-PP REAC sA B -addmsg /kinetics/MAPK/Neg_feedback /kinetics/MAPK/MAPK-PP REAC A B -addmsg /kinetics/MAPK/MAPK-PP /graphs/conc1/MAPK-PP.Co PLOT Co *MAPK-PP.Co *46 -addmsg /kinetics/MAPK/MAPK /graphs/conc1/MAPK.Co PLOT Co *MAPK.Co *35 -addmsg /kinetics/MAPK/Ras-MKKKK /graphs/conc2/Ras-MKKKK.Co PLOT Co *Ras-MKKKK.Co *47 -addmsg /kinetics/MAPK/MAPK /graphs/conc2/MAPK.Co PLOT Co *MAPK.Co *35 -addmsg /kinetics/MAPK/MKKK /graphs/conc2/MKKK.Co PLOT Co *MKKK.Co *16 -addmsg /kinetics/MAPK/MKK /graphs/conc2/MKK.Co PLOT Co *MKK.Co *60 -enddump -// End of dump - -call /kinetics/MAPK/notes LOAD \ -"This is the oscillatory MAPK model from Kholodenko 2000" \ -"Eur J. Biochem 267:1583-1588" \ -"The original model is formulated in terms of idealized" \ -"Michaelis-Menten enzymes and the enzyme-substrate complex" \ -"concentrations are therefore assumed negligible. The" \ -"current implementation of the model uses explicit enzyme" \ -"reactions involving substrates and is therefore an" \ -"approximation to the Kholodenko model. The approximation is" \ -"greatly improved if the enzyme is flagged as Available" \ -"which is an option in Kinetikit. This flag means that the" \ -"enzyme protein concentration is not reduced even when it" \ -"is involved in a complex. However, the substrate protein" \ -"continues to participate in enzyme-substrate complexes" \ -"and its concentration is therefore affected. Overall," \ -"this model works almost the same as the Kholodenko model" \ -"but the peak MAPK-PP amplitudes are a little reduced and" \ -"the period of oscillations is about 10% longer." \ -"If the enzymes are not flagged as Available then the" \ -"oscillations commence only when the Km for enzyme 1" \ -"is set to 0.1 uM." -call /kinetics/MAPK/MAPK/notes LOAD \ -"The total concn. of MAPK is 300nM " \ -"from" \ -"Kholodenko, 2000." -call /kinetics/MAPK/MKKK/notes LOAD \ -"The total concn. of MKKK is 100nM " \ -"from" \ -"Kholodenko, 2000" -call /kinetics/MAPK/MKK/notes LOAD \ -"The total concn. of MKK is 300nM " \ -"from" \ -"Kholodenko,2000" -call /kinetics/MAPK/int1/notes LOAD \ -"This is the intermediate enzyme which catalyses the " \ -"dephosphorylation of MKKK-P to MKKK. The concentration" \ -"is set to 1 nM based on" \ -"from" \ -"Kholodenko, 2000" -call /kinetics/MAPK/int1/2/notes LOAD \ -"Km is 8nM and Vmax is 0.25nM.s-1 " \ -"from" \ -"Kholodenko, 2000." -call /kinetics/MAPK/MKKK-P/notes LOAD \ -"This is the phosphorylated form of MKKK which converts MKK" \ -"to MKK-P and then to MKK-PP" \ -"from" \ -"Kholodenko, 2000." -call /kinetics/MAPK/MKKK-P/3/notes LOAD \ -"Km is 15 nM and Vmax is 0.025s-1" \ -"from" \ -"Kholodenko, 2000" -call /kinetics/MAPK/MKKK-P/4/notes LOAD \ -"Km is 15nM and Vmax is 0.025s-1" \ -"from " \ -"Kholodenko, 2000." -call /kinetics/MAPK/int3/notes LOAD \ -"This intermediate enzyme catalyses the dephosphorylation of" \ -"MKK-P to MKK. The concentration is 1nM" \ -"from" \ -"Kholodenko, 2000" -call /kinetics/MAPK/int3/6/notes LOAD \ -"The Km is 15nM and the Vmax is 0.75nM.s-1" \ -"from" \ -"Kholodenko 2000." -call /kinetics/MAPK/int5/notes LOAD \ -"This catalyses the conversion of MAPK-P to MAPK. The " \ -"concenration is 1nM." \ -"from" \ -"Kholodenko, 2000" -call /kinetics/MAPK/int5/10/notes LOAD \ -"The Km is 15nM and Vmax is 0.5nM.s-1" \ -"from" \ -"Kholodenko, 2000" -call /kinetics/MAPK/MKK-P/notes LOAD \ -"This is the single phoshorylated form of MKK." \ -"from" \ -"Kholodenko, 2000." -call /kinetics/MAPK/MAPK-P/notes LOAD \ -"This is the single phopshorylated form of MAPK" \ -"from" \ -"Kholodenko, 2000." -call /kinetics/MAPK/int2/notes LOAD \ -"This intermediate enzyme which catalyses the dephosphorylation of" \ -"MKK-PP to MKK-P. The concentration is 1nM." \ -"from" \ -"Kholodenko, 2000" -call /kinetics/MAPK/int2/5/notes LOAD \ -"The Km is 15nM and Vmax is 0.75nM.s-1 " \ -"from" \ -"Kholodenko, 2000" \ -"" -call /kinetics/MAPK/int4/notes LOAD \ -"This intermediate enzyme catalyses the dephosphorylation of" \ -"MAPK-PP to MAPK-P. The concentration is 1nM." \ -"from" \ -"Kholodenko, 2000" -call /kinetics/MAPK/int4/9/notes LOAD \ -"The Km is 15nM and Vmax is 0.5nM.s-1 " \ -"from" \ -"Kholodenko, 2000" -call /kinetics/MAPK/Ras-MKKKK/notes LOAD \ -"The concn. of Ras-MKKKK* is set to 1 nM implicitly" \ -"from" \ -"Kholodenko, 2000" -call /kinetics/MAPK/Ras-MKKKK/1/notes LOAD \ -"The Km is 10nM and Vmax is 2.5nM sec^-1. We assume that" \ -"there is 1 nM of the Ras-MKKKK." \ -"From Kholodenko, 2000." \ -"" \ -"If the enzymes are not flagged as Available, then this" \ -"Km should be set to 0.1 to obtain oscillations." -call /kinetics/MAPK/inactiveRas-MKKK/notes LOAD \ -"This is the inactive form of Ras-MKKK. Based on the" \ -"reaction scheme from Kholodenko 2000, this is equivalent" \ -"to a binding of the MAPK-PP to the Ras. The amount of" \ -"Ras in the model is small enough that negligible amounts" \ -"of MAPK are involved in this reaction. So it is a fair" \ -"approximation to the negative feedback mechanism from" \ -"Kholodenko, 2000." -call /kinetics/MAPK/Neg_feedback/notes LOAD \ -"From Kholodenko, 2000 Eur J Biochem 267" \ -"the Kd is 9 nM. We use a rather fast Kf of 1/sec/uM" \ -"so that equilibrium is maintained." \ -"" -call /kinetics/MAPK/MKK-PP/notes LOAD \ -"This is the double phosphorylated and active form of MKK" \ -"from" \ -"Kholodenko, 2000" -call /kinetics/MAPK/MKK-PP/7/notes LOAD \ -"The Km is 15nM which is 0.015uM Vmax is 0.025s-1" \ -"from" \ -"Kholodenko, 2000." \ -"" -call /kinetics/MAPK/MKK-PP/8/notes LOAD \ -"The Km is 15nM which is 0.015uM and Vmax is 0.025s-1" \ -"from" \ -"Kholodenko, 2000" \ -"" -call /kinetics/MAPK/MAPK-PP/notes LOAD \ -"This is the double phosphorylated and active form of MAPK." \ -"from" \ -"Kholodenko, 2000." -call /kinetics/doqcsinfo/notes LOAD \ -"This MAPK model is based on Boris N. Kholodenko Eur J Biochem. (2000) 267(6):1583-8 for data from Xenopus oocytes extracts." -complete_loading diff --git a/tests/python/deprecated_test_gc.py b/tests/python/deprecated_test_gc.py deleted file mode 100644 index 5ae78d0e..00000000 --- a/tests/python/deprecated_test_gc.py +++ /dev/null @@ -1,138 +0,0 @@ -# -*- coding: utf-8 -*- -# test_gc.py --- -# -# Filename: test_gc.py -# Description: -# Author: Subhasis Ray -# Maintainer: -# Created: Mon May 19 10:25:13 2014 (+0530) -# Version: -# Last-Updated: -# By: -# Update #: 0 -# URL: -# Keywords: -# Compatibility: -# -# - -# Commentary: -# -# -# -# - -# Change log: -# -# -# -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 3, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, Fifth -# Floor, Boston, MA 02110-1301, USA. -# -# - -# Code: -"""Test script for memory allocation and garbage collection issues.""" - -from __future__ import print_function -try: - from future_builtins import zip, range -except ImportError: - pass -import random -from collections import defaultdict -from itertools import cycle - -import moose - -classes = [ - 'Reac', - 'IzhikevichNrn', - 'PIDController', - 'HHChannel', - 'PulseGen', - 'Pool', - 'RC', - 'BufPool', - 'DiffAmp', - 'IntFire', - 'MgBlock',] - -def allocate_large_vecs(m, n): - """Allocate m vecs with n elements each""" - test = moose.Neutral('/test') - ret = [] - for jj, mclass in zip(range(m), cycle(classes)): - eval_str = 'moose.vec(path="%s/%s_%d", n=%d, dtype="%s")' % (test.path, - mclass, - jj, - n, - mclass) - mobj = eval(eval_str) - print('Created', mobj.path) - ret.append(mobj) - return ret - -def create_finfos(): - fields = defaultdict(list) - for el in moose.wildcardFind('/test/#'): - print(el) - mobj = moose.element(el) - for f in moose.getFieldNames(mobj.className, 'lookup'): - fields[mobj].append(getattr(mobj, f)) - for f in moose.getFieldNames(mobj.className, 'element'): - fields[mobj].append(getattr(mobj, f)) - return fields - -def check_vector_field(m, n): - test = moose.Neutral('/test') - tabs = [] - for ii in range(m): - comp = moose.Compartment('/test/comp_%d' % (ii), n=n) - for jj in range(n): - tab = moose.Table('/test/data_%d_%d' % (ii, jj)) - moose.connect(tab, 'requestOut', comp.vec[jj], 'getVm') - tabs.append(tab) - moose.setClock(0, 1e-3) - moose.setClock(1, 1e-3) - moose.setClock(2, 1e-3) - moose.useClock(0, '/##[ISA=Compartment]', 'init') - moose.useClock(1, '/##[ISA=Compartment]', 'process') - moose.useClock(2, '/##[ISA=Table]', 'process') - moose.reinit() - moose.start(0.01) - return tabs - -import numpy as np - -if __name__ == '__main__': - np_arrays = [] - for ii in range(3): - print('Creating elements') - allocate_large_vecs(100, 100) - print('Created elements. Creating field dict now') - create_finfos() - moose.delete(moose.element('/test')) - tabs = check_vector_field(100, 100) - for t in tabs: - np_arrays.append(np.array(t.vec)) - moose.delete('/test') - print('Finished') - - - -# -# test_gc.py ends here diff --git a/tests/python/mpi/.gdbinit b/tests/python/mpi/.gdbinit deleted file mode 100644 index 23b0f64e..00000000 --- a/tests/python/mpi/.gdbinit +++ /dev/null @@ -1,5 +0,0 @@ -set environment PYTHONPATH ../../python VERBOSITY 2 -set breakpoint pending on -break PostMaster.cpp:193 -#break Shell::doCreate - diff --git a/tests/python/mpi/benchmark.py b/tests/python/mpi/benchmark.py deleted file mode 100644 index 29c01fc0..00000000 --- a/tests/python/mpi/benchmark.py +++ /dev/null @@ -1,152 +0,0 @@ -# -*- coding: utf-8 -*- -# benchmark.py --- -# -# Filename: benchmark.py -# Description: Script for performance benchmarking -# Author: -# Maintainer: -# Created: Thu Jan 23 16:06:25 2014 (+0530) -# Version: -# Last-Updated: -# By: -# Update #: 0 -# URL: -# Keywords: -# Compatibility: -# -# - -# Commentary: -# -# -# -# - -# Change log: -# -# -# -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 3, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, Fifth -# Floor, Boston, MA 02110-1301, USA. -# -# - -# Code: -"""This script tries to run the test case multiple times with -different number of nodes and dump the performance. It shuffles the -runs with increasing number of processes in an attempt to avoid -systematic error based on process sequence. - -""" -from __future__ import print_function - -import getopt -import subprocess -import sys -import os -import socket -import multiprocessing -import subprocess -from datetime import datetime, timedelta -from collections import defaultdict -import random - -def create_hostfile(slotcount=None, filename='hostfile'): - """Create a file with name `filename` and write host info for openmpi - in this.""" - if slotcount is None: - slotcount = multiprocessing.cpu_count() - with open(filename, 'w') as hostfile: - hostfile.write('%s slots=%d\n' % (socket.gethostname(), slotcount)) - - -def run(script, scriptargs=[], hostfile='hostfile', np=2, ni=1, oversubscribe=False): - """Run `script` with arguments in `scriptargs` list. Use `hostfile` - for host and slot info, use `np` moose processes in addition to - Python, do `ni` iterations to get average performance.""" - if not oversubscribe: - np = multiprocessing.cpu_count() - s0 = datetime.now() - avg = defaultdict(timedelta) - procs = range(np) - for jj in range(ni): - random.shuffle(procs) - for ii in procs: - print('Running with', ii, 'processes') - if ii > 0: - args = ['mpirun', '--hostfile', hostfile, '-np', '1', 'python', script] + scriptargs + [':', '-np', str(ii), '../../../moose'] - else: - args = ['mpirun', '--hostfile', hostfile, '-np', '1', 'python', script] + scriptargs - print('Running:', args) - s1 = datetime.now() - ret = subprocess.check_output(args) - print('====================== OUTPUT START ======================') - print(ret) - print('====================== OUTPUT END ======================') - e1 = datetime.now() - d1 = e1 - s1 - avg[ii] += d1 - print('Time to run ', args) - print(' =', d1.days * 86400 + d1.seconds + 1e-6 * d1.microseconds) - e0 = datetime.now() - d0 = e0 - s0 - avg['all'] += d0 - for ii in sorted(procs): - print('Time to run using', ii, 'additional moose processes: ') - print(' =', (avg[ii].days * 86400 + avg[ii].seconds + 1e-6 * avg[ii].microseconds) / ni) - print('Total time for all different process counts averaged over all', ni, 'iterations:', (avg['all'].days * 86400 + avg['all'].seconds + 1e-6 * avg['all'].microseconds) / ni) - -def print_usage(argv0): - print('''Usage: %s [-s slotcount] [-f hostfile] [-n maxprocess] [-i iterations] {script} [script arguments] - - Run {script} using up to {slotcount} slots and display - execution time. If specified, the host information will be - written in `hostfile`. Default is "hostfile".''' % (argv0)) - sys.exit(1) - -if __name__ == '__main__': - if len(sys.argv) < 2: - print_usage(sys.argv[0]) - hostfile = 'hostfile' - scriptargs = [] - slots = None - np = 1 - ni = 1 - options, rest = getopt.getopt(sys.argv[1:], 'hf:s:n:i:', ['hostfile=','slots=', 'help', 'numproc=']) - for opt, arg in options: - if opt in ('-h', '--help'): - print_usage(sys.argv[0]) - elif opt in ('-f', '--hostfile'): - hostfile = arg - elif opt in ('-s', '--slots'): - slots = int(arg) - elif opt in ('-n', '--numproc'): - np = int(arg) - elif opt in ('-i', '--iterations'): - ni = int(arg) - if len(rest) < 1: - print_usage(sys.argv[0]) - else: - script = rest[0] - if len(rest) > 1: - scriptargs = rest[1:] - create_hostfile(slotcount=slots, filename=hostfile) - run(script, scriptargs, hostfile=hostfile, np=np, ni=ni) - - - -# -# benchmark.py ends here diff --git a/tests/python/mpi/launch.sh b/tests/python/mpi/launch.sh deleted file mode 100644 index 0a1b7793..00000000 --- a/tests/python/mpi/launch.sh +++ /dev/null @@ -1,2 +0,0 @@ -mpirun -np 1 xterm -e gdb --args python recurrentIntFire.py : -np 1 xterm -e gdb ../../../moose - diff --git a/tests/python/mpi/recurrentIntFire.py b/tests/python/mpi/recurrentIntFire.py deleted file mode 100644 index 573552b1..00000000 --- a/tests/python/mpi/recurrentIntFire.py +++ /dev/null @@ -1,85 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import print_function - -import random -import time -from numpy import random as nprand - -import moose - -def make_network(): - size = 1024 - timestep = 0.2 - runtime = 100.0 - delayMin = timestep - delayMax = 4 - weightMax = 0.02 - Vmax = 1.0 - thresh = 0.2 - tau = 1 # Range of tau - tau0 = 0.5 # minimum tau - refr = 0.3 - refr0 = 0.2 - connectionProbability = 0.1 - random.seed( 123 ) - nprand.seed( 456 ) - t0 = time.time() - - clock = moose.element( '/clock' ) - network = moose.IntFire( 'network', size, 1 ); - network.vec.bufferTime = [delayMax * 2] * size - moose.le( '/network' ) - network.vec.numSynapses = [1] * size - # Interesting. This fails because we haven't yet allocated - # the synapses. I guess it is fair to avoid instances of objects that - # don't have allocations. - #synapse = moose.element( '/network/synapse' ) - sv = moose.vec( '/network/synapse' ) - print('before connect t = ', time.time() - t0) - mid = moose.connect( network, 'spikeOut', sv, 'addSpike', 'Sparse') - print('after connect t = ', time.time() - t0) - #print mid.destFields - m2 = moose.element( mid ) - m2.setRandomConnectivity( connectionProbability, 5489 ) - print('after setting connectivity, t = ', time.time() - t0) - network.vec.Vm = [(Vmax*random.random()) for r in range(size)] - network.vec.thresh = thresh - network.vec.refractoryPeriod = [( refr0 + refr * random.random()) for r in range( size) ] - network.vec.tau = [(tau0 + tau*random.random()) for r in range(size)] - numSynVec = network.vec.numSynapses - print('Middle of setup, t = ', time.time() - t0) - numTotSyn = sum( numSynVec ) - for item in network.vec: - neuron = moose.element( item ) - neuron.synapse.delay = [ (delayMin + random.random() * delayMax) for r in range( len( neuron.synapse ) ) ] - neuron.synapse.weight = nprand.rand( len( neuron.synapse ) ) * weightMax - print('after setup, t = ', time.time() - t0, ", numTotSyn = ", numTotSyn) - - """ - - netvec = network.vec - for i in range( size ): - synvec = netvec[i].synapse.vec - synvec.weight = [ (random.random() * weightMax) for r in range( synvec.len )] - synvec.delay = [ (delayMin + random.random() * delayMax) for r in range( synvec.len )] - """ - - #moose.useClock( 9, '/postmaster', 'process' ) - moose.useClock( 0, '/network', 'process' ) - moose.setClock( 0, timestep ) - moose.setClock( 9, timestep ) - t1 = time.time() - moose.reinit() - print('reinit time t = ', time.time() - t1) - network.vec.Vm = [(Vmax*random.random()) for r in range(size)] - print('setting Vm , t = ', time.time() - t1) - t1 = time.time() - print('starting') - moose.start(runtime) - print('runtime, t = ', time.time() - t1) - print('Vm100:103', network.vec.Vm[100:103]) - print('Vm900:903', network.vec.Vm[900:903]) - print('weights 100:', network.vec[100].synapse.delay[0:5]) - print('weights 900:', network.vec[900].synapse.delay[0:5]) - -make_network() diff --git a/tests/python/mumbl/mumbl.xml b/tests/python/mumbl/mumbl.xml deleted file mode 100644 index 157adc1a..00000000 --- a/tests/python/mumbl/mumbl.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1.5e14 - 1e-16 - - - - - diff --git a/tests/python/mus/README b/tests/python/mus/README deleted file mode 100644 index 87006643..00000000 --- a/tests/python/mus/README +++ /dev/null @@ -1,7 +0,0 @@ -TO RUN - - python rc19.py type solver - -type: active or passive -solve: hsolve or ee - diff --git a/tests/python/mus/cachannel.py b/tests/python/mus/cachannel.py deleted file mode 100644 index c162a109..00000000 --- a/tests/python/mus/cachannel.py +++ /dev/null @@ -1,157 +0,0 @@ -# -*- coding: utf-8 -*- -# cachannel.py --- -# -# Filename: cachannel.py -# Description: -# Author: Subhasis Ray -# Maintainer: -# Created: Wed Jun 4 14:59:08 2014 (+0530) -# Version: -# Last-Updated: -# By: -# Update #: 0 -# URL: -# Keywords: -# Compatibility: -# -# - -# Commentary: -# -# -# -# - -# Change log: -# -# -# -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 3, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, Fifth -# Floor, Boston, MA 02110-1301, USA. -# -# - -# Code: -import numpy as np - -import moose -from settings import * - -lib = moose.Neutral('/library') - -def make_cat(): - """ - Ported to pymoose. - Subhasis Ray. Wed Jun 4 15:25:21 IST 2014 - - Original comment: - - COMMENT - T-type Ca channel - ca.mod to lead to thalamic ca current inspired by destexhe and huguenrd - Uses fixed eca instead of GHK eqn - changed from (AS Oct0899) - changed for use with Ri18 (B.Kampa 2005) - ENDCOMMENT - """ - # gbar = 8.0 # (S/m2) : 0.12 mho/cm2 - vshift = 0 # (mV) : voltage shift (affects all) - cao = 2.5 # (mM) : external ca concentration - vmin = -120 # (mV) - vmax = 100 # (mV) - v12m = 50 # (mV) - v12h = 78 # (mV) - vwm = 7.4 # (mV) - vwh = 5.0 # (mV) - am = 3 # (mV) - ah = 85 # (mV) - vm1 = 25 # (mV) - vm2 = 100 # (mV) - vh1 = 46 # (mV) - vh2 = 405 # (mV) - wm1 = 20 # (mV) - wm2 = 15 # (mV) - wh1 = 4 # (mV) - wh2 = 50 # (mV) - v = np.linspace(vmin, vmax, 3000) + vshift - minf = 1.0 / ( 1 + np.exp(- (v + v12m) / vwm)) - hinf = 1.0 / ( 1 + np.exp((v + v12h) / vwh)) - mtau = 1e-3 * (am + 1.0 / ( np.exp((v + vm1) / wm1) + np.exp( - (v + vm2) / wm2))) # second - htau = 1e-3 * (ah + 1.0 / ( np.exp((v + vh1) / wh1) + np.exp( - (v + vh2) / wh2))) # second - channel = moose.HHChannel('%s/CaT' % (lib.path)) - channel.Gbar = 0.0 - channel.Xpower = 2 - channel.Ypower = 1 - channel.gateX[0].tableA = minf / mtau - channel.gateX[0].tableB = 1 / mtau - channel.gateX[0].min = vmin * 1e-3 - channel.gateX[0].max = vmax * 1e-3 - channel.gateY[0].tableA = hinf / htau - channel.gateY[0].tableB = 1 / htau - channel.gateY[0].max = vmax * 1e-3 - channel.Ek = 140e-3 - return channel - -def make_cahva(): - """Ported from Neuron mod file. - Subhasis Ray, Thu Jun 5 11:35:46 IST 2014 - - COMMENT - 26 Ago 2002 Modification of original channel to allow variable time step and to correct an initialization error. - Done by Michael Hines(michael.hines@yale.e) and Ruggero Scorcioni(rscorcio@gmu.edu) at EU Advance Course in Computational Neuroscience. Obidos, Portugal - - ca.mod - Uses fixed eca instead of GHK eqn - - HVA Ca current - Based on Reuveni, Friedman, Amitai and Gutnick (1993) J. Neurosci. 13: - 4609-4621. - - Author: Zach Mainen, Salk Institute, 1994, zach@salk.edu - - ENDCOMMENT - """ - gbar = 0.1 # (pS/um2) : 0.12 mho/cm2 - vshift = 0 # (mV) : voltage shift (affects all) - cao = 2.5 # (mM) : external ca concentration - vmin = -120 # (mV) - vmax = 100 # (mV) - vm = np.linspace(vmin, vmax, 3000) + vshift - a = 0.055*(-27 - vm)/(np.exp((-27-vm)/3.8) - 1) - b = 0.94*np.exp((-75-vm)/17) - mtau = 1/tadj/(a+b) - minf = a/(a+b) - # "h" inactivation - a = 0.000457*np.exp((-13-vm)/50) - b = 0.0065/(np.exp((-vm-15)/28) + 1) - htau = 1/tadj/(a+b) - hinf = a/(a+b) - channel = moose.HHChannel('/library/Ca') - channel.Xpower = 2 - channel.gateX[0].tableA = 1e3 * minf / mtau # mtau: ms to s - channel.gateX[0].tableB = 1e3 / mtau - channel.Ypower = 1 - channel.gateY[0].tableA = 1e3 * hinf / htau # htau: ms to s - channel.gateY[0].tableB = 1e3 / htau - channel.gateX[0].min = vmin * 1e-3 - channel.gateX[0].max = vmax * 1e-3 - channel.gateY[0].min = vmin * 1e-3 - channel.gateY[0].max = vmax * 1e-3 - channel.Gbar = 0.0 - channel.Ek = 140e-3 - return channel - - -# -# cachannel.py ends here diff --git a/tests/python/mus/ee b/tests/python/mus/ee deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/python/mus/hchannel.py b/tests/python/mus/hchannel.py deleted file mode 100644 index 41664740..00000000 --- a/tests/python/mus/hchannel.py +++ /dev/null @@ -1,90 +0,0 @@ -# -*- coding: utf-8 -*- -# hchannel.py --- -# -# Filename: hchannel.py -# Description: -# Author: Subhasis Ray -# Maintainer: -# Created: Thu Jun 5 15:20:30 2014 (+0530) -# Version: -# Last-Updated: -# By: -# Update #: 0 -# URL: -# Keywords: -# Compatibility: -# -# - -# Commentary: -# -# -# -# - -# Change log: -# -# -# -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 3, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, Fifth -# Floor, Boston, MA 02110-1301, USA. -# -# - -# Code: - - -import numpy as np -import moose -from settings import * - -library = moose.Neutral('library') - -def make_h(): - """Converted from code for Branco et al 2010 by Subhasis Ray, - Thu Jun 5 15:32:33 IST 2014 - - Original title: - - TITLE I-h channel from Magee 1998 for distal dendrites - - """ - ghdbar = 1.0 # (mho/cm2) does not matter - we are reading from - vhalfl = -81 # (mV) - kl = -8 - vhalft = -75 # (mV) - a0t = 0.011 # (/ms) - zetat = 2.2 # (1) - gmt = .4 # (1) - q10 = 4.5 - qtl = 1 - qt=q10**((temp - 33) / 10) - vmin = -120 - vmax = 100 - v = np.linspace(vmin, vmax, 3000) - a = np.exp(0.0378 * zetat * (v - vhalft)) - linf = 1/(1 + np.exp(-(v-vhalfl)/kl)) - taul = np.exp(0.0378 * zetat * gmt * (v - vhalft)) / (qtl * qt * a0t * (1 + a)) - channel = moose.HHChannel('/library/H') - channel.Xpower = 1 - channel.gateX[0].tableA = 1e3 * linf / taul # taul: ms -> s - channel.gateX[0].tableB = 1e3 / taul # taul: ms -> s - channel.gateX[0].min = 1e-3 * vmin - channel.gateX[0].max = 1e-3 * vmax - return channel - -# -# hchannel.py ends here diff --git a/tests/python/mus/kchannel.py b/tests/python/mus/kchannel.py deleted file mode 100644 index 0bd7ec22..00000000 --- a/tests/python/mus/kchannel.py +++ /dev/null @@ -1,195 +0,0 @@ -# -*- coding: utf-8 -*- -# kchannel.py --- -# -# Filename: kchannel.py -# Description: -# Author: Subhasis Ray -# Maintainer: -# Created: Wed Jun 4 12:30:31 2014 (+0530) -# Version: -# Last-Updated: -# By: -# Update #: 0 -# URL: -# Keywords: -# Compatibility: -# -# - -# Commentary: -# -# -# -# - -# Change log: -# -# -# -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 3, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, Fifth -# Floor, Boston, MA 02110-1301, USA. -# -# - -# Code: - -import numpy as np -import moose -from settings import * - -def rates_kv(v, Ra, Rb, tha, qa): - a = Ra * (v - tha) / (1 - np.exp(-(v - tha)/qa)) - b = -Rb * (v - tha) / (1 - np.exp((v - tha)/qa)) - ntau = 1e-3/tadj/(a+b) - ninf = a/(a+b) - return ntau, ninf - -def make_kv(): - """Translated to pymoose from original model by Zach Mainen. - Subhasis Ray 2014-06-04 - - Original comment: - - COMMENT - 26 Ago 2002 Modification of original channel to allow variable time step and to correct an initialization error. - Done by Michael Hines(michael.hines@yale.e) and Ruggero Scorcioni(rscorcio@gmu.edu) at EU Advance Course in Computational Neuroscience. Obidos, Portugal - - kv.mod - - Potassium channel, Hodgkin-Huxley style kinetics - Kinetic rates based roughly on Sah et al. and Hamill et al. (1991) - - Author: Zach Mainen, Salk Institute, 1995, zach@salk.edu - - ENDCOMMENT - """ - - gbar = 5 * tadj # (pS/um2) : 0.03 mho/cm2 - tha = 25 # (mV) : v 1/2 for inf - qa = 9 # (mV) : inf slope - Ra = 0.02 # (/ms) : max act rate - Rb = 0.002 # (/ms) : max deact rate - vmin = -120 # (mV) - vmax = 100 # (mV) - v = np.linspace(vmin, vmax, 3000) - ntau, ninf = rates_kv(v, Ra, Rb, tha, qa) - channel = moose.HHChannel('/library/Kv') - channel.Xpower = 1 - channel.gateX[0].tableA = 1e3 * ninf / ntau - channel.gateX[0].tableB = 1e3 / ntau - channel.gateX[0].min = vmin * 1e-3 - channel.gateX[0].max = vmax * 1e-3 - channel.Gbar = 0.0 - channel.Ek = -90e-3 - return channel - -def make_km(): - """Ported to pymoose. - Subhasis Ray, Thu Jun 5 15:07:58 IST 2014 - - Original comment: - - COMMENT - 26 Ago 2002 Modification of original channel to allow variable time step and to correct an initialization error. - Done by Michael Hines(michael.hines@yale.e) and Ruggero Scorcioni(rscorcio@gmu.edu) at EU Advance Course in Computational Neuroscience. Obidos, Portugal - - km.mod - - Potassium channel, Hodgkin-Huxley style kinetics - Based on I-M (muscarinic K channel) - Slow, noninactivating - - Author: Zach Mainen, Salk Institute, 1995, zach@salk.edu - - ENDCOMMENT - - """ - gbar = 10 # (pS/um2) = S/m2 : 0.03 mho/cm2 - tha = -30 # (mV) : v 1/2 for inf - qa = 9 # (mV) : inf slope - Ra = 0.001 # (/ms) : max act rate (slow) - Rb = 0.001 # (/ms) : max deact rate (slow) - vmin = -120 # (mV) - vmax = 100 # (mV) - v = np.linspace(vmin, vmax, 3000) - a = Ra * (v - tha) / (1 - np.exp(-(v - tha)/qa)) - b = -Rb * (v - tha) / (1 - np.exp((v - tha)/qa)) - ntau = 1 / tadj /(a + b) - ninf = a/(a+b) - channel = moose.HHChannel('/library/Km') - channel.Gbar = 0.0 # tadj * gbar # not really used - channel.Xpower = 1 - channel.gateX[0].min = vmin * 1e-3 - channel.gateX[0].max = vmax * 1e-3 - channel.gateX[0].tableA = 1e3 * ninf / ntau - channel.gateX[0].tableB = 1e3 / ntau - channel.Ek = -90e-3 - return channel - -def make_kca(): - """Ported from NEURON code. - Subhasis Ray, Thu Jun 5 16:18:14 IST 2014 - - original file comment: - - COMMENT - 26 Ago 2002 Modification of original channel to allow variable time step and to correct an initialization error. - Done by Michael Hines(michael.hines@yale.e) and Ruggero Scorcioni(rscorcio@gmu.edu) at EU Advance Course in Computational Neuroscience. Obidos, Portugal - - kca.mod - - Calcium-dependent potassium channel - Based on - Pennefather (1990) -- sympathetic ganglion cells - taken from - Reuveni et al (1993) -- neocortical cells - - Author: Zach Mainen, Salk Institute, 1995, zach@salk.edu - - ENDCOMMENT - """ - gbar = 10 # (pS/um2) : 0.03 mho/cm2 - caix = 1 # - Ra = 0.01 # (/ms) : max act rate - Rb = 0.02 # (/ms) : max deact rate - vmin = -120 # (mV) - vmax = 100 # (mV) - # In MOOSE we set up lookup tables beforehand - camin = 0.0 - camax = 500.0 - cai = np.linspace(camin, camax) - a = Ra * cai**caix - b = Rb - ntau = 1 / tadj / ( a + b) - ninf = a / (a + b) - channel = moose.HHChannel('/library/KCa') - channel.Zpower = 1 - channel.useConcentration = 1 - channel.gateZ[0].min = camin - channel.gateZ[0].max = camax - channel.gateZ[0].tableA = 1e3 * ninf / ntau - channel.gateZ[0].tableB = 1e3 / ntau - channel.Gbar = 0.0 - channel.Ek = -90e-3 - # addmsg1 = moose.Mstring('%s/addmsg1' % (channel.path)) - # addmsg1.value = '../Ca_conc concOut . concen' - capool = moose.BufPool('%s/CaPool' % (channel.path)) # send a constant [Ca2+] to this channel - capool.n = 5e-5 # n is actually number of molecules (in - # floating point though, but I am using it for - # conc, because only nOut src msg is available - moose.connect(capool, 'nOut', channel, 'concen') - - - -# -# kchannel.py ends here diff --git a/tests/python/mus/nachannel.py b/tests/python/mus/nachannel.py deleted file mode 100644 index e3281a94..00000000 --- a/tests/python/mus/nachannel.py +++ /dev/null @@ -1,116 +0,0 @@ -# -*- coding: utf-8 -*- -"""Converted from the neuron modl file by Zach Mainen 1994. -- Subhasis Ray 2014-06-04 - -Original comment: - -COMMENT - -26 Ago 2002 Modification of original channel to allow variable time -step and to correct an initialization error. - Done by Michael Hines(michael.hines@yale.e) and Ruggero -Scorcioni(rscorcio@gmu.edu) at EU Advance Course in Computational -Neuroscience. Obidos, Portugal -11 Jan 2007 - Glitch in trap where (v/th) was where (v-th)/q is. (thanks Ronald -van Elburg!) - -na.mod - -Sodium channel, Hodgkin-Huxley style kinetics. - -Kinetics were fit to data from Huguenard et al. (1988) and Hamill et -al. (1991) - -qi is not well constrained by the data, since there are no points -between -80 and -55. So this was fixed at 5 while the thi1,thi2,Rg,Rd -were optimized using a simplex least square proc - -voltage dependencies are shifted approximately from the best -fit to give higher threshold - -Author: Zach Mainen, Salk Institute, 1994, zach@salk.edu - -ENDCOMMENT - -""" -import moose -from settings import * -import numpy as np - -def trap0(v, th, a, q): - return np.where(np.abs((v-th)/q) > 1e-6, - a * (v - th) / (1 - exp(-(v - th) / q)), - a * q) - -def make_na(): - library = moose.Neutral('/library') - channel = moose.HHChannel('/library/Na') - channel.Gbar = 0.0 # 1000 * tadj - channel.Xpower = 3 - channel.Ypower = 1 - vshift = -5 # -10 # has been set to -5 in init_biophysics.hoc - vdivs = 3000 - vmin = -120 - vmax = 100 - vm = np.linspace(vmin, vmax, vdivs) + vshift - tha = -35 # (mV) : v 1/2 for act (-42) - qa = 9 # (mV) : act slope - Ra = 0.182 # (/ms) : open (v) - Rb = 0.124 # (/ms) : close (v) - # - thi1 = -50 # (mV) : v 1/2 for inact - thi2 = -75 # (mV) : v 1/2 for inact - qi = 5 # (mV) : inact tau slope - thinf = -65 # (mV) : inact inf slope - qinf = 6.2 # (mV) : inact inf slope - Rg = 0.0091 # (/ms) : inact (v) - Rd = 0.024 # (/ms) : inact recov (v) - - # m gate - activation - a = trap0(vm, tha, Ra, qa) - b = trap0(-vm, -tha, Rb, qa) - mtau = 1e-3 / tadj / (a + b) - minf = a / (a + b) - channel.gateX[0].tableA = minf / mtau # this contains alpha - channel.gateX[0].tableB = 1.0 / mtau # this contains alpha + beta - channel.gateX[0].min = vmin * 1e-3 - channel.gateX[0].max = vmax * 1e-3 - - # h gate - inactivation - a = trap0(vm, thi1, Rd, qi) - b = trap0(-vm, -thi2, Rg, qi) - htau = 1e-3 / tadj / (a + b) - hinf = 1 / (1 + np.exp((vm - thinf) / qinf)) - channel.gateY[0].tableA = hinf / htau - channel.gateY[0].tableB = 1 / htau - channel.gateY[0].min = vmin * 1e-3 - channel.gateY[0].max = vmax * 1e-3 - channel.Ek = 60e-3 - return channel - -from pylab import * - -# Make the prototype channel and plot minf, hinf, mtau, htau -if __name__ == '__main__': - a = make_na() - xa = moose.element(a.gateX).tableA - xb = moose.element(a.gateX).tableB - ya = moose.element(a.gateY).tableA - yb = moose.element(a.gateY).tableB - minf = xa / xb - mtau = 1 / xb - hinf = ya / yb - htau = 1 / yb - subplot(211) - plot(minf, label='minf') - plot(hinf, label='hinf') - legend() - subplot(212) - plot(mtau, label='mtau') - plot(htau, label='htau') - legend() - show() - -# -# nachannel.py ends here diff --git a/tests/python/mus/nmda.py b/tests/python/mus/nmda.py deleted file mode 100644 index a3ddb4a5..00000000 --- a/tests/python/mus/nmda.py +++ /dev/null @@ -1,13 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Created on Sun Jun 1 15:35:13 2014 - -@author: subhasis ray -""" - -import moose - -def make_nmda(path): - nmda = moose.MarkovChannel(path) - return nmda - diff --git a/tests/python/mus/out b/tests/python/mus/out deleted file mode 100644 index aed75d6f..00000000 --- a/tests/python/mus/out +++ /dev/null @@ -1,249 +0,0 @@ -on node 0, numNodes = 1, numCores = 8 -Info: Time to define moose classes:0 -Info: Time to initialize module:0.07 -Created 371 path=/library numData=1 isGlobal=0 baseType=Neutral -Created 372 path=/model numData=1 isGlobal=0 baseType=Neutral -Created 373 path=/data numData=1 isGlobal=0 baseType=Neutral -running simulation using: model with solver hsolve. Model is passive? True -Created 374 path=/model/expt_0_0 numData=1 isGlobal=0 baseType=Neutral -Loading model rc19.p to /library[0]/rc19 -ReadCell: 483 compartments, 0 channels, 0 others -Created 1343 path=/model[0]/expt_0_0[0]/rc19/solve numData=1 isGlobal=0 baseType=HSolve -1111 Creating synapse in /model[0]/expt_0_0[0]/rc19/dend_13_0 -Created 1344 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_0[0]/nmda numData=1 isGlobal=0 baseType=SynChan -Created 1346 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_0[0]/nmda[0]/mgblock numData=1 isGlobal=0 baseType=MgBlock -Created 1347 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_0[0]/ampa numData=1 isGlobal=0 baseType=SynChan -Created 1349 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_0[0]/spike numData=1 isGlobal=0 baseType=SpikeGen -2222 Creating stimuls in /model[0]/expt_0_0[0]/rc19/dend_13_0/stim -Created 1350 path=/model[0]/expt_0_0[0]/rc19/dend_13_0/stim numData=1 isGlobal=0 baseType=PulseGen -1111 Creating synapse in /model[0]/expt_0_0[0]/rc19/dend_13_1 -Created 1351 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_1[0]/nmda numData=1 isGlobal=0 baseType=SynChan -Created 1353 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_1[0]/nmda[0]/mgblock numData=1 isGlobal=0 baseType=MgBlock -Created 1354 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_1[0]/ampa numData=1 isGlobal=0 baseType=SynChan -Created 1356 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_1[0]/spike numData=1 isGlobal=0 baseType=SpikeGen -2222 Creating stimuls in /model[0]/expt_0_0[0]/rc19/dend_13_1/stim -Created 1357 path=/model[0]/expt_0_0[0]/rc19/dend_13_1/stim numData=1 isGlobal=0 baseType=PulseGen -1111 Creating synapse in /model[0]/expt_0_0[0]/rc19/dend_13_2 -Created 1358 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_2[0]/nmda numData=1 isGlobal=0 baseType=SynChan -Created 1360 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_2[0]/nmda[0]/mgblock numData=1 isGlobal=0 baseType=MgBlock -Created 1361 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_2[0]/ampa numData=1 isGlobal=0 baseType=SynChan -Created 1363 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_2[0]/spike numData=1 isGlobal=0 baseType=SpikeGen -2222 Creating stimuls in /model[0]/expt_0_0[0]/rc19/dend_13_2/stim -Created 1364 path=/model[0]/expt_0_0[0]/rc19/dend_13_2/stim numData=1 isGlobal=0 baseType=PulseGen -1111 Creating synapse in /model[0]/expt_0_0[0]/rc19/dend_13_3 -Created 1365 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_3[0]/nmda numData=1 isGlobal=0 baseType=SynChan -Created 1367 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_3[0]/nmda[0]/mgblock numData=1 isGlobal=0 baseType=MgBlock -Created 1368 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_3[0]/ampa numData=1 isGlobal=0 baseType=SynChan -Created 1370 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_3[0]/spike numData=1 isGlobal=0 baseType=SpikeGen -2222 Creating stimuls in /model[0]/expt_0_0[0]/rc19/dend_13_3/stim -Created 1371 path=/model[0]/expt_0_0[0]/rc19/dend_13_3/stim numData=1 isGlobal=0 baseType=PulseGen -1111 Creating synapse in /model[0]/expt_0_0[0]/rc19/dend_13_4 -Created 1372 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_4[0]/nmda numData=1 isGlobal=0 baseType=SynChan -Created 1374 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_4[0]/nmda[0]/mgblock numData=1 isGlobal=0 baseType=MgBlock -Created 1375 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_4[0]/ampa numData=1 isGlobal=0 baseType=SynChan -Created 1377 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_4[0]/spike numData=1 isGlobal=0 baseType=SpikeGen -2222 Creating stimuls in /model[0]/expt_0_0[0]/rc19/dend_13_4/stim -Created 1378 path=/model[0]/expt_0_0[0]/rc19/dend_13_4/stim numData=1 isGlobal=0 baseType=PulseGen -1111 Creating synapse in /model[0]/expt_0_0[0]/rc19/dend_13_5 -Created 1379 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_5[0]/nmda numData=1 isGlobal=0 baseType=SynChan -Created 1381 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_5[0]/nmda[0]/mgblock numData=1 isGlobal=0 baseType=MgBlock -Created 1382 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_5[0]/ampa numData=1 isGlobal=0 baseType=SynChan -Created 1384 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_5[0]/spike numData=1 isGlobal=0 baseType=SpikeGen -2222 Creating stimuls in /model[0]/expt_0_0[0]/rc19/dend_13_5/stim -Created 1385 path=/model[0]/expt_0_0[0]/rc19/dend_13_5/stim numData=1 isGlobal=0 baseType=PulseGen -1111 Creating synapse in /model[0]/expt_0_0[0]/rc19/dend_13_6 -Created 1386 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_6[0]/nmda numData=1 isGlobal=0 baseType=SynChan -Created 1388 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_6[0]/nmda[0]/mgblock numData=1 isGlobal=0 baseType=MgBlock -Created 1389 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_6[0]/ampa numData=1 isGlobal=0 baseType=SynChan -Created 1391 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_6[0]/spike numData=1 isGlobal=0 baseType=SpikeGen -2222 Creating stimuls in /model[0]/expt_0_0[0]/rc19/dend_13_6/stim -Created 1392 path=/model[0]/expt_0_0[0]/rc19/dend_13_6/stim numData=1 isGlobal=0 baseType=PulseGen -1111 Creating synapse in /model[0]/expt_0_0[0]/rc19/dend_13_7 -Created 1393 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_7[0]/nmda numData=1 isGlobal=0 baseType=SynChan -Created 1395 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_7[0]/nmda[0]/mgblock numData=1 isGlobal=0 baseType=MgBlock -Created 1396 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_7[0]/ampa numData=1 isGlobal=0 baseType=SynChan -Created 1398 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_7[0]/spike numData=1 isGlobal=0 baseType=SpikeGen -2222 Creating stimuls in /model[0]/expt_0_0[0]/rc19/dend_13_7/stim -Created 1399 path=/model[0]/expt_0_0[0]/rc19/dend_13_7/stim numData=1 isGlobal=0 baseType=PulseGen -1111 Creating synapse in /model[0]/expt_0_0[0]/rc19/dend_13_8 -Created 1400 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_8[0]/nmda numData=1 isGlobal=0 baseType=SynChan -Created 1402 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_8[0]/nmda[0]/mgblock numData=1 isGlobal=0 baseType=MgBlock -Created 1403 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_8[0]/ampa numData=1 isGlobal=0 baseType=SynChan -Created 1405 path=/model[0]/expt_0_0[0]/rc19[0]/dend_13_8[0]/spike numData=1 isGlobal=0 baseType=SpikeGen -2222 Creating stimuls in /model[0]/expt_0_0[0]/rc19/dend_13_8/stim -Created 1406 path=/model[0]/expt_0_0[0]/rc19/dend_13_8/stim numData=1 isGlobal=0 baseType=PulseGen -Created 1407 path=/data/expt_0_0 numData=1 isGlobal=0 baseType=Neutral -Created 1408 path=/data[0]/expt_0_0[0]/Vm_soma numData=1 isGlobal=0 baseType=Table -5555 Soma path /model[0]/expt_0_0[0]/rc19/soma_1 -Created 1409 path=/data[0]/expt_0_0[0]/G_AMPA numData=1 isGlobal=0 baseType=Neutral -Created 1410 path=/data[0]/expt_0_0[0]/G_NMDA numData=1 isGlobal=0 baseType=Neutral -Created 1411 path=/data[0]/expt_0_0[0]/G_NMDA[0]/Gk_nmda_dend_13_0 numData=1 isGlobal=0 baseType=Table -Created 1412 path=/data[0]/expt_0_0[0]/G_AMPA[0]/Gk_ampa_dend_13_0 numData=1 isGlobal=0 baseType=Table -Created 1413 path=/data[0]/expt_0_0[0]/G_NMDA[0]/Gk_nmda_dend_13_1 numData=1 isGlobal=0 baseType=Table -Created 1414 path=/data[0]/expt_0_0[0]/G_AMPA[0]/Gk_ampa_dend_13_1 numData=1 isGlobal=0 baseType=Table -Created 1415 path=/data[0]/expt_0_0[0]/G_NMDA[0]/Gk_nmda_dend_13_2 numData=1 isGlobal=0 baseType=Table -Created 1416 path=/data[0]/expt_0_0[0]/G_AMPA[0]/Gk_ampa_dend_13_2 numData=1 isGlobal=0 baseType=Table -Created 1417 path=/data[0]/expt_0_0[0]/G_NMDA[0]/Gk_nmda_dend_13_3 numData=1 isGlobal=0 baseType=Table -Created 1418 path=/data[0]/expt_0_0[0]/G_AMPA[0]/Gk_ampa_dend_13_3 numData=1 isGlobal=0 baseType=Table -Created 1419 path=/data[0]/expt_0_0[0]/G_NMDA[0]/Gk_nmda_dend_13_4 numData=1 isGlobal=0 baseType=Table -Created 1420 path=/data[0]/expt_0_0[0]/G_AMPA[0]/Gk_ampa_dend_13_4 numData=1 isGlobal=0 baseType=Table -Created 1421 path=/data[0]/expt_0_0[0]/G_NMDA[0]/Gk_nmda_dend_13_5 numData=1 isGlobal=0 baseType=Table -Created 1422 path=/data[0]/expt_0_0[0]/G_AMPA[0]/Gk_ampa_dend_13_5 numData=1 isGlobal=0 baseType=Table -Created 1423 path=/data[0]/expt_0_0[0]/G_NMDA[0]/Gk_nmda_dend_13_6 numData=1 isGlobal=0 baseType=Table -Created 1424 path=/data[0]/expt_0_0[0]/G_AMPA[0]/Gk_ampa_dend_13_6 numData=1 isGlobal=0 baseType=Table -Created 1425 path=/data[0]/expt_0_0[0]/G_NMDA[0]/Gk_nmda_dend_13_7 numData=1 isGlobal=0 baseType=Table -Created 1426 path=/data[0]/expt_0_0[0]/G_AMPA[0]/Gk_ampa_dend_13_7 numData=1 isGlobal=0 baseType=Table -Created 1427 path=/data[0]/expt_0_0[0]/G_NMDA[0]/Gk_nmda_dend_13_8 numData=1 isGlobal=0 baseType=Table -Created 1428 path=/data[0]/expt_0_0[0]/G_AMPA[0]/Gk_ampa_dend_13_8 numData=1 isGlobal=0 baseType=Table -Experiment expt_0_0 has been setup. -Stimulus order: ['dend_13_8'] -Stimulus onset: 0.05 -Inter stimulus interval: 0.001 -assignDefaultTicks -Warning: no Elements found on path /model/##[ISA=IzhikevichNrn] -Warning: no Elements found on path /model/##[ISA=GapJunction] -Warning: no Elements found on path /model/##[ISA=LeakyIaF] -Warning: no Elements found on path /model/##[ISA=IntFire] -Warning: no Elements found on path /model/##[ISA=StimulusTable] -Warning: no Elements found on path /model/##[ISA=TimeTable] -Warning: no Elements found on path /model/##[ISA=HHChannel2D] -Warning: no Elements found on path /model/##[ISA=CaConc] -Warning: no Elements found on path /model/##[ISA=Func] -Warning: no Elements found on path /model/##[ISA=DiffAmp] -Warning: no Elements found on path /model/##[ISA=VClamp] -Warning: no Elements found on path /model/##[ISA=PIDController] -Warning: no Elements found on path /model/##[ISA=RC] -$$$$$$$$$$$ 0.2 -Interval= 0.001 Stim order= [8] -dinfo: {'nmda_gk': [, , , , , , , , ], 'soma_vm': , 'data': , 'ampa_gk': [, , , , , , , , ]} - -[-0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 -0.075 - -0.075 -0.075 -0.075 -0.075 -0.075 -0.07499829 - -0.07497706 -0.07492513 -0.07484769 -0.07475377 -0.07465117 -0.07454544 - -0.07444007 -0.07433715 -0.07423779 -0.07414247 -0.07405131 -0.0739642 - -0.07388091 -0.07380113 -0.07372452 -0.07365075 -0.07357949 -0.07351043 - -0.0734433 -0.07337787 -0.0733139 -0.07325122 -0.07318968 -0.07312914 - -0.0730695 -0.07301066 -0.07295256 -0.07289515 -0.07283838 -0.07278223 - -0.07272668 -0.07267171 -0.07261732 -0.07256351 -0.07251029 -0.07245764 - -0.0724056 -0.07235416 -0.07230333 -0.07225312 -0.07220356 -0.07215464 - -0.07210638 -0.07205879 -0.07201188 -0.07196566 -0.07192014 -0.07187532 - -0.07183121 -0.07178782 -0.07174516 -0.07170322 -0.07166201 -0.07162154 - -0.07158181 -0.07154281 -0.07150456 -0.07146704 -0.07143026 -0.07139423 - -0.07135892 -0.07132436 -0.07129052 -0.07125742 -0.07122504 -0.07119338 - -0.07116244 -0.07113222 -0.0711027 -0.07107388 -0.07104577 -0.07101835 - -0.07099161 -0.07096555 -0.07094017 -0.07091546 -0.07089141 -0.07086801 - -0.07084527 -0.07082316 -0.07080169 -0.07078085 -0.07076063 -0.07074102 - -0.07072202 -0.07070362 -0.07068581 -0.07066858 -0.07065193 -0.07063586 - -0.07062034 -0.07060539 -0.07059098 -0.07057711 -0.07056378 -0.07055097 - -0.07053869 -0.07052692 -0.07051565 -0.07050489 -0.07049461 -0.07048483 - -0.07047552 -0.07046668 -0.07045831 -0.0704504 -0.07044294 -0.07043593 - -0.07042935 -0.07042321 -0.0704175 -0.0704122 -0.07040732 -0.07040285 - -0.07039878 -0.0703951 -0.07039182 -0.07038892 -0.0703864 -0.07038425 - -0.07038247 -0.07038105 -0.07037999 -0.07037928 -0.07037891 -0.07037889 - -0.0703792 -0.07037983 -0.0703808 -0.07038208 -0.07038368 -0.07038558 - -0.0703878 -0.07039031 -0.07039312 -0.07039621 -0.0703996 -0.07040326 - -0.07040721 -0.07041142 -0.07041591 -0.07042065 -0.07042566 -0.07043093 - -0.07043644 -0.0704422 -0.07044821 -0.07045445 -0.07046093 -0.07046765 - -0.07047459 -0.07048175 -0.07048913 -0.07049674 -0.07050455 -0.07051257 - -0.0705208 -0.07052923 -0.07053786 -0.07054669 -0.07055571 -0.07056491 - -0.0705743 -0.07058388 -0.07059363 -0.07060356 -0.07061366 -0.07062393 - -0.07063437 -0.07064497 -0.07065574 -0.07066666 -0.07067773 -0.07068896 - -0.07070033 -0.07071186 -0.07072352 -0.07073533 -0.07074727 -0.07075936 - -0.07077157 -0.07078391 -0.07079638 -0.07080898 -0.0708217 -0.07083454 - -0.0708475 -0.07086057 -0.07087375 -0.07088705 -0.07090045 -0.07091396 - -0.07092757 -0.07094129 -0.0709551 -0.07096901 -0.07098301 -0.07099711 - -0.07101129 -0.07102557 -0.07103993 -0.07105437 -0.0710689 -0.0710835 - -0.07109819 -0.07111294 -0.07112778 -0.07114268 -0.07115765 -0.07117269 - -0.0711878 -0.07120297 -0.07121821 -0.0712335 -0.07124885 -0.07126426 - -0.07127973 -0.07129524 -0.07131081 -0.07132643 -0.0713421 -0.07135781 - -0.07137357 -0.07138937 -0.07140521 -0.07142109 -0.07143701 -0.07145296 - -0.07146895 -0.07148498 -0.07150103 -0.07151712 -0.07153323 -0.07154937 - -0.07156554 -0.07158173 -0.07159794 -0.07161418 -0.07163043 -0.07164671 - -0.071663 -0.0716793 -0.07169563 -0.07171196 -0.0717283 -0.07174466 - -0.07176102 -0.0717774 -0.07179378 -0.07181016 -0.07182655 -0.07184294 - -0.07185933 -0.07187572 -0.07189211 -0.0719085 -0.07192489 -0.07194127 - -0.07195765 -0.07197402 -0.07199038 -0.07200673 -0.07202307 -0.0720394 - -0.07205572 -0.07207203 -0.07208832 -0.07210459 -0.07212085 -0.0721371 - -0.07215332 -0.07216952 -0.07218571 -0.07220187 -0.07221801 -0.07223413 - -0.07225022 -0.07226629 -0.07228234 -0.07229835 -0.07231434 -0.0723303 - -0.07234623 -0.07236214 -0.07237801 -0.07239384 -0.07240965 -0.07242542 - -0.07244116 -0.07245687 -0.07247253 -0.07248817 -0.07250376 -0.07251932 - -0.07253484 -0.07255032 -0.07256576 -0.07258116 -0.07259651 -0.07261183 - -0.0726271 -0.07264233 -0.07265752 -0.07267266 -0.07268776 -0.07270282 - -0.07271782 -0.07273278 -0.0727477 -0.07276256 -0.07277738 -0.07279215 - -0.07280686 -0.07282153 -0.07283615 -0.07285072 -0.07286524 -0.07287971 - -0.07289412 -0.07290848 -0.07292279 -0.07293704 -0.07295124 -0.07296539 - -0.07297948 -0.07299352 -0.0730075 -0.07302143 -0.0730353 -0.07304912 - -0.07306287 -0.07307658 -0.07309022 -0.07310381 -0.07311733 -0.0731308 - -0.07314422 -0.07315757 -0.07317086 -0.0731841 -0.07319727 -0.07321039 - -0.07322344 -0.07323644 -0.07324937 -0.07326225 -0.07327506 -0.07328781 - -0.07330051 -0.07331314 -0.07332571 -0.07333821 -0.07335066 -0.07336304 - -0.07337536 -0.07338762 -0.07339982 -0.07341196 -0.07342403 -0.07343604 - -0.07344799 -0.07345987 -0.07347169 -0.07348345 -0.07349515 -0.07350678 - -0.07351835 -0.07352986 -0.0735413 -0.07355269 -0.073564 -0.07357526 - -0.07358645 -0.07359758 -0.07360864 -0.07361965 -0.07363059 -0.07364146 - -0.07365227 -0.07366302 -0.07367371 -0.07368433 -0.0736949 -0.07370539 - -0.07371583 -0.0737262 -0.07373651 -0.07374676 -0.07375694 -0.07376707 - -0.07377713 -0.07378712 -0.07379706 -0.07380693 -0.07381674 -0.07382649 - -0.07383618 -0.07384581 -0.07385537 -0.07386488 -0.07387432 -0.0738837 - -0.07389302 -0.07390228 -0.07391148 -0.07392062 -0.07392969 -0.07393871 - -0.07394767 -0.07395657 -0.07396541 -0.07397418 -0.0739829 -0.07399156 - -0.07400016 -0.07400871 -0.07401719 -0.07402562 -0.07403398 -0.07404229 - -0.07405054 -0.07405874 -0.07406687 -0.07407495 -0.07408297 -0.07409094 - -0.07409885 -0.0741067 -0.07411449 -0.07412223 -0.07412992 -0.07413754 - -0.07414512 -0.07415264 -0.0741601 -0.07416751 -0.07417486 -0.07418216 - -0.07418941 -0.0741966 -0.07420374 -0.07421082 -0.07421786 -0.07422484 - -0.07423177 -0.07423864 -0.07424546 -0.07425224 -0.07425896 -0.07426563 - -0.07427224 -0.07427881 -0.07428533 -0.07429179 -0.07429821 -0.07430458 - -0.07431089 -0.07431716 -0.07432338 -0.07432955 -0.07433568 -0.07434175 - -0.07434778 -0.07435375 -0.07435969 -0.07436557 -0.07437141 -0.0743772 - -0.07438294 -0.07438864 -0.07439429 -0.0743999 -0.07440546 -0.07441098 - -0.07441645 -0.07442188 -0.07442726 -0.0744326 -0.07443789 -0.07444314 - -0.07444835 -0.07445352 -0.07445864 -0.07446372 -0.07446876 -0.07447376 - -0.07447871 -0.07448363 -0.0744885 -0.07449333 -0.07449812 -0.07450288 - -0.07450759 -0.07451226 -0.07451689 -0.07452148 -0.07452604 -0.07453055 - -0.07453503 -0.07453947 -0.07454387 -0.07454823 -0.07455255 -0.07455684 - -0.07456109 -0.07456531 -0.07456948 -0.07457363 -0.07457773 -0.0745818 - -0.07458584 -0.07458983 -0.0745938 -0.07459773 -0.07460162 -0.07460549 - -0.07460931 -0.07461311 -0.07461687 -0.07462059 -0.07462429 -0.07462795 - -0.07463158 -0.07463517 -0.07463874 -0.07464227 -0.07464577 -0.07464924 - -0.07465268 -0.07465609 -0.07465946 -0.07466281 -0.07466613 -0.07466941 - -0.07467267 -0.0746759 -0.07467909 -0.07468226 -0.0746854 -0.07468852 - -0.0746916 -0.07469465 -0.07469768 -0.07470068 -0.07470365 -0.0747066 - -0.07470951 -0.07471241 -0.07471527 -0.07471811 -0.07472092 -0.0747237 - -0.07472646 -0.0747292 -0.07473191 -0.07473459 -0.07473725 -0.07473988 - -0.07474249 -0.07474508 -0.07474764 -0.07475018 -0.07475269 -0.07475518 - -0.07475764 -0.07476009 -0.07476251 -0.0747649 -0.07476728 -0.07476963 - -0.07477196 -0.07477427 -0.07477655 -0.07477882 -0.07478106 -0.07478328 - -0.07478548 -0.07478766 -0.07478982 -0.07479196 -0.07479408 -0.07479617 - -0.07479825 -0.07480031 -0.07480234 -0.07480436 -0.07480636 -0.07480834 - -0.0748103 -0.07481224 -0.07481416 -0.07481607 -0.07481795 -0.07481982 - -0.07482167 -0.0748235 -0.07482531 -0.07482711 -0.07482889] -num points= 801 t0= 0.0 t_last= 0.2 v0= -0.075 v_last= -0.0748288867931 diff --git a/tests/python/mus/passive b/tests/python/mus/passive deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/python/mus/rc19.p b/tests/python/mus/rc19.p deleted file mode 100644 index fad33e38..00000000 --- a/tests/python/mus/rc19.p +++ /dev/null @@ -1,499 +0,0 @@ -/* - This code was generated from a NEURON model using stub hoc code - by Subhasis Ray, NCBS, Bangalore. - It corresponds to L2/3Pyramidal cell in the model by Branco et al 2010 - Reference: http://senselab.med.yale.edu/ModelDb/ShowModel.asp?model=45539 - - Reference: http://senselab.med.yale.edu/modeldb/ShowModel.asp?model=140828 - ***********************************************************************/ -*cartesian -*relative -*asymmetric -*set_global EREST_ACT -0.075 -*set_global ELEAK -0.075 -*set_compt_param RM 1 -*set_compt_param RA 1.5 -*set_compt_param CM 0.01 -soma_0 none 4.83607 0 0 15.659 Ca 5000 CaT 3 KCa 25000 Kv 2e+06 KM 22000 Na 1.5e+07 -soma_1 . 4.83607 0 0 15.659 Ca 5000 CaT 3 KCa 25000 Kv 2e+06 KM 22000 Na 1.5e+07 -soma_2 . 4.83607 0 0 15.659 Ca 5000 CaT 3 KCa 25000 Kv 2e+06 KM 22000 Na 1.5e+07 -axon_0 soma_1 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_1 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_2 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_3 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_4 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_5 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_6 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_7 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_8 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_9 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_10 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_11 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_12 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_13 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_14 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_15 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_16 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_17 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_18 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_19 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_20 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_21 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_22 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_23 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_24 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_25 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_26 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_27 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_28 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_29 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_30 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_31 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_32 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_33 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_34 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_35 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_36 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_37 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_38 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_39 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_40 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_41 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_42 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_43 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_44 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_45 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_46 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_47 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_48 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_49 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_50 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_51 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_52 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_53 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_54 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_55 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -axon_56 . 10.725 0 0 0.54 Kv 4e+06 Na 3e+08 -dend_0_0 soma_1 5.92106 0 0 1.62 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_0_1 . 5.92106 0 0 1.62 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_0_2 . 5.92106 0 0 1.62 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_1_0 dend_0_2 3.33842 0 0 1.62 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_1_1 . 3.33842 0 0 1.62 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_1_2 . 3.33842 0 0 1.62 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_2_0 dend_1_2 10.0489 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_2_1 . 10.0489 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_2_2 . 10.0489 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_2_3 . 10.0489 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_2_4 . 10.0489 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_2_5 . 10.0489 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_2_6 . 10.0489 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_2_7 . 10.0489 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_2_8 . 10.0489 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_3_0 dend_1_2 4.03361 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_3_1 . 4.03361 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_3_2 . 4.03361 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_4_0 dend_3_2 8.53083 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_4_1 . 8.53083 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_4_2 . 8.53083 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_5_0 dend_4_2 6.67041 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_5_1 . 6.67041 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_5_2 . 6.67041 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_5_3 . 6.67041 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_5_4 . 6.67041 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_5_5 . 6.67041 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_5_6 . 6.67041 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_5_7 . 6.67041 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_5_8 . 6.67041 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_6_0 dend_4_2 7.26592 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_6_1 . 7.26592 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_6_2 . 7.26592 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_6_3 . 7.26592 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_6_4 . 7.26592 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_6_5 . 7.26592 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_6_6 . 7.26592 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_6_7 . 7.26592 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_6_8 . 7.26592 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_7_0 dend_3_2 5.0579 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_7_1 . 5.0579 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_7_2 . 5.0579 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_8_0 dend_7_2 4.52536 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_8_1 . 4.52536 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_8_2 . 4.52536 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_9_0 dend_7_2 10.1746 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_9_1 . 10.1746 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_9_2 . 10.1746 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_10_0 dend_0_2 1.16362 0 0 1.62 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_10_1 . 1.16362 0 0 1.62 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_10_2 . 1.16362 0 0 1.62 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_11_0 dend_10_2 7.23706 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_11_1 . 7.23706 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_11_2 . 7.23706 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_11_3 . 7.23706 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_11_4 . 7.23706 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_11_5 . 7.23706 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_11_6 . 7.23706 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_11_7 . 7.23706 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_11_8 . 7.23706 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_12_0 dend_10_2 3.75691 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_12_1 . 3.75691 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_12_2 . 3.75691 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_13_0 dend_12_2 11.0025 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_13_1 . 11.0025 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_13_2 . 11.0025 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_13_3 . 11.0025 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_13_4 . 11.0025 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_13_5 . 11.0025 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_13_6 . 11.0025 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_13_7 . 11.0025 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_13_8 . 11.0025 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_14_0 dend_12_2 8.20349 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_14_1 . 8.20349 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_14_2 . 8.20349 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_14_3 . 8.20349 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_14_4 . 8.20349 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_14_5 . 8.20349 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_14_6 . 8.20349 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_14_7 . 8.20349 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_14_8 . 8.20349 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_15_0 soma_1 4.76231 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_15_1 . 4.76231 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_15_2 . 4.76231 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_16_0 dend_15_2 9.12347 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_16_1 . 9.12347 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_16_2 . 9.12347 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_16_3 . 9.12347 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_16_4 . 9.12347 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_16_5 . 9.12347 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_16_6 . 9.12347 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_16_7 . 9.12347 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_16_8 . 9.12347 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_17_0 dend_15_2 1.93284 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_17_1 . 1.93284 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_17_2 . 1.93284 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_18_0 dend_17_2 11.2689 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_18_1 . 11.2689 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_18_2 . 11.2689 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_18_3 . 11.2689 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_18_4 . 11.2689 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_18_5 . 11.2689 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_18_6 . 11.2689 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_18_7 . 11.2689 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_18_8 . 11.2689 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_19_0 dend_17_2 10.3675 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_19_1 . 10.3675 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_19_2 . 10.3675 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_19_3 . 10.3675 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_19_4 . 10.3675 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_19_5 . 10.3675 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_19_6 . 10.3675 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_19_7 . 10.3675 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_19_8 . 10.3675 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_20_0 dend_19_8 8.13627 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_20_1 . 8.13627 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_20_2 . 8.13627 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_21_0 dend_19_8 8.76655 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_21_1 . 8.76655 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_21_2 . 8.76655 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_22_0 soma_1 10.6877 0 0 0.997174 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_22_1 . 10.6877 0 0 0.997174 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_22_2 . 10.6877 0 0 0.997174 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_22_3 . 10.6877 0 0 0.997174 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_22_4 . 10.6877 0 0 0.997174 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_22_5 . 10.6877 0 0 0.997174 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_22_6 . 10.6877 0 0 0.997174 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_22_7 . 10.6877 0 0 0.997174 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_22_8 . 10.6877 0 0 0.997174 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_23_0 soma_1 13.537 0 0 1.09687 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_23_1 . 13.537 0 0 1.09687 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_23_2 . 13.537 0 0 1.09687 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_24_0 soma_1 2.55227 0 0 1.0958 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_24_1 . 2.55227 0 0 1.0958 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_24_2 . 2.55227 0 0 1.0958 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_25_0 dend_24_2 6.02663 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_25_1 . 6.02663 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_25_2 . 6.02663 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_26_0 dend_25_2 5.85801 0 0 1.62 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_26_1 . 5.85801 0 0 1.62 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_26_2 . 5.85801 0 0 1.62 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_27_0 dend_25_2 9.95705 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_27_1 . 9.95705 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_27_2 . 9.95705 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_27_3 . 9.95705 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_27_4 . 9.95705 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_27_5 . 9.95705 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_27_6 . 9.95705 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_27_7 . 9.95705 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_27_8 . 9.95705 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_28_0 dend_24_2 7.22498 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_28_1 . 7.22498 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_28_2 . 7.22498 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_29_0 dend_28_2 9.33538 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_29_1 . 9.33538 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_29_2 . 9.33538 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_29_3 . 9.33538 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_29_4 . 9.33538 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_29_5 . 9.33538 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_29_6 . 9.33538 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_29_7 . 9.33538 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_29_8 . 9.33538 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_30_0 dend_28_2 11.064 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_30_1 . 11.064 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_30_2 . 11.064 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_31_0 soma_2 19.6064 0 0 1.62 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_31_1 . 19.6064 0 0 1.62 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_31_2 . 19.6064 0 0 1.62 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_32_0 dend_31_2 8.18489 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_32_1 . 8.18489 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_32_2 . 8.18489 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_32_3 . 8.18489 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_32_4 . 8.18489 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_32_5 . 8.18489 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_32_6 . 8.18489 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_32_7 . 8.18489 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_32_8 . 8.18489 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_33_0 dend_32_8 4.61539 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_33_1 . 4.61539 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_33_2 . 4.61539 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_34_0 dend_32_8 6.33102 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_34_1 . 6.33102 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_34_2 . 6.33102 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_34_3 . 6.33102 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_34_4 . 6.33102 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_34_5 . 6.33102 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_34_6 . 6.33102 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_34_7 . 6.33102 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_34_8 . 6.33102 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_35_0 dend_31_2 2.54415 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_35_1 . 2.54415 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_35_2 . 2.54415 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_36_0 dend_35_2 8.04864 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_36_1 . 8.04864 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_36_2 . 8.04864 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_36_3 . 8.04864 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_36_4 . 8.04864 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_36_5 . 8.04864 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_36_6 . 8.04864 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_36_7 . 8.04864 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_36_8 . 8.04864 0 0 1.08 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_37_0 dend_35_2 11.6565 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_37_1 . 11.6565 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_37_2 . 11.6565 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_37_3 . 11.6565 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_37_4 . 11.6565 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_37_5 . 11.6565 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_37_6 . 11.6565 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_37_7 . 11.6565 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -dend_37_8 . 11.6565 0 0 0.54 Ca 5000 CaT 6 KCa 25000 Kv 300000 KM 500 Na 400000 -apic_0_0 soma_2 8.74694 0 0 2.16 -apic_0_1 . 8.74694 0 0 2.16 -apic_0_2 . 8.74694 0 0 2.16 -apic_1_0 apic_0_2 5.88054 0 0 1.62 -apic_1_1 . 5.88054 0 0 1.62 -apic_1_2 . 5.88054 0 0 1.62 -apic_2_0 apic_1_2 7.38115 0 0 1.06666 -apic_2_1 . 7.38115 0 0 1.06666 -apic_2_2 . 7.38115 0 0 1.06666 -apic_3_0 apic_2_2 17.2355 0 0 1.08 -apic_3_1 . 17.2355 0 0 1.08 -apic_3_2 . 17.2355 0 0 1.08 -apic_4_0 apic_2_2 7.24974 0 0 0.54 -apic_4_1 . 7.24974 0 0 0.54 -apic_4_2 . 7.24974 0 0 0.54 -apic_4_3 . 7.24974 0 0 0.54 -apic_4_4 . 7.24974 0 0 0.54 -apic_4_5 . 7.24974 0 0 0.54 -apic_4_6 . 7.24974 0 0 0.54 -apic_4_7 . 7.24974 0 0 0.54 -apic_4_8 . 7.24974 0 0 0.54 -apic_5_0 apic_1_2 2.62586 0 0 1.08 -apic_5_1 . 2.62586 0 0 1.08 -apic_5_2 . 2.62586 0 0 1.08 -apic_6_0 apic_5_2 9.99651 0 0 1.62 -apic_6_1 . 9.99651 0 0 1.62 -apic_6_2 . 9.99651 0 0 1.62 -apic_7_0 apic_6_2 4.41555 0 0 1.08 -apic_7_1 . 4.41555 0 0 1.08 -apic_7_2 . 4.41555 0 0 1.08 -apic_8_0 apic_7_2 13.2757 0 0 1.08 -apic_8_1 . 13.2757 0 0 1.08 -apic_8_2 . 13.2757 0 0 1.08 -apic_9_0 apic_8_2 11.2281 0 0 1.08 -apic_9_1 . 11.2281 0 0 1.08 -apic_9_2 . 11.2281 0 0 1.08 -apic_10_0 apic_8_2 8.67281 0 0 0.553321 -apic_10_1 . 8.67281 0 0 0.553321 -apic_10_2 . 8.67281 0 0 0.553321 -apic_11_0 apic_7_2 10.9587 0 0 0.54 -apic_11_1 . 10.9587 0 0 0.54 -apic_11_2 . 10.9587 0 0 0.54 -apic_11_3 . 10.9587 0 0 0.54 -apic_11_4 . 10.9587 0 0 0.54 -apic_11_5 . 10.9587 0 0 0.54 -apic_11_6 . 10.9587 0 0 0.54 -apic_11_7 . 10.9587 0 0 0.54 -apic_11_8 . 10.9587 0 0 0.54 -apic_12_0 apic_6_2 1.73971 0 0 2.16 -apic_12_1 . 1.73971 0 0 2.16 -apic_12_2 . 1.73971 0 0 2.16 -apic_13_0 apic_12_2 2.85569 0 0 1.62 -apic_13_1 . 2.85569 0 0 1.62 -apic_13_2 . 2.85569 0 0 1.62 -apic_14_0 apic_13_2 6.17406 0 0 0.54 -apic_14_1 . 6.17406 0 0 0.54 -apic_14_2 . 6.17406 0 0 0.54 -apic_14_3 . 6.17406 0 0 0.54 -apic_14_4 . 6.17406 0 0 0.54 -apic_14_5 . 6.17406 0 0 0.54 -apic_14_6 . 6.17406 0 0 0.54 -apic_14_7 . 6.17406 0 0 0.54 -apic_14_8 . 6.17406 0 0 0.54 -apic_15_0 apic_13_2 6.79328 0 0 1.08 -apic_15_1 . 6.79328 0 0 1.08 -apic_15_2 . 6.79328 0 0 1.08 -apic_15_3 . 6.79328 0 0 1.08 -apic_15_4 . 6.79328 0 0 1.08 -apic_15_5 . 6.79328 0 0 1.08 -apic_15_6 . 6.79328 0 0 1.08 -apic_15_7 . 6.79328 0 0 1.08 -apic_15_8 . 6.79328 0 0 1.08 -apic_16_0 apic_12_2 10.8493 0 0 1.57121 -apic_16_1 . 10.8493 0 0 1.57121 -apic_16_2 . 10.8493 0 0 1.57121 -apic_17_0 apic_16_2 8.90269 0 0 1.08 -apic_17_1 . 8.90269 0 0 1.08 -apic_17_2 . 8.90269 0 0 1.08 -apic_18_0 apic_17_2 9.53415 0 0 0.54 -apic_18_1 . 9.53415 0 0 0.54 -apic_18_2 . 9.53415 0 0 0.54 -apic_18_3 . 9.53415 0 0 0.54 -apic_18_4 . 9.53415 0 0 0.54 -apic_18_5 . 9.53415 0 0 0.54 -apic_18_6 . 9.53415 0 0 0.54 -apic_18_7 . 9.53415 0 0 0.54 -apic_18_8 . 9.53415 0 0 0.54 -apic_18_9 . 9.53415 0 0 0.54 -apic_18_10 . 9.53415 0 0 0.54 -apic_18_11 . 9.53415 0 0 0.54 -apic_18_12 . 9.53415 0 0 0.54 -apic_18_13 . 9.53415 0 0 0.54 -apic_18_14 . 9.53415 0 0 0.54 -apic_18_15 . 9.53415 0 0 0.54 -apic_18_16 . 9.53415 0 0 0.54 -apic_18_17 . 9.53415 0 0 0.54 -apic_18_18 . 9.53415 0 0 0.54 -apic_18_19 . 9.53415 0 0 0.54 -apic_18_20 . 9.53415 0 0 0.54 -apic_19_0 apic_18_20 10.1414 0 0 0.54 -apic_19_1 . 10.1414 0 0 0.54 -apic_19_2 . 10.1414 0 0 0.54 -apic_19_3 . 10.1414 0 0 0.54 -apic_19_4 . 10.1414 0 0 0.54 -apic_19_5 . 10.1414 0 0 0.54 -apic_19_6 . 10.1414 0 0 0.54 -apic_19_7 . 10.1414 0 0 0.54 -apic_19_8 . 10.1414 0 0 0.54 -apic_19_9 . 10.1414 0 0 0.54 -apic_19_10 . 10.1414 0 0 0.54 -apic_19_11 . 10.1414 0 0 0.54 -apic_19_12 . 10.1414 0 0 0.54 -apic_19_13 . 10.1414 0 0 0.54 -apic_19_14 . 10.1414 0 0 0.54 -apic_20_0 apic_18_20 5.52984 0 0 0.54 -apic_20_1 . 5.52984 0 0 0.54 -apic_20_2 . 5.52984 0 0 0.54 -apic_20_3 . 5.52984 0 0 0.54 -apic_20_4 . 5.52984 0 0 0.54 -apic_20_5 . 5.52984 0 0 0.54 -apic_20_6 . 5.52984 0 0 0.54 -apic_20_7 . 5.52984 0 0 0.54 -apic_20_8 . 5.52984 0 0 0.54 -apic_21_0 apic_17_2 11.1759 0 0 0.54 -apic_21_1 . 11.1759 0 0 0.54 -apic_21_2 . 11.1759 0 0 0.54 -apic_21_3 . 11.1759 0 0 0.54 -apic_21_4 . 11.1759 0 0 0.54 -apic_21_5 . 11.1759 0 0 0.54 -apic_21_6 . 11.1759 0 0 0.54 -apic_21_7 . 11.1759 0 0 0.54 -apic_21_8 . 11.1759 0 0 0.54 -apic_21_9 . 11.1759 0 0 0.54 -apic_21_10 . 11.1759 0 0 0.54 -apic_21_11 . 11.1759 0 0 0.54 -apic_21_12 . 11.1759 0 0 0.54 -apic_21_13 . 11.1759 0 0 0.54 -apic_21_14 . 11.1759 0 0 0.54 -apic_21_15 . 11.1759 0 0 0.54 -apic_21_16 . 11.1759 0 0 0.54 -apic_21_17 . 11.1759 0 0 0.54 -apic_21_18 . 11.1759 0 0 0.54 -apic_21_19 . 11.1759 0 0 0.54 -apic_21_20 . 11.1759 0 0 0.54 -apic_21_21 . 11.1759 0 0 0.54 -apic_21_22 . 11.1759 0 0 0.54 -apic_21_23 . 11.1759 0 0 0.54 -apic_21_24 . 11.1759 0 0 0.54 -apic_21_25 . 11.1759 0 0 0.54 -apic_21_26 . 11.1759 0 0 0.54 -apic_22_0 apic_16_2 16.7786 0 0 1.08 -apic_22_1 . 16.7786 0 0 1.08 -apic_22_2 . 16.7786 0 0 1.08 -apic_23_0 apic_22_2 17.472 0 0 1.08 -apic_23_1 . 17.472 0 0 1.08 -apic_23_2 . 17.472 0 0 1.08 -apic_24_0 apic_22_2 11.2915 0 0 1.4935 -apic_24_1 . 11.2915 0 0 1.4935 -apic_24_2 . 11.2915 0 0 1.4935 -apic_24_3 . 11.2915 0 0 1.4935 -apic_24_4 . 11.2915 0 0 1.4935 -apic_24_5 . 11.2915 0 0 1.4935 -apic_24_6 . 11.2915 0 0 1.4935 -apic_24_7 . 11.2915 0 0 1.4935 -apic_24_8 . 11.2915 0 0 1.4935 -apic_25_0 apic_5_2 4.82258 0 0 0.54 -apic_25_1 . 4.82258 0 0 0.54 -apic_25_2 . 4.82258 0 0 0.54 -apic_26_0 apic_25_2 7.25593 0 0 0.54 -apic_26_1 . 7.25593 0 0 0.54 -apic_26_2 . 7.25593 0 0 0.54 -apic_26_3 . 7.25593 0 0 0.54 -apic_26_4 . 7.25593 0 0 0.54 -apic_26_5 . 7.25593 0 0 0.54 -apic_26_6 . 7.25593 0 0 0.54 -apic_26_7 . 7.25593 0 0 0.54 -apic_26_8 . 7.25593 0 0 0.54 -apic_26_9 . 7.25593 0 0 0.54 -apic_26_10 . 7.25593 0 0 0.54 -apic_26_11 . 7.25593 0 0 0.54 -apic_26_12 . 7.25593 0 0 0.54 -apic_26_13 . 7.25593 0 0 0.54 -apic_26_14 . 7.25593 0 0 0.54 -apic_27_0 apic_25_2 8.09499 0 0 0.54 -apic_27_1 . 8.09499 0 0 0.54 -apic_27_2 . 8.09499 0 0 0.54 -apic_27_3 . 8.09499 0 0 0.54 -apic_27_4 . 8.09499 0 0 0.54 -apic_27_5 . 8.09499 0 0 0.54 -apic_27_6 . 8.09499 0 0 0.54 -apic_27_7 . 8.09499 0 0 0.54 -apic_27_8 . 8.09499 0 0 0.54 -apic_28_0 apic_0_2 7.9644 0 0 1.08 -apic_28_1 . 7.9644 0 0 1.08 -apic_28_2 . 7.9644 0 0 1.08 -apic_29_0 apic_28_2 4.28209 0 0 0.54 -apic_29_1 . 4.28209 0 0 0.54 -apic_29_2 . 4.28209 0 0 0.54 -apic_29_3 . 4.28209 0 0 0.54 -apic_29_4 . 4.28209 0 0 0.54 -apic_29_5 . 4.28209 0 0 0.54 -apic_29_6 . 4.28209 0 0 0.54 -apic_29_7 . 4.28209 0 0 0.54 -apic_29_8 . 4.28209 0 0 0.54 -apic_30_0 apic_28_2 5.14988 0 0 0.54 -apic_30_1 . 5.14988 0 0 0.54 -apic_30_2 . 5.14988 0 0 0.54 -apic_30_3 . 5.14988 0 0 0.54 -apic_30_4 . 5.14988 0 0 0.54 -apic_30_5 . 5.14988 0 0 0.54 -apic_30_6 . 5.14988 0 0 0.54 -apic_30_7 . 5.14988 0 0 0.54 -apic_30_8 . 5.14988 0 0 0.54 diff --git a/tests/python/mus/rc19.py b/tests/python/mus/rc19.py deleted file mode 100644 index fa0d596b..00000000 --- a/tests/python/mus/rc19.py +++ /dev/null @@ -1,264 +0,0 @@ -# -*- coding: utf-8 -*- -# rc19.py --- -# -# Filename: rc19.py -# Description: -# Author: Subhasis Ray -# Maintainer: -# Created: Sat May 24 14:10:22 2014 (+0530) -# Version: -# Last-Updated: -# By: -# Update #: 0 -# URL: -# Keywords: -# Compatibility: -# -# - -# Commentary: -# -# -# -# - -# Change log: -# -# -# -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 3, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, Fifth -# Floor, Boston, MA 02110-1301, USA. -# -# - -# Code: -"""Cell morphology and passive properties from Branco et al 2010.""" -from __future__ import print_function -__author__ = 'Subhasis Ray, Dilawar Sing' - -import sys - -import moose -from moose import utils as mutils -from synapse import * -import numpy as np -from settings import * -from nachannel import * -from kchannel import * -from cachannel import * -from hchannel import * - -# locations of the synapses -# synapse_locations = [#(9, 2), # this one seems garbage : loc should be within 0-1 -# (13, 1), -# (13, 0.875), -# (13, 0.75), -# (13, 0.625), -# (13, 0.5), -# (13, 0.375), -# (13, 0.25), -# (13, 0.125), -# (13, 0)] - -# This has been generated and edited from dumping the locations in the -# neuron model -synloc = [ - 'dend_13_0', - 'dend_13_1', - 'dend_13_2', - 'dend_13_3', - 'dend_13_4', - 'dend_13_5', - 'dend_13_6', - 'dend_13_7', - 'dend_13_8',] - -# synapse stimulation order -# stim_order = [# [2, 9], # What is this? -# [0, 1, 2, 3, 4, 5, 6, 7, 8], -# [8, 7, 6, 5, 4, 3, 2, 1, 0]] -stim_order = [[8]] - -color = {0: 'darkcyan', - 1: 'darkmagenta'} - -library = moose.Neutral('/library') -model_container = moose.Neutral('/model') -data_container = moose.Neutral('/data') - -simdt = 5e-6 - -def make_prototype(passive=True): - path = '%s/rc19' % (library.path) - pfile = 'rc19.p' - try: - return moose.element(path) - except ValueError: - pass - if not passive: - make_na() - make_kv() - make_km() - make_kca() - make_cat() - make_cahva() - make_h() - try: - proto = moose.element(path) - except ValueError: - print('Loading model %s to %s' % (pfile, path)) - proto = moose.loadModel(pfile, path, 'ee') # hsolve is not functional yet - for comp in proto[0].children: - comp.initVm = -75e-3 - for chan in moose.wildcardFind('%s/##[ISA=HHChannel]'): - chan.Gbar *= tadj - return proto - -def setup_model(model_path, synapse_locations, passive=False, solver='hsolve'): - """Set up a single cell model under `model_path` with synapses - created in the compartments listed in `synapse_locations`. - - - `model_path` - location where the model should be created. - - `synapse_locations`: compartment names for the synapses. - - """ - cell = moose.copy(make_prototype(passive), model_path) - if solver.lower() == 'hsolve': - hsolve = moose.HSolve( '%s/solve' % (cell.path)) - hsolve.dt = simdt - hsolve.target = cell.path - syninfo_list = [] - for compname in synapse_locations: - comppath = '%s/%s' % (cell.path, compname) - print('1111 Creating synapse in', comppath) - compartment = moose.element(comppath) - syninfo = make_synapse(compartment) - syninfo_list.append(syninfo) - # connect pulse stimulus - stim_path = '%s/%s/stim' % (cell.path, compname) - print('2222 Creating stimuls in', stim_path) - stim = moose.PulseGen(stim_path) - moose.connect(stim, 'output', syninfo['spike'], 'Vm') - syninfo['stimulus'] = stim - return {'neuron': cell, - 'syninfo': syninfo_list} - -def setup_recording(data_path, neuron, syninfo_list): - """Record Vm from soma and synaptic conductances from synapses in - syninfo_list - - """ - neuron_path = neuron.path - data_container = moose.Neutral(data_path) - soma_vm = moose.Table('%s/Vm_soma' % (data_path)) - soma_path = '%s/soma_1' % (neuron_path) - print('5555 Soma path', soma_path) - soma = moose.element(soma_path) - moose.connect(soma_vm, 'requestOut', soma, 'getVm') - ampa_data = moose.Neutral('%s/G_AMPA' % (data_path)) - nmda_data = moose.Neutral('%s/G_NMDA' % (data_path)) - ampa_gk = [] - nmda_gk = [] - - # Record synaptic conductances - for syninfo in syninfo_list: - compname = syninfo['spike'].parent.name - tab = moose.Table('%s/Gk_nmda_%s' % (nmda_data.path, compname)) - moose.connect(tab, 'requestOut', syninfo['nmda'], 'getGk') - nmda_gk.append(tab) - tab = moose.Table('%s/Gk_ampa_%s' % (ampa_data.path, compname)) - moose.connect(tab, 'requestOut', syninfo['ampa'], 'getGk') - ampa_gk.append(tab) - return {'ampa_gk': ampa_gk, - 'nmda_gk': nmda_gk, - 'soma_vm': soma_vm, - 'data': data_container} - -def setup_experiment(name, stim_order, onset, interval, passive=False, solver='hsolve'): - """Setup an experiment with specified stimulation order. `stim_order` is a - series of integers specifying the compartment numbers along dendritic - branch dend_13. `onset` is time of onset of stimulation protocol. - `inteval` is the interval between stimulation time of - successive synapses.""" - model_container = moose.Neutral('/model/%s' % (name)) - model_info = setup_model(model_container.path, synloc, passive=passive, solver=solver) - data_container = moose.Neutral('/data/%s' % (name)) - data_info = setup_recording(data_container.path, model_info['neuron'], model_info['syninfo']) - for ii, dend_no in enumerate(stim_order): - comp_path = '%s/%s' % (model_info['neuron'].path, synloc[dend_no]) - stim = moose.PulseGen('%s/stim' % (comp_path)) - stim.delay[0] = onset + ii * interval - stim.width[0] = 1e9 # The spike generator is edge triggered. A single level change will suffice. - stim.level[0] = 1.0 - print('Experiment %s has been setup.' % (name)) - print('Stimulus order:', [synloc[ii] for ii in stim_order]) - print('Stimulus onset:', onset) - print('Inter stimulus interval:', interval) - return (data_info, model_info) - - -tstop = 200e-3 -tonset = 50e-3 -intervals = [1e-3]#[ii * 1e-3 for ii in range(1,11)] -def run_sim_parallel(passive=True, solver='hsolve'): - data_info_list = [] - model_info_list = [] - for jj, ti in enumerate(intervals): - for ii, st in enumerate(stim_order): - experiment_name = 'expt_%d_%d' % (jj, ii) - dinfo, minfo = setup_experiment(experiment_name, st, tonset, ti, passive=passive, solver=solver) - data_info_list.append(dinfo) - model_info_list.append(minfo) - mutils.setDefaultDt(elecdt=simdt) - mutils.assignDefaultTicks() - moose.reinit() - moose.start(tstop) - print('$$$$$$$$$$$', moose.element('/clock' ).currentTime) - axes_vm = fig.add_subplot(111) - # axes_vm_out = fig.add_subplot(121) - # axes_vm_in = fig.add_subplot(122, sharex=axes_vm_out, sharey=axes_vm_out) - ################ - # axes_vm = fig.add_subplot(311) - # axes_nmda = fig.add_subplot(312) - # axes_ampa = fig.add_subplot(313) - for jj, ti in enumerate(intervals): - for ii, st in enumerate(stim_order): - dinfo = data_info_list[jj * len(stim_order) + ii] - print('Interval=', ti, 'Stim order=', st) - print('dinfo:', dinfo) - print(dinfo['soma_vm']) - print(dinfo['soma_vm'].vector) - v = dinfo['soma_vm'].vector - t = np.linspace(0, tstop, len(v)) - print('num points=', len(t), 't0=', t[0], 't_last=', t[-1], 'v0=', v[0], 'v_last=', v[-1]) - -if __name__ == '__main__': - if len(sys.argv) > 1: - passive = sys.argv[1].lower() == 'passive' - else: - passive = False - if len(sys.argv) > 2: - solver = sys.argv[2].lower() - else: - solver = 'hsolve' - print('running simulation using: model with solver %s. Model is passive? %s' % (solver, passive)) - run_sim_parallel(passive=passive, solver=solver) - - -# -# rc19.py ends here diff --git a/tests/python/mus/settings.py b/tests/python/mus/settings.py deleted file mode 100644 index bd030859..00000000 --- a/tests/python/mus/settings.py +++ /dev/null @@ -1,58 +0,0 @@ -# -*- coding: utf-8 -*- -# settings.py --- -# -# Filename: settings.py -# Description: -# Author: Subhasis Ray -# Maintainer: -# Created: Wed Jun 4 12:26:46 2014 (+0530) -# Version: -# Last-Updated: -# By: -# Update #: 0 -# URL: -# Keywords: -# Compatibility: -# -# - -# Commentary: -# -# -# -# - -# Change log: -# -# -# -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 3, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, Fifth -# Floor, Boston, MA 02110-1301, USA. -# -# - -# Code: - - - -q10 = 2.3 -temp0 = 23.0 # Centegrade: original temperature -temp = 37 # Centegrade : experimental temperature -tadj = q10 ** ((temp - temp0)/10.0) - - -# -# settings.py ends here diff --git a/tests/python/mus/synapse.py b/tests/python/mus/synapse.py deleted file mode 100644 index 617f93eb..00000000 --- a/tests/python/mus/synapse.py +++ /dev/null @@ -1,109 +0,0 @@ -# -*- coding: utf-8 -*- -# synapse.py --- -# -# Filename: synapse.py -# Description: -# Author: Subhasis Ray -# Maintainer: -# Created: Mon May 26 11:29:54 2014 (+0530) -# Version: -# Last-Updated: -# By: -# Update #: 0 -# URL: -# Keywords: -# Compatibility: -# -# - -# Commentary: -# -# -# -# - -# Change log: -# -# -# -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 3, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, Fifth -# Floor, Boston, MA 02110-1301, USA. -# -# - -# Code: - -import moose - -def make_NMDA(comp): - """This function is modified from proto18.py by Upi, which is again - based on Dave Beeman's implementation. - - This implementation of NMDA uses the formulation by Zador, Koch - and Brown (1990) where - - Gk = Gbar * (exp(- t / tau1) - exp(-t / tau2)) / (1 + eta * [Mg2+] * exp(- gmma * Vm)) - - The MgBlock object sits between the SynChan and teh Compartment - and scales the Gk of regular SynChan Gk by [Mg2+] such that the - resulting conductance is as above formula, where the fields are : - - CMg = [Mg2+] - KMg_A = 1 / eta - KMg_B = 1 / gamma - - """ - nmda = moose.SynChan('%s/nmda' % (comp.path)) - nmda.synapse.num = 1 - nmda.Ek = 0.0 - nmda.tau1 = 20e-3 - nmda.tau2 = 20e-3 - nmda.Gbar = 0.2 * 8e-9 # channel open probability is 0.2 - nmda.bufferTime = 0.0001 - mgblock = moose.MgBlock('%s/mgblock' % (nmda.path)) - mgblock.CMg = 1.2 # [Mg] in mM - mgblock.Zk = 2 - mgblock.KMg_A = 1.0/0.28 - mgblock.KMg_B = 1.0/62 - moose.connect( nmda, 'channelOut', mgblock, 'origChannel', 'OneToOne' ) - moose.connect(mgblock, 'channel', comp, 'channel') - return nmda, mgblock - -def make_AMPA(comp): - ampa = moose.SynChan('%s/ampa' % (comp.path)) - ampa.synapse.num = 1 - ampa.tau1 = 2e-3 - ampa.Gbar = 0.5e-9 - ampa.bufferTime = 0.0001 - moose.connect(ampa, 'channel', comp, 'channel') - return ampa - -def make_synapse(comp): - nmda, mgblock = make_NMDA(comp) - ampa = make_AMPA(comp) - spikegen = moose.SpikeGen('%s/spike' % (comp.path)) - moose.connect(spikegen, 'spikeOut', ampa.synapse[0], 'addSpike') - moose.connect(spikegen, 'spikeOut', nmda.synapse[0], 'addSpike') - return {'ampa': ampa, - 'nmda': nmda, - 'mgblock': mgblock, - 'spike': spikegen - } - - - -# -# synapse.py ends here diff --git a/tests/python/testXchan1.py b/tests/python/testXchan1.py deleted file mode 100644 index d93b1b3e..00000000 --- a/tests/python/testXchan1.py +++ /dev/null @@ -1,181 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################################### -## This program is part of 'MOOSE', the -## Messaging Object Oriented Simulation Environment. -## Copyright (C) 2014 Upinder S. Bhalla. and NCBS -## It is made available under the terms of the -## GNU Lesser General Public License version 2.1 -## See the file COPYING.LIB for the full notice. -## Here test ConcChan. We set up a channel and a pump and run two tests. -## First we have zero flux through the pump and check that the conc -## equalizes on both sides of the membrane. Then we change the Kf of -## the pump to a value designed to give twice the conc In as Out. -## The system is a 1-voxel cyl compt and an internal endoMesh, having a -## volume = 1/8 of the cylinder. -## \ -## COMPT: s ----> / s :ENDO -## s =chan= s -## \ -## -## This becomes: -## \ -## COMPT: s ----> s_xfer_endo / s :ENDO -## s =chan= s -## \ -## -######################################################################### - -import math -import numpy as np -import moose -print( '[INFO ] Using moose from %s, %s' % (moose.__file__, moose.version()) ) -import moose.fixXreacs as fixXreacs - -def makeModel(): - # create container for model - num = 1 # number of compartments - model = moose.Neutral( '/model' ) - compartment = moose.CylMesh( '/model/compartment' ) - compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder - - # create molecules and reactions - s = moose.Pool( '/model/compartment/s' ) - rXfer = moose.Reac( '/model/compartment/rXfer' ) - ##################################################################### - # Put in endo compartment. Add molecule s - endo = moose.EndoMesh( '/model/endo' ) - # Note that the chanPool must be on the 'In' compartment. - #chanPool = moose.Pool( '/model/compartment/chanPool' ) - #chan = moose.ConcChan( '/model/compartment/chanPool/chan' ) - chanPool = moose.Pool( '/model/endo/chanPool' ) - chan = moose.ConcChan( '/model/endo/chanPool/chan' ) - endo.isMembraneBound = True - endo.surround = compartment - es = moose.Pool( '/model/endo/s' ) - ##################################################################### - moose.connect( rXfer, 'sub', s, 'reac' ) - moose.connect( rXfer, 'prd', es, 'reac' ) - moose.connect( chanPool, 'nOut', chan, 'setNumChan' ) - moose.connect( chan, 'out', s, 'reac' ) - moose.connect( chan, 'in', es, 'reac' ) - volRatio = compartment.volume / endo.volume - rXfer.Kf = 0.0 # 0.02/sec - rXfer.Kb = 0.0 # - s.concInit = 0.001 - chanPool.nInit = 1000.0 - # Flux (#/s) = permeability * N * (#out/vol_out - #in/vol_in) - chan.permeability = 0.1 * chanPool.volume / chanPool.nInit - - ##################################################################### - fixXreacs.fixXreacs( '/model' ) - #fixXreacs.restoreXreacs( '/model' ) - #fixXreacs.fixXreacs( '/model' ) - ##################################################################### - - # Make solvers - ksolve = moose.Ksolve( '/model/compartment/ksolve' ) - dsolve = moose.Dsolve( '/model/dsolve' ) - eksolve = moose.Ksolve( '/model/endo/ksolve' ) - eksolve.method = 'gsl' - edsolve = moose.Dsolve( '/model/endo/dsolve' ) - - stoich = moose.Stoich( '/model/compartment/stoich' ) - stoich.compartment = compartment - stoich.ksolve = ksolve - stoich.dsolve = dsolve - stoich.path = "/model/compartment/##" - assert( dsolve.numPools == 2 ) - - estoich = moose.Stoich( '/model/endo/stoich' ) - estoich.compartment = endo - estoich.ksolve = eksolve - estoich.dsolve = edsolve - estoich.path = "/model/endo/##" - assert( edsolve.numPools == 2 ) - - edsolve.buildMeshJunctions( dsolve ) - - plot1 = moose.Table2( '/model/plot1' ) - plot2 = moose.Table2( '/model/plot2' ) - plot3 = moose.Table2( '/model/plot3' ) - moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) - moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) - moose.connect( '/model/plot3', 'requestOut', '/model/compartment/s_xfer_endo', 'getN' ) - plot4 = moose.Table2( '/model/plot4' ) - plot5 = moose.Table2( '/model/plot5' ) - plot6 = moose.Table2( '/model/plot6' ) - moose.connect( '/model/plot4', 'requestOut', s, 'getConc' ) - moose.connect( '/model/plot5', 'requestOut', es, 'getConc' ) - moose.connect( '/model/plot6', 'requestOut', '/model/compartment/s_xfer_endo', 'getConc' ) - -def doPlot( ax, i, label ): - scale = 1 - if i > 3: - scale = 1000 # Just to plot in uM. - plot1 = '/model/plot' + str(i) - plot2 = '/model/plot' + str(i+1) - plot3 = '/model/plot' + str(i+2) - plt.ylabel( label ) - plt.xlabel( 'time(s)' ) - v1 = moose.element(plot1).vector * scale - v2 = moose.element(plot2).vector * scale - v3 = moose.element(plot3).vector * scale - ax.plot( v1, label='s' ) - ax.plot( v2, 'x',label='es' ) - ax.plot( v3, label='xfer' ) - ax.plot( np.array( v1 ) + np.array( v2 ), label='sum' ) - plt.legend() - - -def almostEq( a, b ): - #print a, b, (a-b)/(a+b) - return abs(a-b)/(a+b) < 5e-5 - -def main( standalone = False ): - runtime = 100 - displayInterval = 2 - makeModel() - for i in range( 10, 18 ): - moose.setClock( i, 0.01 ) - moose.reinit() - moose.start( runtime ) - s = moose.element( '/model/compartment/s' ) - es = moose.element( '/model/endo/s' ) - assert almostEq( s.conc, es.conc ), 'Asserting %g=%g' % (s.conc, es.conc) - # We go for concEndo = 2x concOut. Then - # We already know volIn = volOut/8 - # #in/volIn = 2x #out/volOut - # #in/volIn = 2x #out/(8*volIn) - # so #in = #out/4 - # From consv, #in + #out = nInit - # so 5/4#out = nInit => - # #out = 0.8*nInit; #in = 0.2*nInit - # - # flux = perm * nChan * (0.8nInit/volOut - 0.2nInit/(volOut/8) ) = - # perm * (nChan*nInit/volOut) * (0.8 - 0.2*8) = - # perm * (nChan*nInit/volOut) * (-0.8) - # - # This has to be balanced by flux = numKf * nOut = numKf * 0.8 * nInit - # So 0.8*numKf*nInit = 0.8*perm*nChan*nInit/volOut - - # Note that chan.permeability = 0.1*chanPool.volume / chanPool.nInit - - # so numKf = perm*nChan/volOut = (0.1*volIn/nChan)*nChan/volOut=0.1/8 - # - rXfer = moose.element( '/model/compartment/rXfer' ) - rXfer.numKf = 0.1/8.0 - moose.start( runtime ) - assert( almostEq( 2 * s.conc, es.conc ) ) - - if standalone: - fig = plt.figure( figsize=(12,10) ) - ax1 = fig.add_subplot(211) - doPlot( ax1, 1, '# of molecules' ) - ax2 = fig.add_subplot(212) - doPlot( ax2, 4, 'conc (uM)' ) - plt.show() - moose.delete( '/model' ) - -# Run the 'main' if this script is executed standalone. -if __name__ == '__main__': - main( standalone = True ) diff --git a/tests/python/testXdiff1.py b/tests/python/testXdiff1.py deleted file mode 100644 index 0cec22d9..00000000 --- a/tests/python/testXdiff1.py +++ /dev/null @@ -1,172 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################################### -## This program is part of 'MOOSE', the -## Messaging Object Oriented Simulation Environment. -## Copyright (C) 2014 Upinder S. Bhalla. and NCBS -## It is made available under the terms of the -## GNU Lesser General Public License version 2.1 -## See the file COPYING.LIB for the full notice. -## Here test diffusion across a junction. We set up a pump and change its -## rate to do a check on the calculation of the diffusion rate separate -## from the verification that diffusion gives equal concs on either side. -## The system is a ## 1-voxel cyl compt and an internal endoMesh, -## having a volume = 1/8 of the parent cylinder.. -## \ -## COMPT: s ----> / s :ENDO -## s =diffn= s -## \ -## -## This becomes: -## \ -## COMPT: s ----> s_xfer_endo / s :ENDO -# s =diffn= s -## \ -## -######################################################################### - - -import math -import numpy as np -import moose -import moose.fixXreacs as fixXreacs - -diffConst = 1e-16 - -def makeModel(): - # create container for model - num = 1 # number of compartments - model = moose.Neutral( '/model' ) - compartment = moose.CylMesh( '/model/compartment' ) - compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder - - # create molecules and reactions - s = moose.Pool( '/model/compartment/s' ) - rXfer = moose.Reac( '/model/compartment/rXfer' ) - ##################################################################### - # Put in endo compartment. Add molecule s - endo = moose.EndoMesh( '/model/endo' ) - endo.isMembraneBound = False - endo.surround = compartment - es = moose.Pool( '/model/endo/s' ) - ##################################################################### - moose.connect( rXfer, 'sub', s, 'reac' ) - moose.connect( rXfer, 'prd', es, 'reac' ) - volRatio = compartment.volume / endo.volume - #print( "Volume ratio = {}".format( volRatio ) ) - rXfer.Kf = 0.0 # 0.02/sec - rXfer.Kb = 0.0 # - s.concInit = 0.001 - s.diffConst = diffConst - es.diffConst = diffConst - - ##################################################################### - fixXreacs.fixXreacs( '/model' ) - #fixXreacs.restoreXreacs( '/model' ) - #fixXreacs.fixXreacs( '/model' ) - ##################################################################### - - # Make solvers - ksolve = moose.Ksolve( '/model/compartment/ksolve' ) - dsolve = moose.Dsolve( '/model/dsolve' ) - eksolve = moose.Ksolve( '/model/endo/ksolve' ) - edsolve = moose.Dsolve( '/model/endo/dsolve' ) - - stoich = moose.Stoich( '/model/compartment/stoich' ) - stoich.compartment = compartment - stoich.ksolve = ksolve - stoich.dsolve = dsolve - stoich.path = "/model/compartment/##" - assert( dsolve.numPools == 2 ) - - estoich = moose.Stoich( '/model/endo/stoich' ) - estoich.compartment = endo - estoich.ksolve = eksolve - estoich.dsolve = edsolve - estoich.path = "/model/endo/##" - assert( edsolve.numPools == 1 ) - - edsolve.buildMeshJunctions( dsolve ) - - plot1 = moose.Table2( '/model/plot1' ) - plot2 = moose.Table2( '/model/plot2' ) - plot3 = moose.Table2( '/model/plot3' ) - moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) - moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) - moose.connect( '/model/plot3', 'requestOut', '/model/compartment/s_xfer_endo', 'getN' ) - plot4 = moose.Table2( '/model/plot4' ) - plot5 = moose.Table2( '/model/plot5' ) - plot6 = moose.Table2( '/model/plot6' ) - moose.connect( '/model/plot4', 'requestOut', s, 'getConc' ) - moose.connect( '/model/plot5', 'requestOut', es, 'getConc' ) - moose.connect( '/model/plot6', 'requestOut', '/model/compartment/s_xfer_endo', 'getConc' ) - -def doPlot( ax, i, label ): - scale = 1 - if i > 3: - scale = 1000 # Just to plot in uM. - plot1 = '/model/plot' + str(i) - plot2 = '/model/plot' + str(i+1) - plot3 = '/model/plot' + str(i+2) - plt.ylabel( label ) - plt.xlabel( 'time(s)' ) - v1 = moose.element(plot1).vector * scale - v2 = moose.element(plot2).vector * scale - v3 = moose.element(plot3).vector * scale - ax.plot( v1, label='s' ) - ax.plot( v2, 'x',label='es' ) - ax.plot( v3, label='xfer' ) - ax.plot( np.array( v1 ) + np.array( v2 ), label='sum' ) - plt.legend() - - -def almostEq( a, b ): - #print a, b, (a-b)/(a+b) - return abs(a-b)/(a+b) < 5e-5 - -def main( standalone = False ): - runtime = 100 - makeModel() - for i in range( 10, 18 ): - moose.setClock( i, 0.01 ) - moose.reinit() - moose.start( runtime ) - s = moose.element( '/model/compartment/s' ) - es = moose.element( '/model/endo/s' ) - assert( almostEq( s.conc, es.conc ) ) - # We go for concEndo = 2x concOut. Then - # We already know volIn = volOut/8 - # #in/volIn = 2x #out/volOut - # #in/volIn = 2x #out/(8*volIn) - # so #in = #out/4 - # From consv, #in + #out = nInit - # so 5/4#out = nInit => - # #out = 0.8*nInit; #in = 0.2*nInit - # - # Diffn flux = D * (xa/L) * (0.8nInit/volOut - 0.2nInit/(volOut/8) ) - # = -D * (xa/L) * (nInit/volOut) * 0.8 - # We can obtain xa and L from the endo/mesh - # - # This has to be balanced by flux = numKf * nOut = numKf * 0.8 * nInit - # So 0.8*numKf*nInit = 0.8*(D.Xa/L)*(nInit/volOut) - # So numKf = D.Xa/(L*volOut) - # - rXfer = moose.element( '/model/compartment/rXfer' ) - endo = moose.element( '/model/endo' ) - compt = moose.element( '/model/compartment' ) - endoA = endo.aScale * pow( compt.volume, endo.aPower ) - rXfer.numKf = 2.0*diffConst*endoA/(compt.r0*compt.volume) - moose.start( runtime ) - assert( almostEq( 2 * s.conc, es.conc ) ) - - if standalone: - fig = plt.figure( figsize=(12,10) ) - ax1 = fig.add_subplot(211) - doPlot( ax1, 1, '# of molecules' ) - ax2 = fig.add_subplot(212) - doPlot( ax2, 4, 'conc (uM)' ) - plt.show() - moose.delete( '/model' ) - -# Run the 'main' if this script is executed standalone. -if __name__ == '__main__': - main( standalone = True ) diff --git a/tests/python/testXenz1.py b/tests/python/testXenz1.py deleted file mode 100644 index 75234a11..00000000 --- a/tests/python/testXenz1.py +++ /dev/null @@ -1,135 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################################### -## This program is part of 'MOOSE', the -## Messaging Object Oriented Simulation Environment. -## Copyright (C) 2014 Upinder S. Bhalla. and NCBS -## It is made available under the terms of the -## GNU Lesser General Public License version 2.1 -## See the file COPYING.LIB for the full notice. -## -## Endo / Compartment -## \ -## sub--enz-/-----> prd -## sub<-----\----- prd -## / -######################################################################### - - -import math -import numpy as np -import moose -import moose.fixXreacs as fixXreacs - -subInit = 0.002 -eInit = 0.001 -Km = 0.001 -kcat = 0.2 -Kf = 0.1 - -def makeModel(): - # create container for model - num = 1 # number of compartments - model = moose.Neutral( '/model' ) - compartment = moose.CylMesh( '/model/compartment' ) - compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder - - # create molecules and reactions - prd = moose.Pool( '/model/compartment/prd' ) - rXfer = moose.Reac( '/model/compartment/rXfer' ) - ##################################################################### - # Put in endo compartment. Add molecule s - endo = moose.EndoMesh( '/model/endo' ) - endo.isMembraneBound = True - endo.surround = compartment - sub = moose.Pool( '/model/endo/sub' ) - enzPool = moose.Pool( '/model/endo/enzPool' ) - enzPool.concInit = eInit - enz = moose.MMenz( '/model/endo/enzPool/enz' ) - ##################################################################### - moose.connect( enz, 'sub', sub, 'reac' ) - moose.connect( enz, 'prd', prd, 'reac' ) - moose.connect( enzPool, 'nOut', enz, 'enzDest' ) - moose.connect( rXfer, 'sub', prd, 'reac' ) - moose.connect( rXfer, 'prd', sub, 'reac' ) - rXfer.Kf = Kf # 0.04/sec - rXfer.Kb = 0.0 # 0.02/sec - enz.Km = Km - enz.kcat = kcat - # v = es.kcat/(s+Km) - # v = Kf * conc. - ##################################################################### - fixXreacs.fixXreacs( '/model' ) - fixXreacs.restoreXreacs( '/model' ) - fixXreacs.fixXreacs( '/model' ) - ##################################################################### - - # Make solvers - ksolve = moose.Ksolve( '/model/compartment/ksolve' ) - dsolve = moose.Dsolve( '/model/dsolve' ) - eksolve = moose.Ksolve( '/model/endo/ksolve' ) - edsolve = moose.Dsolve( '/model/endo/dsolve' ) - - stoich = moose.Stoich( '/model/compartment/stoich' ) - stoich.compartment = compartment - stoich.ksolve = ksolve - stoich.dsolve = dsolve - stoich.path = "/model/compartment/##" - assert( dsolve.numPools == 2 ) - sub.vec.concInit = subInit - enzPool.vec.concInit = eInit - - estoich = moose.Stoich( '/model/endo/stoich' ) - estoich.compartment = endo - estoich.ksolve = eksolve - estoich.dsolve = edsolve - estoich.path = "/model/endo/##" - assert( edsolve.numPools == 3 ) - - edsolve.buildMeshJunctions( dsolve ) - - plot1 = moose.Table2( '/model/plot1' ) - plot2 = moose.Table2( '/model/plot2' ) - moose.connect( '/model/plot1', 'requestOut', sub, 'getN' ) - moose.connect( '/model/plot2', 'requestOut', prd, 'getN' ) - plot3 = moose.Table2( '/model/plot3' ) - plot4 = moose.Table2( '/model/plot4' ) - moose.connect( '/model/plot3', 'requestOut', sub, 'getConc' ) - moose.connect( '/model/plot4', 'requestOut', prd, 'getConc' ) - -def doPlot( ax, plot1, plot2, label ): - plt.ylabel( label ) - plt.xlabel( 'time(s)' ) - v1 = moose.element(plot1).vector - v2 = moose.element(plot2).vector - ax.plot( v1, label='sub' ) - ax.plot( v2, label='prd' ) - ax.plot( np.array( v1 ) + np.array( v2 ), label='sum' ) - plt.legend() - -def almostEq( a, b ): - #print a, b, (a-b)/(a+b) - return abs(a-b)/(a+b) < 5e-5 - -def main( standalone = False ): - for i in range( 10, 18 ): - moose.setClock( i, 0.001 ) - runtime = 100 - displayInterval = 2 - makeModel() - moose.reinit() - moose.start( runtime ) - assert( almostEq( moose.element( 'model/compartment/prd' ).n, - moose.element( '/model/endo/sub' ).n ) ) - - if standalone: - fig = plt.figure( figsize=(12,10) ) - ax1 = fig.add_subplot(211) - doPlot( ax1, '/model/plot1', '/model/plot2', '# of molecules' ) - ax2 = fig.add_subplot(212) - doPlot( ax2, '/model/plot3', '/model/plot4', 'conc (mM)' ) - plt.show() - moose.delete( '/model' ) - -# Run the 'main' if this script is executed standalone. -if __name__ == '__main__': - main( standalone = True ) diff --git a/tests/python/testXreacs2.py b/tests/python/testXreacs2.py deleted file mode 100644 index cee4e6b4..00000000 --- a/tests/python/testXreacs2.py +++ /dev/null @@ -1,59 +0,0 @@ -# -*- coding: utf-8 -*- -import os -mpl.rcParams['text.usetex'] = False -import moose -import numpy as np -import moose.fixXreacs as fixXreacs - -def countCrossings( plot, thresh ): - vec = moose.element( plot ).vector - #print (vec[:-1] < thresh) - return sum( (vec[:-1] < thresh) * (vec[1:] >= thresh ) ) - -def main( standalone = False ): - mfile = os.path.join( os.path.dirname( __file__), 'OSC_diff_vols.g' ) - runtime = 4000.0 - modelId = moose.loadModel( mfile, 'model', 'ee' ) - kin = moose.element( '/model/kinetics' ) - compt1 = moose.element( '/model/compartment_1' ) - compt1.x1 += kin.x1 - compt1.x0 += kin.x1 - fixXreacs.fixXreacs( '/model' ) - #fixXreacs.restoreXreacs( '/model' ) - #fixXreacs.fixXreacs( '/model' ) - - ks1 = moose.Ksolve( '/model/kinetics/ksolve' ) - ds1 = moose.Dsolve( '/model/kinetics/dsolve' ) - s1 = moose.Stoich( '/model/kinetics/stoich' ) - s1.compartment = moose.element( '/model/kinetics' ) - s1.ksolve = ks1 - s1.dsolve = ds1 - s1.path = '/model/kinetics/##' - - ks2 = moose.Ksolve( '/model/compartment_1/ksolve' ) - ds2 = moose.Dsolve( '/model/compartment_1/dsolve' ) - s2 = moose.Stoich( '/model/compartment_1/stoich' ) - s2.compartment = moose.element( '/model/compartment_1' ) - s2.ksolve = ks2 - s2.dsolve = ds2 - s2.path = '/model/compartment_1/##' - - ds2.buildMeshJunctions( ds1 ) - - moose.reinit() - moose.start( runtime ) - # I don't have an analytic way to assess oscillations - assert( countCrossings( '/model/graphs/conc2/M.Co', 0.001 ) == 4 ) - - if standalone: - # Display all plots. - for x in moose.wildcardFind( '/model/#graphs/conc#/#' ): - t = np.arange( 0, x.vector.size, 1 ) * x.dt - plt.plot( t, x.vector, label=x.name ) - plt.legend() - plt.show() - moose.delete( '/model' ) - -# Run the 'main' if this script is executed standalone. -if __name__ == '__main__': - main( standalone = True ) diff --git a/tests/python/testXreacs3.py b/tests/python/testXreacs3.py deleted file mode 100644 index a4d68029..00000000 --- a/tests/python/testXreacs3.py +++ /dev/null @@ -1,130 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################################### -## This program is part of 'MOOSE', the -## Messaging Object Oriented Simulation Environment. -## Copyright (C) 2014 Upinder S. Bhalla. and NCBS -## It is made available under the terms of the -## GNU Lesser General Public License version 2.1 -## See the file COPYING.LIB for the full notice. -## Here we set up equal Kf and Kb in a reversible reaction across a -## 1-voxel cyl compt and an internal endoMesh, having a smaller volume. -## \ -## COMPT: s <===> / s :ENDO -## \ -## -## This becomes: -## \ -## COMPT: s <===> s_xfer_endo / s :ENDO -## \ -## -######################################################################### - - -import math -import numpy as np -import moose -import moose.fixXreacs as fixXreacs - -def makeModel(): - # create container for model - num = 1 # number of compartments - model = moose.Neutral( '/model' ) - compartment = moose.CylMesh( '/model/compartment' ) - compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder - - # create molecules and reactions - s = moose.Pool( '/model/compartment/s' ) - rXfer = moose.Reac( '/model/compartment/rXfer' ) - ##################################################################### - # Put in endo compartment. Add molecule s - endo = moose.EndoMesh( '/model/endo' ) - endo.isMembraneBound = True - endo.surround = compartment - es = moose.Pool( '/model/endo/s' ) - ##################################################################### - moose.connect( rXfer, 'sub', s, 'reac' ) - moose.connect( rXfer, 'prd', es, 'reac' ) - volRatio = compartment.volume / endo.volume - rXfer.Kf = 0.02 # 0.01/sec - rXfer.Kb = 0.02 # 1/sec - - ##################################################################### - fixXreacs.fixXreacs( '/model' ) - fixXreacs.restoreXreacs( '/model' ) - fixXreacs.fixXreacs( '/model' ) - ##################################################################### - - # Make solvers - ksolve = moose.Ksolve( '/model/compartment/ksolve' ) - dsolve = moose.Dsolve( '/model/dsolve' ) - eksolve = moose.Ksolve( '/model/endo/ksolve' ) - edsolve = moose.Dsolve( '/model/endo/dsolve' ) - - stoich = moose.Stoich( '/model/compartment/stoich' ) - stoich.compartment = compartment - stoich.ksolve = ksolve - stoich.dsolve = dsolve - stoich.path = "/model/compartment/##" - assert( dsolve.numPools == 2 ) - s.vec.concInit = [1]*num - - estoich = moose.Stoich( '/model/endo/stoich' ) - estoich.compartment = endo - estoich.ksolve = eksolve - estoich.dsolve = edsolve - estoich.path = "/model/endo/##" - assert( edsolve.numPools == 1 ) - - edsolve.buildMeshJunctions( dsolve ) - - plot1 = moose.Table2( '/model/plot1' ) - plot2 = moose.Table2( '/model/plot2' ) - plot3 = moose.Table2( '/model/plot3' ) - moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) - moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) - moose.connect( '/model/plot3', 'requestOut', '/model/compartment/s_xfer_endo', 'getN' ) - plot4 = moose.Table2( '/model/plot4' ) - plot5 = moose.Table2( '/model/plot5' ) - plot6 = moose.Table2( '/model/plot6' ) - moose.connect( '/model/plot4', 'requestOut', s, 'getConc' ) - moose.connect( '/model/plot5', 'requestOut', es, 'getConc' ) - moose.connect( '/model/plot6', 'requestOut', '/model/compartment/s_xfer_endo', 'getConc' ) - -def doPlot( ax, i, label ): - plot1 = '/model/plot' + str(i) - plot2 = '/model/plot' + str(i+1) - plot3 = '/model/plot' + str(i+2) - plt.ylabel( label ) - plt.xlabel( 'time(s)' ) - v1 = moose.element(plot1).vector - v2 = moose.element(plot2).vector - v3 = moose.element(plot3).vector - ax.plot( v1, label='s' ) - ax.plot( v2, 'x',label='es' ) - ax.plot( v3, label='xfer' ) - ax.plot( np.array( v1 ) + np.array( v2 ), label='sum' ) - plt.legend() - -def almostEq( a, b ): - return abs(a-b)/(a+b) < 5e-5 - -def main( standalone = False ): - runtime = 100 - makeModel() - moose.reinit() - moose.start( runtime ) - assert( almostEq( moose.element( 'model/compartment/s' ).conc, - moose.element( '/model/endo/s' ).conc ) ) - - if standalone: - fig = plt.figure( figsize=(12,10) ) - ax1 = fig.add_subplot(211) - doPlot( ax1, 1, '# of molecules' ) - ax2 = fig.add_subplot(212) - doPlot( ax2, 4, 'conc (mM)' ) - plt.show() - moose.delete( '/model' ) - -# Run the 'main' if this script is executed standalone. -if __name__ == '__main__': - main( standalone = True ) diff --git a/tests/python/testXreacs4.py b/tests/python/testXreacs4.py deleted file mode 100644 index ceb36096..00000000 --- a/tests/python/testXreacs4.py +++ /dev/null @@ -1,112 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################################### -## This program is part of 'MOOSE', the -## Messaging Object Oriented Simulation Environment. -## Copyright (C) 2014 Upinder S. Bhalla. and NCBS -## It is made available under the terms of the -## GNU Lesser General Public License version 2.1 -## See the file COPYING.LIB for the full notice. -######################################################################### - - -import math -import numpy as np -import moose -import moose.fixXreacs as fixXreacs - -def makeModel(): - # create container for model - num = 1 # number of compartments - model = moose.Neutral( '/model' ) - compartment = moose.CylMesh( '/model/compartment' ) - compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder - - # create molecules and reactions - s = moose.Pool( '/model/compartment/s' ) - rXfer = moose.Reac( '/model/compartment/rXfer' ) - ##################################################################### - # Put in endo compartment. Add molecule s - endo = moose.EndoMesh( '/model/endo' ) - endo.isMembraneBound = True - endo.surround = compartment - es = moose.Pool( '/model/endo/s' ) - ##################################################################### - moose.connect( rXfer, 'sub', s, 'reac' ) - moose.connect( rXfer, 'prd', es, 'reac' ) - volRatio = compartment.volume / endo.volume - rXfer.Kf = 0.04 # 0.04/sec - rXfer.Kb = 0.02 # 0.02/sec - - ##################################################################### - fixXreacs.fixXreacs( '/model' ) - #fixXreacs.restoreXreacs( '/model' ) - #fixXreacs.fixXreacs( '/model' ) - ##################################################################### - - # Make solvers - ksolve = moose.Ksolve( '/model/compartment/ksolve' ) - dsolve = moose.Dsolve( '/model/dsolve' ) - eksolve = moose.Ksolve( '/model/endo/ksolve' ) - edsolve = moose.Dsolve( '/model/endo/dsolve' ) - - stoich = moose.Stoich( '/model/compartment/stoich' ) - stoich.compartment = compartment - stoich.ksolve = ksolve - stoich.dsolve = dsolve - stoich.path = "/model/compartment/##" - assert( dsolve.numPools == 2 ) - s.vec.concInit = [1]*num - - estoich = moose.Stoich( '/model/endo/stoich' ) - estoich.compartment = endo - estoich.ksolve = eksolve - estoich.dsolve = edsolve - estoich.path = "/model/endo/##" - assert( edsolve.numPools == 1 ) - - edsolve.buildMeshJunctions( dsolve ) - - plot1 = moose.Table2( '/model/plot1' ) - plot2 = moose.Table2( '/model/plot2' ) - moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) - moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) - plot3 = moose.Table2( '/model/plot3' ) - plot4 = moose.Table2( '/model/plot4' ) - moose.connect( '/model/plot3', 'requestOut', s, 'getConc' ) - moose.connect( '/model/plot4', 'requestOut', es, 'getConc' ) - -def doPlot( ax, plot1, plot2, label ): - plt.ylabel( label ) - plt.xlabel( 'time(s)' ) - v1 = moose.element(plot1).vector - v2 = moose.element(plot2).vector - ax.plot( v1, label='s' ) - ax.plot( v2, label='es' ) - ax.plot( np.array( v1 ) + np.array( v2 ), label='sum' ) - plt.legend() - -def almostEq( a, b ): - return abs(a-b)/(a+b) < 5e-5 - -def main( standalone = False ): - runtime = 100 - displayInterval = 2 - makeModel() - moose.reinit() - moose.start( runtime ) - assert( almostEq( 2.0 * moose.element( 'model/compartment/s' ).conc, - moose.element( '/model/endo/s' ).conc ) ) - - if standalone: - fig = plt.figure( figsize=(12,10) ) - ax1 = fig.add_subplot(211) - doPlot( ax1, '/model/plot1', '/model/plot2', '# of molecules' ) - ax2 = fig.add_subplot(212) - doPlot( ax2, '/model/plot3', '/model/plot4', 'conc (mM)' ) - plt.show() - - moose.delete( '/model' ) - -# Run the 'main' if this script is executed standalone. -if __name__ == '__main__': - main( standalone = True ) diff --git a/tests/python/testXreacs4a.py b/tests/python/testXreacs4a.py deleted file mode 100644 index 79f98ba6..00000000 --- a/tests/python/testXreacs4a.py +++ /dev/null @@ -1,112 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################################### -## This program is part of 'MOOSE', the -## Messaging Object Oriented Simulation Environment. -## Copyright (C) 2014 Upinder S. Bhalla. and NCBS -## It is made available under the terms of the -## GNU Lesser General Public License version 2.1 -## See the file COPYING.LIB for the full notice. -######################################################################### - - -import math -import numpy as np -import moose -import moose.fixXreacs as fixXreacs - -def makeModel(): - # create container for model - num = 1 # number of compartments - model = moose.Neutral( '/model' ) - compartment = moose.CylMesh( '/model/compartment' ) - compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder - - # create molecules and reactions - s = moose.Pool( '/model/compartment/s' ) - ##################################################################### - # Put in endo compartment. Add molecule s - endo = moose.EndoMesh( '/model/endo' ) - endo.isMembraneBound = True - endo.surround = compartment - es = moose.Pool( '/model/endo/s' ) - rXfer = moose.Reac( '/model/endo/rXfer' ) - ##################################################################### - moose.connect( rXfer, 'sub', s, 'reac' ) - moose.connect( rXfer, 'prd', es, 'reac' ) - volRatio = compartment.volume / endo.volume - rXfer.Kf = 0.04 # 0.04/sec - rXfer.Kb = 0.02 # 0.02/sec - - ##################################################################### - fixXreacs.fixXreacs( '/model' ) - #fixXreacs.restoreXreacs( '/model' ) - #fixXreacs.fixXreacs( '/model' ) - ##################################################################### - - # Make solvers - ksolve = moose.Ksolve( '/model/compartment/ksolve' ) - dsolve = moose.Dsolve( '/model/dsolve' ) - eksolve = moose.Ksolve( '/model/endo/ksolve' ) - edsolve = moose.Dsolve( '/model/endo/dsolve' ) - - stoich = moose.Stoich( '/model/compartment/stoich' ) - stoich.compartment = compartment - stoich.ksolve = ksolve - stoich.dsolve = dsolve - stoich.path = "/model/compartment/##" - assert( dsolve.numPools == 1 ) - s.vec.concInit = [1]*num - - estoich = moose.Stoich( '/model/endo/stoich' ) - estoich.compartment = endo - estoich.ksolve = eksolve - estoich.dsolve = edsolve - estoich.path = "/model/endo/##" - assert( edsolve.numPools == 2 ) - - edsolve.buildMeshJunctions( dsolve ) - - plot1 = moose.Table2( '/model/plot1' ) - plot2 = moose.Table2( '/model/plot2' ) - moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) - moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) - plot3 = moose.Table2( '/model/plot3' ) - plot4 = moose.Table2( '/model/plot4' ) - moose.connect( '/model/plot3', 'requestOut', s, 'getConc' ) - moose.connect( '/model/plot4', 'requestOut', es, 'getConc' ) - -def doPlot( ax, plot1, plot2, label ): - plt.ylabel( label ) - plt.xlabel( 'time(s)' ) - v1 = moose.element(plot1).vector - v2 = moose.element(plot2).vector - ax.plot( v1, label='s' ) - ax.plot( v2, label='es' ) - ax.plot( np.array( v1 ) + np.array( v2 ), label='sum' ) - plt.legend() - -def almostEq( a, b ): - return abs(a-b)/(a+b) < 5e-5 - -def main( standalone = False ): - runtime = 200 - displayInterval = 2 - makeModel() - moose.reinit() - moose.start( runtime ) - assert( almostEq( 2.0 * moose.element( 'model/compartment/s' ).conc, - moose.element( '/model/endo/s' ).conc ) ) - - if standalone: - fig = plt.figure( figsize=(12,10) ) - ax1 = fig.add_subplot(211) - doPlot( ax1, '/model/plot1', '/model/plot2', '# of molecules' ) - ax2 = fig.add_subplot(212) - doPlot( ax2, '/model/plot3', '/model/plot4', 'conc (mM)' ) - plt.show() - moose.delete( '/model' ) - - -# Run the 'main' if this script is executed standalone. -if __name__ == '__main__': - main( standalone = True ) diff --git a/tests/python/testXreacs5.py b/tests/python/testXreacs5.py deleted file mode 100644 index f011381e..00000000 --- a/tests/python/testXreacs5.py +++ /dev/null @@ -1,118 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################################### -## This program is part of 'MOOSE', the -## Messaging Object Oriented Simulation Environment. -## Copyright (C) 2014 Upinder S. Bhalla. and NCBS -## It is made available under the terms of the -## GNU Lesser General Public License version 2.1 -## See the file COPYING.LIB for the full notice. -######################################################################### - - -import math -import numpy as np -import moose -import moose.fixXreacs as fixXreacs - -def makeModel(): - # create container for model - num = 1 # number of compartments - model = moose.Neutral( '/model' ) - compartment = moose.CylMesh( '/model/compartment' ) - compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder - - # create molecules and reactions - s = moose.Pool( '/model/compartment/s' ) - rXfer = moose.Reac( '/model/compartment/rXfer' ) - ##################################################################### - # Put in endo compartment. Add molecule s - endo = moose.EndoMesh( '/model/endo' ) - endo.isMembraneBound = True - endo.surround = compartment - es = moose.Pool( '/model/endo/s' ) - erXfer = moose.Reac( '/model/endo/erXfer' ) - ##################################################################### - moose.connect( erXfer, 'sub', es, 'reac' ) - moose.connect( erXfer, 'prd', s, 'reac' ) - moose.connect( rXfer, 'sub', s, 'reac' ) - moose.connect( rXfer, 'prd', es, 'reac' ) - rXfer.Kf = 0.04 # 0.04/sec - rXfer.Kb = 0.0 # 0.00/sec - erXfer.Kf = 0.16 # 0.16/sec - erXfer.Kb = 0.0 # 0.00/sec - - ##################################################################### - fixXreacs.fixXreacs( '/model' ) - fixXreacs.restoreXreacs( '/model' ) - fixXreacs.fixXreacs( '/model' ) - ##################################################################### - - # Make solvers - ksolve = moose.Ksolve( '/model/compartment/ksolve' ) - dsolve = moose.Dsolve( '/model/dsolve' ) - eksolve = moose.Ksolve( '/model/endo/ksolve' ) - edsolve = moose.Dsolve( '/model/endo/dsolve' ) - - stoich = moose.Stoich( '/model/compartment/stoich' ) - stoich.compartment = compartment - stoich.ksolve = ksolve - stoich.dsolve = dsolve - stoich.path = "/model/compartment/##" - assert( dsolve.numPools == 2 ) - s.vec.concInit = [1]*num - - estoich = moose.Stoich( '/model/endo/stoich' ) - estoich.compartment = endo - estoich.ksolve = eksolve - estoich.dsolve = edsolve - estoich.path = "/model/endo/##" - assert( edsolve.numPools == 2 ) - - edsolve.buildMeshJunctions( dsolve ) - - plot1 = moose.Table2( '/model/plot1' ) - plot2 = moose.Table2( '/model/plot2' ) - moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) - moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) - plot3 = moose.Table2( '/model/plot3' ) - plot4 = moose.Table2( '/model/plot4' ) - moose.connect( '/model/plot3', 'requestOut', s, 'getConc' ) - moose.connect( '/model/plot4', 'requestOut', es, 'getConc' ) - -def doPlot( ax, plot1, plot2, label ): - plt.ylabel( label ) - plt.xlabel( 'time(s)' ) - v1 = moose.element(plot1).vector - v2 = moose.element(plot2).vector - ax.plot( v1, label='s' ) - ax.plot( v2, label='es' ) - ax.plot( np.array( v1 ) + np.array( v2 ), label='sum' ) - plt.legend() - -def almostEq( a, b ): - #print a, b, (a-b)/(a+b) - return abs(a-b)/(a+b) < 5e-5 - -def main( standalone = False ): - for i in range( 10, 18): - moose.setClock( i, 0.001 ) - runtime = 100 - makeModel() - moose.reinit() - moose.start( runtime ) - - assert( almostEq( 2.0 * moose.element( 'model/compartment/s' ).conc, - moose.element( '/model/endo/s' ).conc ) ) - - if standalone: - fig = plt.figure( figsize=(12,10) ) - ax1 = fig.add_subplot(211) - doPlot( ax1, '/model/plot1', '/model/plot2', '# of molecules' ) - ax2 = fig.add_subplot(212) - doPlot( ax2, '/model/plot3', '/model/plot4', 'conc (mM)' ) - plt.show() - moose.delete( '/model' ) - -# Run the 'main' if this script is executed standalone. -if __name__ == '__main__': - main( standalone = True ) diff --git a/tests/python/testXreacs5a.py b/tests/python/testXreacs5a.py deleted file mode 100644 index 45e32743..00000000 --- a/tests/python/testXreacs5a.py +++ /dev/null @@ -1,118 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################################### -## This program is part of 'MOOSE', the -## Messaging Object Oriented Simulation Environment. -## Copyright (C) 2014 Upinder S. Bhalla. and NCBS -## It is made available under the terms of the -## GNU Lesser General Public License version 2.1 -## See the file COPYING.LIB for the full notice. -######################################################################### - - -import math -import numpy as np -import moose -import moose.fixXreacs as fixXreacs - -def makeModel(): - # create container for model - num = 1 # number of compartments - model = moose.Neutral( '/model' ) - compartment = moose.CylMesh( '/model/compartment' ) - compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder - - # create molecules and reactions - s = moose.Pool( '/model/compartment/s' ) - rXfer = moose.Reac( '/model/compartment/rXfer' ) - ##################################################################### - # Put in endo compartment. Add molecule s - endo = moose.EndoMesh( '/model/endo' ) - endo.isMembraneBound = True - endo.surround = compartment - es = moose.Pool( '/model/endo/s' ) - erXfer = moose.Reac( '/model/compartment/erXfer' ) - ##################################################################### - moose.connect( erXfer, 'sub', es, 'reac' ) - moose.connect( erXfer, 'prd', s, 'reac' ) - moose.connect( rXfer, 'sub', s, 'reac' ) - moose.connect( rXfer, 'prd', es, 'reac' ) - rXfer.Kf = 0.04 # 0.04/sec - rXfer.Kb = 0.0 # 0.02/sec - erXfer.Kf = 0.02 # 0.04/sec - erXfer.Kb = 0.0 # 0.02/sec - - ##################################################################### - fixXreacs.fixXreacs( '/model' ) - fixXreacs.restoreXreacs( '/model' ) - fixXreacs.fixXreacs( '/model' ) - ##################################################################### - rx = moose.element( '/model/compartment/rXfer' ) - erx = moose.element( '/model/compartment/erXfer' ) - - # Make solvers - ksolve = moose.Ksolve( '/model/compartment/ksolve' ) - dsolve = moose.Dsolve( '/model/dsolve' ) - eksolve = moose.Ksolve( '/model/endo/ksolve' ) - edsolve = moose.Dsolve( '/model/endo/dsolve' ) - - stoich = moose.Stoich( '/model/compartment/stoich' ) - stoich.compartment = compartment - stoich.ksolve = ksolve - stoich.dsolve = dsolve - stoich.path = "/model/compartment/##" - assert( dsolve.numPools == 2 ) - s.vec.concInit = [1]*num - - estoich = moose.Stoich( '/model/endo/stoich' ) - estoich.compartment = endo - estoich.ksolve = eksolve - estoich.dsolve = edsolve - estoich.path = "/model/endo/##" - assert( edsolve.numPools == 1 ) - - edsolve.buildMeshJunctions( dsolve ) - - plot1 = moose.Table2( '/model/plot1' ) - plot2 = moose.Table2( '/model/plot2' ) - moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) - moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) - plot3 = moose.Table2( '/model/plot3' ) - plot4 = moose.Table2( '/model/plot4' ) - moose.connect( '/model/plot3', 'requestOut', s, 'getConc' ) - moose.connect( '/model/plot4', 'requestOut', es, 'getConc' ) - -def doPlot( ax, plot1, plot2, label ): - plt.ylabel( label ) - plt.xlabel( 'time(s)' ) - v1 = moose.element(plot1).vector - v2 = moose.element(plot2).vector - ax.plot( v1, label='s' ) - ax.plot( v2, label='es' ) - ax.plot( np.array( v1 ) + np.array( v2 ), label='sum' ) - plt.legend() - -def almostEq( a, b ): - return abs(a-b)/(a+b) < 5e-5 - -def main( standalone = False ): - runtime = 200 - displayInterval = 2 - makeModel() - moose.reinit() - moose.start( runtime ) - - assert( almostEq( 2.0 * moose.element( 'model/compartment/s' ).n, - moose.element( '/model/endo/s' ).n ) ) - - if standalone: - fig = plt.figure( figsize=(12,10) ) - ax1 = fig.add_subplot(211) - doPlot( ax1, '/model/plot1', '/model/plot2', '# of molecules' ) - ax2 = fig.add_subplot(212) - doPlot( ax2, '/model/plot3', '/model/plot4', 'conc (mM)' ) - plt.show() - moose.delete( '/model' ) - -# Run the 'main' if this script is executed standalone. -if __name__ == '__main__': - main( standalone = True ) diff --git a/tests/python/testXreacs6.py b/tests/python/testXreacs6.py deleted file mode 100644 index e491253d..00000000 --- a/tests/python/testXreacs6.py +++ /dev/null @@ -1,118 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################################### -## This program is part of 'MOOSE', the -## Messaging Object Oriented Simulation Environment. -## Copyright (C) 2018 Upinder S. Bhalla. and NCBS -## It is made available under the terms of the -## GNU General Public License version 3 or later. -## See the file COPYING.LIB for the full notice. -######################################################################### - - -import math -import numpy as np -import moose -import moose.fixXreacs as fixXreacs - -def makeModel(): - # create container for model - num = 1 # number of compartments - model = moose.Neutral( '/model' ) - compartment = moose.CylMesh( '/model/compartment' ) - compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder - - # create molecules and reactions - s = moose.Pool( '/model/compartment/s' ) - t = moose.Pool( '/model/compartment/t' ) - rXfer = moose.Reac( '/model/compartment/rXfer' ) - ##################################################################### - # Put in endo compartment. Add molecule s - endo = moose.EndoMesh( '/model/endo' ) - endo.isMembraneBound = True - endo.surround = compartment - es = moose.Pool( '/model/endo/s' ) - et = moose.Pool( '/model/endo/t' ) - ##################################################################### - moose.connect( rXfer, 'sub', s, 'reac' ) - moose.connect( rXfer, 'sub', t, 'reac' ) - moose.connect( rXfer, 'prd', es, 'reac' ) - moose.connect( rXfer, 'prd', et, 'reac' ) - rXfer.Kf = 0.02 # 0.02/mM/sec - rXfer.Kb = 0.02 # 0.02/mM/sec - - ##################################################################### - fixXreacs.fixXreacs( '/model' ) - #fixXreacs.restoreXreacs( '/model' ) - #fixXreacs.fixXreacs( '/model' ) - ##################################################################### - # Make solvers - ksolve = moose.Ksolve( '/model/compartment/ksolve' ) - dsolve = moose.Dsolve( '/model/dsolve' ) - eksolve = moose.Ksolve( '/model/endo/ksolve' ) - edsolve = moose.Dsolve( '/model/endo/dsolve' ) - - stoich = moose.Stoich( '/model/compartment/stoich' ) - stoich.compartment = compartment - stoich.ksolve = ksolve - stoich.dsolve = dsolve - stoich.path = "/model/compartment/##" - assert( dsolve.numPools == 4 ) - s.vec.concInit = [1]*num - t.vec.concInit = [1]*num - - estoich = moose.Stoich( '/model/endo/stoich' ) - estoich.compartment = endo - estoich.ksolve = eksolve - estoich.dsolve = edsolve - estoich.path = "/model/endo/##" - assert( edsolve.numPools == 2 ) - - edsolve.buildMeshJunctions( dsolve ) - - plot1 = moose.Table2( '/model/plot1' ) - plot2 = moose.Table2( '/model/plot2' ) - moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) - moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) - plot3 = moose.Table2( '/model/plot3' ) - plot4 = moose.Table2( '/model/plot4' ) - moose.connect( '/model/plot3', 'requestOut', s, 'getConc' ) - moose.connect( '/model/plot4', 'requestOut', es, 'getConc' ) - -def doPlot( ax, plot1, plot2, label ): - plt.ylabel( label ) - plt.xlabel( 'time(s)' ) - v1 = moose.element(plot1).vector - v2 = moose.element(plot2).vector - ax.plot( v1, label='s' ) - ax.plot( v2, label='es' ) - ax.plot( np.array( v1 ) + np.array( v2 ), label='sum' ) - plt.legend() - -def almostEq( a, b ): - #print a, b, (a-b)/(a+b) - return abs(a-b)/(a+b) < 5e-5 - -def main( standalone = False ): - for i in range( 10, 18): - moose.setClock( i, 0.01 ) - runtime = 100 - displayInterval = 2 - makeModel() - moose.reinit() - moose.start( runtime ) - - assert( almostEq( moose.element( 'model/compartment/s' ).conc, - moose.element( '/model/endo/s' ).conc ) ) - - if standalone: - fig = plt.figure( figsize=(12,10) ) - ax1 = fig.add_subplot(211) - doPlot( ax1, '/model/plot1', '/model/plot2', '# of molecules' ) - ax2 = fig.add_subplot(212) - doPlot( ax2, '/model/plot3', '/model/plot4', 'conc (mM)' ) - plt.show() - moose.delete( '/model' ) - -# Run the 'main' if this script is executed standalone. -if __name__ == '__main__': - main( standalone = True ) diff --git a/tests/python/testXreacs7.py b/tests/python/testXreacs7.py deleted file mode 100644 index bb7d79a1..00000000 --- a/tests/python/testXreacs7.py +++ /dev/null @@ -1,135 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################################### -## This program is part of 'MOOSE', the -## Messaging Object Oriented Simulation Environment. -## Copyright (C) 2018 Upinder S. Bhalla. and NCBS -## It is made available under the terms of the -## GNU General Public License version 3 or later. -## See the file COPYING.LIB for the full notice. -## -## This file makes u + t <=====> s where u is in a different compt from t,s -######################################################################### - - -import math -import numpy as np -import moose -import moose.fixXreacs as fixXreacs - -def makeModel(): - # create container for model - num = 1 # number of compartments - model = moose.Neutral( '/model' ) - compartment = moose.CylMesh( '/model/compartment' ) - compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder - - # create molecules and reactions - u = moose.Pool( '/model/compartment/u' ) - ##################################################################### - # Put in endo compartment. Add molecule s - endo = moose.EndoMesh( '/model/endo' ) - endo.isMembraneBound = True - endo.surround = compartment - rXfer = moose.Reac( '/model/endo/rXfer' ) - et = moose.Pool( '/model/endo/t' ) - es = moose.Pool( '/model/endo/s' ) - ##################################################################### - moose.connect( rXfer, 'sub', u, 'reac' ) - moose.connect( rXfer, 'sub', et, 'reac' ) - moose.connect( rXfer, 'prd', es, 'reac' ) - u.concInit = 1.0 - et.concInit = 1.0 - - ##################################################################### - # [u0] = 1 in compt, [t0] = 1 in endo, [s0] = 0 - # [u] + [s]/8 = [u0] ; [t] + [s] = [t0]; nu + ns = nu0, nt + ns = nt0 - # At equil, numKf*nu*nt = numKb*ns - # Express all # in terms of ns. - # nu = nu0-ns; nt = nt0-ns Also, nu0 = 8*nt0 - # So numKf*(nu0-ns)*(nt0-ns) = numKb*ns - # Target level is nt = ns = nt0/2 - # So numKf*( 8nt0 - nt0/2)*nt0/2 = numKb*nt0/2 - # So 7.5*nt0 = numKb/numKf - rXfer.numKb = 0.1 - rXfer.numKf = 0.1/(7.5 * et.nInit) - #print( "Rates = {}, {}".format( rXfer.Kf, rXfer.Kb )) - ##################################################################### - fixXreacs.fixXreacs( '/model' ) - #fixXreacs.restoreXreacs( '/model' ) - #fixXreacs.fixXreacs( '/model' ) - ##################################################################### - - # Make solvers - ksolve = moose.Ksolve( '/model/compartment/ksolve' ) - dsolve = moose.Dsolve( '/model/compartment/dsolve' ) - eksolve = moose.Ksolve( '/model/endo/ksolve' ) - edsolve = moose.Dsolve( '/model/endo/dsolve' ) - - stoich = moose.Stoich( '/model/compartment/stoich' ) - stoich.compartment = compartment - stoich.ksolve = ksolve - stoich.dsolve = dsolve - stoich.path = "/model/compartment/##" - assert( dsolve.numPools == 1 ) - - estoich = moose.Stoich( '/model/endo/stoich' ) - estoich.compartment = endo - estoich.ksolve = eksolve - estoich.dsolve = edsolve - estoich.path = "/model/endo/##" - assert( edsolve.numPools == 3 ) - - edsolve.buildMeshJunctions( dsolve ) - - plot1 = moose.Table2( '/model/plot1' ) - plot2 = moose.Table2( '/model/plot2' ) - plot3 = moose.Table2( '/model/plot3' ) - moose.connect( '/model/plot1', 'requestOut', u, 'getN' ) - moose.connect( '/model/plot2', 'requestOut', et, 'getN' ) - moose.connect( '/model/plot3', 'requestOut', es, 'getN' ) - plot4 = moose.Table2( '/model/plot4' ) - plot5 = moose.Table2( '/model/plot5' ) - plot6 = moose.Table2( '/model/plot6' ) - moose.connect( '/model/plot4', 'requestOut', u, 'getConc' ) - moose.connect( '/model/plot5', 'requestOut', et, 'getConc' ) - moose.connect( '/model/plot6', 'requestOut', es, 'getConc' ) - -def doPlot( ax, i, label ): - plt.ylabel( label ) - plt.xlabel( 'time(s)' ) - v1 = moose.element('/model/plot' + str(i)).vector - v2 = moose.element('/model/plot' + str(i+1)).vector - v3 = moose.element('/model/plot' + str(i+2)).vector - ax.plot( v1, label='u' ) - ax.plot( v2, label='et' ) - ax.plot( v3, label='es' ) - ax.plot( np.array( v1 ) + np.array( v3 ), label='sum' ) - plt.legend() - -def almostEq( a, b ): - #print a, b, (a-b)/(a+b) - return abs(a-b)/(a+b) < 5e-5 - -def main( standalone = False ): - runtime = 100 - displayInterval = 2 - makeModel() - moose.reinit() - moose.start( runtime ) - - assert( almostEq( moose.element( 'model/endo/t' ).conc, - moose.element( '/model/endo/s' ).conc ) ) - - if standalone: - fig = plt.figure( figsize=(12,10) ) - ax1 = fig.add_subplot(211) - doPlot( ax1, 1, '# of molecules' ) - ax2 = fig.add_subplot(212) - doPlot( ax2, 4, 'conc (mM)' ) - plt.show() - - moose.delete( '/model' ) - -# Run the 'main' if this script is executed standalone. -if __name__ == '__main__': - main( standalone = True ) diff --git a/tests/python/testXreacs8.py b/tests/python/testXreacs8.py deleted file mode 100644 index bf5d28ed..00000000 --- a/tests/python/testXreacs8.py +++ /dev/null @@ -1,132 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################################### -## This program is part of 'MOOSE', the -## Messaging Object Oriented Simulation Environment. -## Copyright (C) 2014 Upinder S. Bhalla. and NCBS -## It is made available under the terms of the -## GNU Lesser General Public License version 2.1 -## See the file COPYING.LIB for the full notice. -## Here we set up equal Kf and Kb in a reversible reaction across a -## 1-voxel cyl compt and an internal endoMesh, having a smaller volume. -## \ -## COMPT: 2 s <===> / 2 s :ENDO -## \ -## -## This becomes: -## \ -## COMPT: 2 s <===> 2 s_xfer_endo / 2s :ENDO -## \ -## -######################################################################### - - -import math -import numpy as np -import moose -import moose.fixXreacs as fixXreacs - -def makeModel(): - # create container for model - num = 1 # number of compartments - model = moose.Neutral( '/model' ) - compartment = moose.CylMesh( '/model/compartment' ) - compartment.x1 = 1.0e-6 # Set it to a 1 micron single-voxel cylinder - - # create molecules and reactions - s = moose.Pool( '/model/compartment/s' ) - rXfer = moose.Reac( '/model/compartment/rXfer' ) - ##################################################################### - # Put in endo compartment. Add molecule s - endo = moose.EndoMesh( '/model/endo' ) - endo.isMembraneBound = True - endo.surround = compartment - es = moose.Pool( '/model/endo/s' ) - ##################################################################### - moose.connect( rXfer, 'sub', s, 'reac' ) - moose.connect( rXfer, 'sub', s, 'reac' ) - moose.connect( rXfer, 'prd', es, 'reac' ) - moose.connect( rXfer, 'prd', es, 'reac' ) - rXfer.Kf = 0.01 # 0.01/sec - rXfer.Kb = 0.01 # 0.01/sec - - ##################################################################### - fixXreacs.fixXreacs( '/model' ) - fixXreacs.restoreXreacs( '/model' ) - fixXreacs.fixXreacs( '/model' ) - ##################################################################### - - # Make solvers - ksolve = moose.Ksolve( '/model/compartment/ksolve' ) - dsolve = moose.Dsolve( '/model/dsolve' ) - eksolve = moose.Ksolve( '/model/endo/ksolve' ) - edsolve = moose.Dsolve( '/model/endo/dsolve' ) - - stoich = moose.Stoich( '/model/compartment/stoich' ) - stoich.compartment = compartment - stoich.ksolve = ksolve - stoich.dsolve = dsolve - stoich.path = "/model/compartment/##" - assert( dsolve.numPools == 2 ) - s.vec.concInit = [1]*num - - estoich = moose.Stoich( '/model/endo/stoich' ) - estoich.compartment = endo - estoich.ksolve = eksolve - estoich.dsolve = edsolve - estoich.path = "/model/endo/##" - assert( edsolve.numPools == 1 ) - - edsolve.buildMeshJunctions( dsolve ) - - plot1 = moose.Table2( '/model/plot1' ) - plot2 = moose.Table2( '/model/plot2' ) - plot3 = moose.Table2( '/model/plot3' ) - moose.connect( '/model/plot1', 'requestOut', s, 'getN' ) - moose.connect( '/model/plot2', 'requestOut', es, 'getN' ) - moose.connect( '/model/plot3', 'requestOut', '/model/compartment/s_xfer_endo', 'getN' ) - plot4 = moose.Table2( '/model/plot4' ) - plot5 = moose.Table2( '/model/plot5' ) - plot6 = moose.Table2( '/model/plot6' ) - moose.connect( '/model/plot4', 'requestOut', s, 'getConc' ) - moose.connect( '/model/plot5', 'requestOut', es, 'getConc' ) - moose.connect( '/model/plot6', 'requestOut', '/model/compartment/s_xfer_endo', 'getConc' ) - -def doPlot( ax, i, label ): - plot1 = '/model/plot' + str(i) - plot2 = '/model/plot' + str(i+1) - plot3 = '/model/plot' + str(i+2) - plt.ylabel( label ) - plt.xlabel( 'time(s)' ) - v1 = moose.element(plot1).vector - v2 = moose.element(plot2).vector - v3 = moose.element(plot3).vector - ax.plot( v1, label='s' ) - ax.plot( v2, 'x',label='es' ) - ax.plot( v3, label='xfer' ) - ax.plot( np.array( v1 ) + np.array( v2 ), label='sum' ) - plt.legend() - -def almostEq( a, b ): - return abs(a-b)/(a+b) < 5e-5 - -def main( standalone = False ): - runtime = 100 - makeModel() - moose.reinit() - moose.start( runtime ) - assert( almostEq( moose.element( 'model/compartment/s' ).conc, - moose.element( '/model/endo/s' ).conc ) ) - - if standalone: - fig = plt.figure( figsize=(12,10) ) - ax1 = fig.add_subplot(211) - doPlot( ax1, 1, '# of molecules' ) - ax2 = fig.add_subplot(212) - doPlot( ax2, 4, 'conc (mM)' ) - plt.show() - moose.delete( '/model' ) - - -# Run the 'main' if this script is executed standalone. -if __name__ == '__main__': - main( standalone = True ) diff --git a/tests/python/test_accessing_existing_paths.py b/tests/python/test_accessing_existing_paths.py deleted file mode 100644 index 769c9a33..00000000 --- a/tests/python/test_accessing_existing_paths.py +++ /dev/null @@ -1,41 +0,0 @@ -# -*- coding: utf-8 -*- -import moose -import re - -def fixPath(path): - path = re.sub(r'/+', '/', path) - return path - -paths = [ '/a' - , '//a' - , '/a/b' - , '/a/b/' - , '//a//b/////' - , '/a/./b' - , '///a/././b' - ] -expectedPath = [fixPath(p) for p in paths] - -expectedChanges = zip(paths, expectedPath) - -for p in expectedPath: - print( 'Accessing %s' % p ) - try: - moose.Neutral(p) - except Exception as e: - print( 'Same path access by element' ) - moose.element( p ) - -foundPath = [] -for p in moose.wildcardFind('/##'): - if "/a" in p.path: - foundPath.append(p.path) - -testFailed = False -for f in foundPath: - f = re.sub(r'\[\d+\]', '', f) - if f not in expectedPath: - testFailed = True - -if testFailed: - print("Test failed on paths") diff --git a/tests/python/test_all.sh b/tests/python/test_all.sh deleted file mode 100755 index 4b10beab..00000000 --- a/tests/python/test_all.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -test_scripts="./test_function.py - test_function.py - test_moose_paths.py - test_mumbl.py - test_pymoose.py - test_synchan.py - test_vec.py - test_difshells.py" - -for testFile in $test_scripts; do - echo "Executing $testFile" - python $testFile | tee test_all.sh.log -done diff --git a/tests/python/test_function_derivative.py b/tests/python/test_function_derivative.py deleted file mode 100644 index c2e1dc81..00000000 --- a/tests/python/test_function_derivative.py +++ /dev/null @@ -1,160 +0,0 @@ -# function.py --- - -import numpy as np -import sys -import moose - -simtime = 1.0 -plot_ = False -if plot_: - import matplotlib.pyplot as plt - -def example(): - """Function objects can be used to evaluate expressions with arbitrary - number of variables and constants. We can assign expression of the - form:: - - f(c0, c1, ..., cM, x0, x1, ..., xN, y0,..., yP ) - - where `c_i`'s are constants and `x_i`'s and `y_i`'s are variables. - - The constants must be defined before setting the expression and - variables are connected via messages. The constants can have any - name, but the variable names must be of the form x{i} or y{i} - where i is increasing integer starting from 0. - - The `x_i`'s are field elements and you have to set their number - first (function.x.num = N). Then you can connect any source field - sending out double to the 'input' destination field of the - `x[i]`. - - The `y_i`'s are useful when the required variable is a value field - and is not available as a source field. In that case you connect - the `requestOut` source field of the function element to the - `get{Field}` destination field on the target element. The `y_i`'s - are automatically added on connecting. Thus, if you call:: - - moose.connect(function, 'requestOut', a, 'getSomeField') - moose.connect(function, 'requestOut', b, 'getSomeField') - - then ``a.someField`` will be assigned to ``y0`` and - ``b.someField`` will be assigned to ``y1``. - - In this example we evaluate the expression: ``z = c0 * exp(c1 * - x0) * cos(y0)`` - - with x0 ranging from -1 to +1 and y0 ranging from -pi to - +pi. These values are stored in two stimulus tables called xtab - and ytab respectively, so that at each timestep the next values of - x0 and y0 are assigned to the function. - - Along with the value of the expression itself we also compute its - derivative with respect to y0 and its derivative with respect to - time (rate). The former uses a five-point stencil for the - numerical differentiation and has a glitch at y=0. The latter uses - backward difference divided by dt. - - Unlike Func class, the number of variables and constants are - unlimited in Function and you can set all the variables via - messages. - - """ - demo = moose.Neutral('/model') - function = moose.Function('/model/function') - function.c['c0'] = 1.0 - function.c['c1'] = 2.0 - function.x.num = 1 - function.expr = 'c0 * exp(c1*x0) * cos(y0) + sin(t)' - # mode 0 - evaluate function value, derivative and rate - # mode 1 - just evaluate function value, - # mode 2 - evaluate derivative, - # mode 3 - evaluate rate - function.mode = 0 - function.independent = 'y0' - nsteps = 1000 - xarr = np.linspace(0.0, 1.0, nsteps) - # Stimulus tables allow you to store sequences of numbers which - # are delivered via the 'output' message at each time step. This - # is a placeholder and in real scenario you will be using any - # sourceFinfo that sends out a double value. - input_x = moose.StimulusTable('/xtab') - input_x.vector = xarr - input_x.startTime = 0.0 - input_x.stepPosition = xarr[0] - input_x.stopTime = simtime - moose.connect(input_x, 'output', function.x[0], 'input') - - yarr = np.linspace(-np.pi, np.pi, nsteps) - input_y = moose.StimulusTable('/ytab') - input_y.vector = yarr - input_y.startTime = 0.0 - input_y.stepPosition = yarr[0] - input_y.stopTime = simtime - moose.connect(function, 'requestOut', input_y, 'getOutputValue') - - # data recording - result = moose.Table('/ztab') - moose.connect(result, 'requestOut', function, 'getValue') - derivative = moose.Table('/zprime') - moose.connect(derivative, 'requestOut', function, 'getDerivative') - rate = moose.Table('/dz_by_dt') - moose.connect(rate, 'requestOut', function, 'getRate') - x_rec = moose.Table('/xrec') - moose.connect(x_rec, 'requestOut', input_x, 'getOutputValue') - y_rec = moose.Table('/yrec') - moose.connect(y_rec, 'requestOut', input_y, 'getOutputValue') - - dt = simtime/nsteps - for ii in range(32): - moose.setClock(ii, dt) - moose.reinit() - moose.start(simtime) - - # Uncomment the following lines and the import matplotlib.pyplot as plt on top - # of this file to display the plot. - if plot_: - plt.plot(x_rec.vector, result.vector, 'r-', label='z = {}'.format(function.expr)) - plt.subplot(4,1,1) - z = function.c['c0'] * np.exp(function.c['c1'] * xarr) * np.cos(yarr) + np.sin(np.arange(len(xarr)) * dt) - zz = result.vector[1:] - err = z[1:] - zz[1:] - assert (np.abs(err) <= 0.05).all(), err[err > 0.05] - assert (np.mean(err) <= 0.001), np.mean(err) - - if plot_: - plt.plot(xarr, z, 'b--', label='numpy computed') - plt.xlabel('x') - plt.ylabel('z') - plt.legend() - - if plot_: - plt.subplot(4,1,2) - plt.plot(y_rec.vector, derivative.vector, 'r-', label='dz/dy0') - # derivatives computed by putting x values in the analytical formula - dzdy = function.c['c0'] * np.exp(function.c['c1'] * xarr) * (- np.sin(yarr)) - err = np.abs(dzdy - derivative.vector[1:]) - assert (err < 0.05).all(), (err[err>1e-2]) - assert (np.mean(err) < 1e-2), np.mean(err) - - if plot_: - plt.plot(yarr, dzdy, 'b--', label='numpy computed') - plt.xlabel('y') - plt.ylabel('dz/dy') - plt.legend() - - if plot_: - plt.subplot(4,1,3) - # *** BEWARE *** The first two entries are spurious. Entry 0 is - # *** from reinit sending out the defaults. Entry 2 is because - # *** there is no lastValue for computing real forward difference. - plt.plot(np.arange(2, len(rate.vector), 1) * dt, rate.vector[2:], 'r-', label='dz/dt') - dzdt = np.diff(z)/dt - plt.plot(np.arange(0, len(dzdt), 1.0) * dt, dzdt, 'b--', label='numpy computed') - plt.xlabel('t') - plt.ylabel('dz/dt') - plt.legend() - plt.tight_layout() - plt.show() - -if __name__ == '__main__': - example() diff --git a/tests/python/test_import.py b/tests/python/test_import.py deleted file mode 100644 index ec0913fb..00000000 --- a/tests/python/test_import.py +++ /dev/null @@ -1,8 +0,0 @@ -# -*- coding: utf-8 -*- -# Script to test all import modules. - -import moose -from moose.genesis import * -from moose.SBML import * -import moose.chemMerge -import moose.utils as mu diff --git a/tests/python/test_kkit.py b/tests/python/test_kkit.py deleted file mode 100644 index e4b0336b..00000000 --- a/tests/python/test_kkit.py +++ /dev/null @@ -1,57 +0,0 @@ -# -*- coding: utf-8 -*- -import numpy -import sys -import os -import moose - -scriptdir = os.path.dirname( os.path.realpath( __file__ ) ) -print( 'Script dir %s' % scriptdir ) - -def main(): - """ This example illustrates loading, running, and saving a kinetic model - defined in kkit format. It uses a default kkit model but you can specify another using the command line ``python filename runtime solver``. We use the gsl solver here. The model already defines a couple of plots and sets the runtime to 20 seconds. - """ - solver = "gsl" # Pick any of gsl, gssa, ee.. - mfile = os.path.join( scriptdir, 'genesis/kkit_objects_example.g' ) - runtime = 20.0 - if ( len( sys.argv ) >= 3 ): - if sys.argv[1][0] == '/': - mfile = sys.argv[1] - else: - mfile = './genesis/' + sys.argv[1] - runtime = float( sys.argv[2] ) - if ( len( sys.argv ) == 4 ): - solver = sys.argv[3] - modelId = moose.loadModel( mfile, 'model') - moose.mooseAddChemSolver('model',solver) - - # Increase volume so that the stochastic solver gssa - # gives an interesting output - #compt = moose.element( '/model/kinetics' ) - #compt.volume = 1e-19 - - moose.reinit() - moose.start( runtime ) - - # Report parameters - ''' - for x in moose.wildcardFind( '/model/kinetics/##[ISA=PoolBase]' ): - print x.name, x.nInit, x.concInit - for x in moose.wildcardFind( '/model/kinetics/##[ISA=ReacBase]' ): - print x.name, 'num: (', x.numKf, ', ', x.numKb, '), conc: (', x.Kf, ', ', x.Kb, ')' - for x in moose.wildcardFind('/model/kinetics/##[ISA=EnzBase]'): - print x.name, '(', x.Km, ', ', x.numKm, ', ', x.kcat, ')' - ''' - - # Display all plots. - for x in moose.wildcardFind( '/model/#graphs/conc#/#' ): - t = numpy.arange( 0, x.vector.size, 1 ) * x.dt - - vals = x.vector - stats = [ vals.min(), vals.max( ), vals.mean(), vals.std( ) ] - expected = [ 0.0, 0.00040464 , 0.0001444 , 0.00013177 ] - assert numpy.allclose(stats, expected, rtol=1e-4) , 'Got %s expected %s' % (stats, expected ) - -# Run the 'main' if this script is executed standalone. -if __name__ == '__main__': - main() diff --git a/tests/python/test_ksolve.py b/tests/python/test_ksolve.py deleted file mode 100644 index 4edabc93..00000000 --- a/tests/python/test_ksolve.py +++ /dev/null @@ -1,54 +0,0 @@ -# -*- coding: utf-8 -*- -import sys -import numpy as np -import time -import moose - -print('Using moose from %s' % moose.__file__ ) - -compt = moose.CubeMesh( '/compt' ) -compt.volume = 1e-20 - -pools = [] -for r in range( 10 ): - a1 = moose.Pool( '/compt/a1%s' % r ) - a1.concInit = 10 - a2 = moose.Pool( '/compt/a2%s' % r ) - a2.concInit = 5 - b1 = moose.Pool( '/compt/b1%s' % r ) - b1.concInit = 0.054 - b2 = moose.Pool( '/compt/b2%s' % r ) - b2.concInit = 3.9 - r = moose.Reac( '/compt/reac%s'% r ) - moose.connect( r, 'sub', a1, 'reac' ) - moose.connect( r, 'sub', a2, 'reac' ) - moose.connect( r, 'prd', b1, 'reac' ) - moose.connect( r, 'prd', b2, 'reac' ) - r.Kf = 2.9 - r.Kb = 4.5 - pools += [ a1, a2, b1, b2 ] - -ksolve = moose.Ksolve( '/compt/ksolve' ) -stoich = moose.Stoich( '/compt/stoich' ) -stoich.compartment = compt -stoich.ksolve = ksolve -ksolve.numThreads = 2 -stoich.path = '/compt/##' -moose.reinit() -print( '[INFO] Using method = %s' % ksolve.method ) -t1 = time.time() -moose.start( 10 ) -print('[INFO] Time taken %s' % (time.time() - t1 )) -expected = [ 7.77859 , 2.77858 , 2.27541 , 6.12141 , 7.77858 , 2.77858 - , 2.27541 , 6.12141 , 7.77858 , 2.77858 , 2.27541 , 6.12141 , 7.77858 - , 2.77858 , 2.27541 , 6.12141 , 7.77858 , 2.77858 , 2.27541 , 6.12141 - , 7.77858 , 2.77858 , 2.27541 , 6.12141 , 7.77858 , 2.77858 , 2.27541 - , 6.12141 , 7.77858 , 2.77858 , 2.27541 , 6.12141 , 7.77858 , 2.77858 - , 2.27541 , 6.12141 , 7.77858 , 2.77858 , 2.27541 , 6.12141 - ] -concs = [ p.conc for p in pools ] -if(not np.isclose( concs, expected ).all() ): - print( " Expected %s" % expected ) - print( " Got %s" % concs ) - quit(1) -print( 'Test passed' ) diff --git a/tests/python/test_moose_paths.py b/tests/python/test_moose_paths.py deleted file mode 100644 index 7992d0c0..00000000 --- a/tests/python/test_moose_paths.py +++ /dev/null @@ -1,36 +0,0 @@ -# -*- coding: utf-8 -*- -import moose -import re - -def fixPath(path): - path = re.sub(r'/+', '/', path) - return path - -paths = [ '/a' - , '//a' - , '/a/b' - , '/a/b/' - , '//a//b/////' - , '/a/./b' - , '///a/././b' - ] -expectedPath = set([fixPath(p) for p in paths]) - -expectedChanges = zip(paths, expectedPath) - -for p in paths: - moose.Neutral(p) - -foundPath = [] -for p in moose.wildcardFind('/##'): - if "/a" in p.path: - foundPath.append(p.path) - -testFailed = False -for f in foundPath: - f = re.sub(r'\[\d+\]', '', f) - if f not in expectedPath: - testFailed = True - -if testFailed: - print("Test failed on paths") diff --git a/tests/python/test_muparser.py b/tests/python/test_muparser.py deleted file mode 100644 index 26480932..00000000 --- a/tests/python/test_muparser.py +++ /dev/null @@ -1,162 +0,0 @@ -# -*- coding: utf-8 -*- -"""test_muparser.py: -Modified from https://elifesciences.org/articles/25827 , Fig4.py -""" -import sys -import os -import numpy as np -import sys -import numpy as np -import moose -import abstrModelEqns9 as ame -import rdesigneur as rd - - -def singleCompt( name, params ): - mod = moose.copy( '/library/' + name + '/' + name, '/model' ) - A = moose.element( mod.path + '/A' ) - Z = moose.element( mod.path + '/Z' ) - Z.nInit = 1 - Ca = moose.element( mod.path + '/Ca' ) - CaStim = moose.element( Ca.path + '/CaStim' ) - runtime = params['preStimTime'] + params['postStimTime'] - steptime = 50 - - CaStim.expr += ' + x2 * (t > 100+' + str( runtime ) + ' ) * ( t < 100+' + str( runtime + steptime ) + ' )' - print(CaStim.expr) - tab = moose.Table2( '/model/' + name + '/Atab' ) - ampl = moose.element( mod.path + '/ampl' ) - phase = moose.element( mod.path + '/phase' ) - moose.connect( tab, 'requestOut', A, 'getN' ) - ampl.nInit = params['stimAmplitude'] * 1 - phase.nInit = params['preStimTime'] - - ksolve = moose.Ksolve( mod.path + '/ksolve' ) - stoich = moose.Stoich( mod.path + '/stoich' ) - stoich.compartment = mod - stoich.ksolve = ksolve - stoich.path = mod.path + '/##' - - moose.reinit() - runtime += 100 + steptime*2 - moose.start( runtime ) - t = np.arange( 0, runtime + 1e-9, tab.dt ) - return name, t, tab.vector - - -def plotPanelC(): - panelC = [] - panelCticks = [] - panelC.append( singleCompt( 'negFB', ame.makeNegFB( [] ) ) ) - panelC.append( singleCompt( 'negFF', ame.makeNegFF( [] ) ) ) - panelC.append( singleCompt( 'fhn', ame.makeFHN( [] ) ) ) - panelC.append( singleCompt( 'bis', ame.makeBis( [] ) ) ) - - panelCticks.append( np.arange( 0, 15.00001, 5 ) ) - panelCticks.append( np.arange( 0, 1.50001, 0.5 ) ) - panelCticks.append( np.arange( 0, 5.00002, 1 ) ) - panelCticks.append( np.arange( 0, 5.00002, 1 ) ) - moose.delete( '/model' ) - for i in zip( panelC, panelCticks, list(range( len( panelC ))) ): - plotPos = i[2] + 5 - doty = i[1][-1] * 0.95 - print('doty', doty ) - -def runPanelDEFG( name, dist, seqDt, numSpine, seq, stimAmpl ): - preStim = 10.0 - blanks = 20 - rdes = rd.rdesigneur( - useGssa = False, - turnOffElec = True, - chemPlotDt = 0.1, - diffusionLength = 1e-6, - cellProto = [['cell', 'soma']], - chemProto = [['dend', name]], - chemDistrib = [['dend', 'soma', 'install', '1' ]], - plotList = [['soma', '1', 'dend' + '/A', 'n', '# of A']], - ) - rdes.buildModel() - A = moose.vec( '/model/chem/dend/A' ) - Z = moose.vec( '/model/chem/dend/Z' ) - print(moose.element( '/model/chem/dend/A/Adot' ).expr) - print(moose.element( '/model/chem/dend/B/Bdot' ).expr) - print(moose.element( '/model/chem/dend/Ca/CaStim' ).expr) - phase = moose.vec( '/model/chem/dend/phase' ) - ampl = moose.vec( '/model/chem/dend/ampl' ) - vel = moose.vec( '/model/chem/dend/vel' ) - vel.nInit = 1e-6 * seqDt - ampl.nInit = stimAmpl - stride = int( dist ) / numSpine - phase.nInit = 10000 - Z.nInit = 0 - for j in range( numSpine ): - k = int( blanks + j * stride ) - Z[k].nInit = 1 - phase[k].nInit = preStim + seq[j] * seqDt - - moose.reinit() - runtime = 50 - snapshot = preStim + seqDt * (numSpine - 0.8) - print(snapshot) - moose.start( snapshot ) - avec = moose.vec( '/model/chem/dend/A' ).n - moose.start( runtime - snapshot ) - tvec = [] - for i in range( 5 ): - tab = moose.element( '/model/graphs/plot0[' + str( blanks + i * stride ) + ']' ) - dt = tab.dt - tvec.append( tab.vector ) - moose.delete( '/model' ) - return dt, tvec, avec - -def makePassiveSoma( name, length, diameter ): - elecid = moose.Neuron( '/library/' + name ) - dend = moose.Compartment( elecid.path + '/soma' ) - dend.diameter = diameter - dend.length = length - dend.x = length - return elecid - -def plotOnePanel( tLabel, dt, tplot, numSyn, plotRange, tick ): - t = np.arange( 0, len( tplot[0] ), 1.0 ) * dt - for i in range( 5 ): - print( tplot[i] ) - - -def plotPanelDEFG( seq, row ): - makePassiveSoma( 'cell', 100e-6, 10e-6 ) - start = (row -1) * 4 - tLabel = chr( ord( 'B' ) + row - 1 ) - xLabel = chr( ord( 'D' ) + row - 1 ) - xplot = [] - - - dt, tplot, avec = runPanelDEFG( 'negFB', 5.0, 2.0, 5, seq, 1.0 ) - xplot.append( avec ) - t = np.arange( 0, len( tplot[0] ), 1.0 ) * dt - - dt, tplot, avec = runPanelDEFG( 'negFF', 10.0, 1.0, 5, seq, 1.0 ) - xplot.append( avec ) - t = np.arange( 0, len( tplot[0] ), 1.0 ) * dt - dt, tplot, avec = runPanelDEFG( 'fhn', 5.0, 1.5, 5, seq, 0.4 ) - xplot.append( avec ) - t = np.arange( 0, len( tplot[0] ), 1.0 ) * dt - - dt, tplot, avec = runPanelDEFG( 'bis', 15.0, 2.0, 5, seq, 1.0 ) - xplot.append( avec ) - t = np.arange( 0, len( tplot[0] ), 1.0 ) * dt - ref = np.array( [0.04840247926323106, 0.060446860947786119 - , 0.047612129439079991, 0.081329604404641223, 0.050365470686926379] ) - res = np.array( [ np.mean( x ) for x in tplot ] ) - assert np.isclose( ref.all(), res.all() ), "Expected %s got %s" % (ref,res) - -if __name__ == '__main__': - moose.Neutral( '/library' ) - moose.Neutral( '/model' ) - plotPanelC() - #if sys.version_info[0] == 2: - # plotPanelDEFG( [0,1,2,3,4], 3 ) - # plotPanelDEFG( [4,1,0,3,2], 4 ) - #else: - # print( 'TODO: Running any of the following two functions causes seg-fault' ) - print( 'All done' ) diff --git a/tests/python/test_paths.py b/tests/python/test_paths.py deleted file mode 100644 index a9d8bc63..00000000 --- a/tests/python/test_paths.py +++ /dev/null @@ -1,51 +0,0 @@ -# -*- coding: utf-8 -*- -import moose -import re - -def fixPath(path): - path = re.sub(r'/+', '/', path) - return path - -paths = [ '/a' - , '//a' - , '/a/b' - , '/a/b/' - , '//a//b/////' - , '/a/./b' - , '///a/././b' - ] -expectedPath = [fixPath(p) for p in paths] - -expectedChanges = zip(paths, expectedPath) - -for p in expectedPath: - print( 'Accessing %s' % p ) - try: - moose.Neutral(p) - except Exception as e: - print( 'Same path access by element' ) - moose.element( p ) - -foundPath = [] -for p in moose.wildcardFind('/##'): - if "/a" in p.path: - foundPath.append(p.path) - -testFailed = False -for f in foundPath: - f = re.sub(r'\[\d+\]', '', f) - if f not in expectedPath: - testFailed = True - -if testFailed: - print("Test failed on paths") - -a = moose.Neutral( '/k' ) -b = moose.Neutral( '/k' ) -h = moose.HSolve( '/h' ) -try: - h = moose.Neutral( '/h' ) - print( 'This should have failed' ) - quit(1) -except Exception as e: - print( 'Success' ) diff --git a/tests/python/test_pyrun.py b/tests/python/test_pyrun.py deleted file mode 100644 index 7bb71293..00000000 --- a/tests/python/test_pyrun.py +++ /dev/null @@ -1,3 +0,0 @@ -# -*- coding: utf-8 -*- -import moose -moose.PyRun('/p') diff --git a/tests/python/test_rdesigneur_random_syn_input.py b/tests/python/test_rdesigneur_random_syn_input.py deleted file mode 100644 index 07c3ccb3..00000000 --- a/tests/python/test_rdesigneur_random_syn_input.py +++ /dev/null @@ -1,46 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import print_function, division - -# This example demonstrates random (Poisson) synaptic input to a cell. -# Copyright (C) Upinder S. Bhalla NCBS 2018 -# Released under the terms of the GNU Public License V3. No warranty. -# Changelog: -# Thursday 20 September 2018 09:53:27 AM IST -# - Turned into a test script. Dilawar Singh - -import moose -import numpy as np - -moose.seed( 100 ) - -try: - import matplotlib -except Exception as e: - print( "[INFO ] matplotlib is not found. This test wont run." ) - quit() - -import rdesigneur as rd - -rdes = rd.rdesigneur( - cellProto = [['somaProto', 'soma', 20e-6, 200e-6]], - chanProto = [['make_glu()', 'glu']], - chanDistrib = [['glu', 'soma', 'Gbar', '1' ]], - stimList = [['soma', '0.5', 'glu', 'randsyn', '50' ]], - # Deliver stimulus to glu synapse on soma, at mean 50 Hz Poisson. - plotList = [['soma', '1', '.', 'Vm', 'Soma membrane potential']] -) -rdes.buildModel() -moose.reinit() -moose.start( 0.3 ) -tables = moose.wildcardFind( '/##[TYPE=Table]' ) -res = [ ] -for t in tables: - y = t.vector - u, s = np.mean(y), np.std(y) - res.append( (u,s) ) - - -# Got these values from version compiled on Sep 20, 2018 with moose.seed set to -# 100. -expected = [(-0.051218660048699974, 0.01028490481294165)] -assert np.isclose( expected, res, atol=1e-5).all(), "Expected %s, got %s" %(expected,res) diff --git a/tests/python/test_snippets.py b/tests/python/test_snippets.py deleted file mode 100644 index 45a00ba7..00000000 --- a/tests/python/test_snippets.py +++ /dev/null @@ -1,58 +0,0 @@ -# -*- coding: utf-8 -*- -"""test_snippets.py: - -This script tests all the snippets. - -""" -from __future__ import print_function - -__author__ = "Dilawar Singh" -__copyright__ = "Copyright 2015, Dilawar Singh and NCBS Bangalore" -__credits__ = ["NCBS Bangalore"] -__license__ = "GNU GPL" -__version__ = "1.0.0" -__maintainer__ = "Dilawar Singh" -__email__ = "dilawars@ncbs.res.in" -__status__ = "Development" - -import sys -import os -import tempfile -import subprocess -import re - -results_ = {} -pat_ = re.compile(r'show\(\)|draw\(\)') -max_run_ = 2 - -def executeCode(filepath): - print("Executing %s" % filepath) - code = [] - with open(filepath, "r") as f: - for l in f.readlines(): - if not pat_.search(l): - code.append(l) - newfile = tempfile.NamedTemporaryFile(delete=False) - newfile.write("".join(code)) - - ret = subprocess.call(["python", newfile.name], shell=False) - if ret: - results_[filepath] = 'Passed' - else: - results_[filepath] = 'Failed' - -def main(): - snippetPath = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../../Demos/snippets') - print("Testing snippets in %s" % snippetPath) - print("[INFO] Disabling all pylab/matplotlib show() functions") - files = [] - for d, subd, fs in os.walk(snippetPath): - for f in fs: - if ".py" in f: - files.append(os.path.join(d, f)) - [ executeCode(f) for f in files[0:] ] - for k in results_: - print("{0} {1}".format(results_[k], k)) - -if __name__ == '__main__': - main() diff --git a/tests/python/test_vec.py b/tests/python/test_vec.py deleted file mode 100644 index c3ad5c1e..00000000 --- a/tests/python/test_vec.py +++ /dev/null @@ -1,5 +0,0 @@ -# -*- coding: utf-8 -*- -import moose -foo = moose.Pool('/foo1', 500) -bar = moose.vec('/foo1') -assert len(bar) == 500 diff --git a/tests/python/testdisabled_dose_response.py b/tests/python/testdisabled_dose_response.py deleted file mode 100644 index a840565a..00000000 --- a/tests/python/testdisabled_dose_response.py +++ /dev/null @@ -1,106 +0,0 @@ -# -*- coding: utf-8 -*- -## Makes and plots the dose response curve for bistable models -## Author: Sahil Moza -## June 26, 2014 -## Update: -## Friday 14 September 2018 05:48:42 PM IST -## Tunrned into a light-weight test by Dilawar Singh - -import os -import sys -import moose -import numpy as np - -sdir_ = os.path.dirname( os.path.realpath( __file__ ) ) - -def setupSteadyState(simdt,plotDt): - - ksolve = moose.Ksolve( '/model/kinetics/ksolve' ) - stoich = moose.Stoich( '/model/kinetics/stoich' ) - stoich.compartment = moose.element('/model/kinetics') - stoich.ksolve = ksolve - stoich.path = "/model/kinetics/##" - state = moose.SteadyState( '/model/kinetics/state' ) - moose.reinit() - state.stoich = stoich - state.showMatrices() - state.convergenceCriterion = 1e-8 - return ksolve, state - -def parseModelName(fileName): - pos1=fileName.rfind('/') - pos2=fileName.rfind('.') - directory=fileName[:pos1] - prefix=fileName[pos1+1:pos2] - suffix=fileName[pos2+1:len(fileName)] - return directory, prefix, suffix - -# Solve for the steady state -def getState( ksolve, state, vol): - scale = 1.0 / ( vol * 6.022e23 ) - moose.reinit() - state.randomInit() # Removing random initial condition to systematically make Dose reponse curves. - moose.start( 2.0 ) # Run the model for 2 seconds. - state.settle() - - vector = [] - a = moose.element( '/model/kinetics/a' ).conc - for x in ksolve.nVec[0]: - vector.append( x * scale) - failedSteadyState = any([np.isnan(x) for x in vector]) - if not (failedSteadyState): - return state.stateType, state.solutionStatus, a, vector - - -def main(): - # Setup parameters for simulation and plotting - simdt= 1e-2 - plotDt= 1 - - # Factors to change in the dose concentration in log scale - factorExponent = 10 ## Base: ten raised to some power. - factorBegin = -10 - factorEnd = 11 - factorStepsize = 2 - factorScale = 10.0 ## To scale up or down the factors - - # Load Model and set up the steady state solver. - # model = sys.argv[1] # To load model from a file. - model = os.path.join( sdir_, 'chem_models/19085.cspace' ) - modelPath, modelName, modelType = parseModelName(model) - outputDir = modelPath - - modelId = moose.loadModel(model, 'model', 'ee') - dosePath = '/model/kinetics/b/DabX' # The dose entity - - ksolve, state = setupSteadyState( simdt, plotDt) - vol = moose.element( '/model/kinetics' ).volume - iterInit = 100 - solutionVector = [] - factorArr = [] - - enz = moose.element(dosePath) - init = float(enz.kcat) # Dose parameter - - # Change Dose here to . - for factor in range(factorBegin, factorEnd, factorStepsize ): - scale = factorExponent ** (factor/factorScale) - enz.kcat = init * scale - print( "scale={:.3f}\tkcat={:.3f}".format( scale, enz.kcat) ) - for num in range(iterInit): - stateType, solStatus, a, vector = getState( ksolve, state, vol) - if solStatus == 0: - #solutionVector.append(vector[0]/sum(vector)) - solutionVector.append(a) - factorArr.append(scale) - - joint = np.array([factorArr, solutionVector]) - joint = joint[:,joint[1,:].argsort()] - got = np.mean( joint ), np.std( joint ) - expected = (1.2247, 2.46) - # Close upto 2 decimal place is good enough. - assert np.isclose(got, expected, atol=1e-2).all(), "Got %s, expected %s" % (got, expected) - print( joint ) - -if __name__ == '__main__': - main() diff --git a/tests/python/two_cells_nml_1.8/cellMechanisms/DoubExpSyn/ChannelML_v1.8.1_GENESIStab.xsl b/tests/python/two_cells_nml_1.8/cellMechanisms/DoubExpSyn/ChannelML_v1.8.1_GENESIStab.xsl deleted file mode 100644 index dd6ea88c..00000000 --- a/tests/python/two_cells_nml_1.8/cellMechanisms/DoubExpSyn/ChannelML_v1.8.1_GENESIStab.xsl +++ /dev/null @@ -1,1503 +0,0 @@ - - - - - - - - - -no - - - - - -Physiological Units - - - - -// This is a GENESIS script file generated from a ChannelML v1.8.1 file -// The ChannelML file is mapped onto a tabchannel object - - -// Units of ChannelML file: , units of GENESIS file generated: - - - -/* - -*/ - - - - - *** Note: Kinetic scheme based ChannelML descriptions cannot be mapped on to GENESIS at the present time. *** - - - *** Note: Integrate and Fire mechanisms cannot be mapped on to GENESIS at the present time. *** - - - - - - - - - - - - - - - - - - - - - - - no - yes - - - - - - - yes - yes - no - - - - - - - no - yes - - - - - - - yes - no - - - - -// NOTE: There are parameters in the ChannelML file, so there will be a seperate init of the table -extern init_ - - - - -function make_ - - - /* - - - Reference: - Pubmed: - */ - - - str chanpath = "/library/" - - if ({exists {chanpath}}) - return - end - - - - - - - - - - - - - - - - - - - create leakage {chanpath} - - - create tabchannel {chanpath} - - - create tab2Dchannel {chanpath} - - - create tabchannel {chanpath} - - - - setfield {chanpath} \ - Ek - - Voltage - \ - Ik 0 \ - Xpower - \ - Ypower - \ - Zpower - \ - Zpower 1 - \ - Xpower - \ - Ypower - \ - Zpower - \ - Zpower 1 - \ - Zpower - - - - - - setfield {chanpath} Gk - - Conductance Density - - - - - - setfield {chanpath} Gk - - Conductance Density - - - - - - setfield {chanpath} \ - Gbar - - Conductance Density - \ - Gk 0 - - - - - setfield {chanpath} \ - Gbar - - Conductance Density - \ - Gk 0 - - - - - - - // There are parameters in the ChannelML file, which may be changed after initialisation which could mean the tables - // will need to be updated. Seperating out the generation of the table values into init function. - - - addfield {chanpath} - setfield {chanpath} // Note units of this will be determined by its usage in the generic functions - - - init_ {chanpath} // Initialisation of the tables - -end // End of main channel definition - - -// calling this function after changing the extra parameters/added fields will updated the table -function init_(chanpath) - - str chanpath - - // Retrieving the param values as local variables - - float = {getfield {chanpath} } - - - - - - - - - // There is a Q10 factor which will alter the tau of the gates - - - - - float temp_adj_ = {pow {(celsius - )/10}} - - float temp_adj_ = - - - - - {pow {(celsius - )/10}} - - float temp_adj_ = - - float temp_adj_ = - - - - - float temp_adj_ = - - - float temp_adj_ = - - - - - - - - // No Q10 temperature adjustment found - float temp_adj_ = 1 - - float temp_adj_ = 1 - - - - - - - - - - 100 - 0.1 - - - - - Voltage - - - - - - - - - -100 - -0.1 - - - - - Voltage - - - - - - - - 400 - - - - - float tab_divs = - - - - float v_min = - - float v_max = - - float v, dv, i - - - - - - - - X - Y - Z - - - - // Creating table for gate , using name for it here - - float dv = ({v_max} - {v_min})/{tab_divs} - - - - - - - - - // Channel is dependent on concentration of: , rate equations will involve variable: - float c - float conc_min = - - Concentration - - float conc_max = - - Concentration - - - float dc = ({conc_max} - {conc_min})/{tab_divs} - - float = {conc_min} - - - - - // Setting up the volt/conc dependent 2D table - setfield {chanpath} index {VOLT_C1_INDEX} // assumes all gates are volt/conc dep - - - - call {chanpath} TABCREATE {tab_divs} {v_min} {v_max} {tab_divs} {conc_min} {conc_max} - - - - call {chanpath} TABCREATE Z {tab_divs} {conc_min} {conc_max} - - - for (c = 0; c <= ({tab_divs}); c = c + 1) - - - - call {chanpath} TABCREATE {tab_divs} {v_min} {v_max} - - - - - v = {v_min} - - - // There is a voltage offset of . This will shift the dependency of the rate equations - v = v - - - Voltage - - - - - for (i = 0; i <= ({tab_divs}); i = i + 1) - - - - - // Looking at rate: - - float - - - - - float A, B, k, V0 - - - - - - - - - - - - // Found a generic form of rate equation for , using expression: - // Will translate this for GENESIS compatibility... - - - // Equation (and all ChannelML file values) in but this script in - - v = v * - 1 - InvVoltage - // temporarily set v to units of equation... - - - // Equation depends on alpha/beta, so converting them too... - alpha = alpha * - 1 - Time - - beta = beta * - 1 - Time - - - - - // Equation depends on alpha, so converting it... - alpha = alpha * - 1 - Time - - - - - - // Equation depends on concentration, so converting that too... - - = * - 1 - InvConcentration - - - - - - - - - - - - - - - - - - - v = v * - 1 - Voltage - // reset v - - - alpha = alpha * - 1 - InvTime - // resetting alpha - beta = beta * - 1 - InvTime - // resetting beta - - - - alpha = alpha * - 1 - InvTime - // resetting alpha - - - - = * - 1 - Concentration - // resetting ca_conc - - - - - - - - - - // Set correct units of - - = * - 1 - InvTime - - - - - - - // Set correct units of - - = * - 1 - Time - - - - - - - - ? ERROR: Unrecognised form of the rate equation for ... - - - - - - - - - table[{i}] - table[{i}][{c}] - - - - - - - - // Using the alpha and beta expressions to populate the tables - - float tau = 1/(temp_adj_ * (alpha + beta)) - echo "Tab : v: "{v} ", a: "{alpha} ", b: "{beta} ", tau: "{tau} - - echo "Tab : conc: " {} - - - setfield {chanpath} _A-> {temp_adj_ * alpha} - setfield {chanpath} _B-> {temp_adj_ * (alpha + beta)} - - - - // Evaluating the tau and inf expressions - - - - float tau = 1/(temp_adj_ * (alpha + beta)) - - - tau = tau/temp_adj_ - - - - float inf = alpha/(alpha + beta) - - - echo "Tab : v: "{v} ", tau: "{tau} ", inf: "{inf} - - echo "Tab : conc: " {} - - - - - // Working out the "real" alpha and beta expressions from the tau and inf - - float alpha - - float beta - alpha = inf / tau - beta = (1- inf)/tau - - - setfield {chanpath} _A-> {alpha} - setfield {chanpath} _B-> {alpha + beta} - - - - - - - - // Looking at rate: - - float - - - - - float A, B, Vhalf - - - - - - - - - - - // Found a generic form of rate equation for , using expression: - // Will translate this for GENESIS compatibility... - - - // Equation (and all ChannelML file values) in but this script in - - v = v * - 1 - InvVoltage - // temporarily set v to units of equation... - - - // Equation depends on alpha/beta, so converting them too... - alpha = alpha * - 1 - Time - - beta = beta * - 1 - Time - - - - - // Equation depends on alpha, so converting it... - alpha = alpha * - 1 - Time - - - - - - // Equation depends on concentration, so converting that too... - - = * - 1 - InvConcentration - - - - - - - - - - - - - - - - - - - v = v * - 1 - Voltage - // reset v - - - alpha = alpha * - 1 - InvTime - // resetting alpha - beta = beta * - 1 - InvTime - // resetting beta - - - - alpha = alpha * - 1 - InvTime - // resetting alpha - - - - = * - 1 - Concentration - // resetting ca_conc - - - - - - - - - - // Set correct units of - - = * - 1 - InvTime - - - - - - - // Set correct units of - - = * - 1 - Time - - - - - - - - ? ERROR: Unrecognised form of the rate equation for ... - - - - - - - - - table[{c}] - table[{i}] - table[{i}][{c}] - - - - - - - - // Using the alpha and beta expressions to populate the tables - - float tau = 1/(temp_adj_ * (alpha + beta)) - echo "Tab : v: "{v} ", a: "{alpha} ", b: "{beta} ", tau: "{tau} - - echo "Tab : conc: " {} - - - - - - setfield {chanpath} _A-> {temp_adj_ * alpha} - setfield {chanpath} _B-> {temp_adj_ * (alpha + beta)} - - - setfield {chanpath} Z_A-> {temp_adj_ * alpha} - setfield {chanpath} Z_B-> {temp_adj_ * (alpha + beta)} - - - - - - - // Evaluating the tau and inf expressions - - - - float tau = 1/(temp_adj_ * (alpha + beta)) - - - tau = tau/temp_adj_ - - - - float inf = alpha/(alpha + beta) - - - echo "Tab : v: "{v} ", tau: "{tau} ", inf: "{inf} - - echo "Tab : conc: " {} - - - - - // Working out the "real" alpha and beta expressions from the tau and inf - - float alpha - - float beta - alpha = inf / tau - beta = (1- inf)/tau - - - setfield {chanpath} _A-> {alpha} - setfield {chanpath} _B-> {alpha + beta} - - - - - - - v = v + dv - - end // end of for (i = 0; i <= ({tab_divs}); i = i + 1) - - - - - - = + dc - - - = + dc - - - - end // end of for (c = 0; c <= ({tab_divs}); c = c + 1) - - - - - - - - setfield {chanpath} _A->calc_mode 1 _B->calc_mode 1 - - - setfield {chanpath} Z_conc 1 - setfield {chanpath} Z_A->calc_mode 1 Z_B->calc_mode 1 - - - - - - - - - // Adding voltage independent concentration term - - - float conc_min = - - Concentration - - float conc_max = - - Concentration - - - float dc = ({conc_max} - {conc_min})/{tab_divs} - - float = {conc_min} - - call {chanpath} TABCREATE Z {tab_divs} {conc_min} {conc_max} - - float const_state - - for (i = 0; i <= ({tab_divs}); i = i + 1) - - - - - // Equation is in different set of units... - = * - 1 - InvConcentration - - - - - - - const_state - - - - - - - - - // Converting back... - = * - 1 - Concentration - - - - - - - setfield {chanpath} Z_A->table[{i}] {0} - setfield {chanpath} Z_B->table[{i}] {const_state} - - - = + dc - - end - - tweaktau {chanpath} Z - - - -end - - - - - - - - - - - -function __catchCeiling__(action) - - call . PROCESS -parent // Carry out all normal actions - - float caval = {getfield Ca} - float cabase = {getfield Ca_base} - float ceil = {getfield ceiling} - - if (caval > ceil) - setfield Ca {ceil} - setfield C {ceil - cabase} - end - -end - - -function make_ - - - /* - - */ - - - str chanpath = "/library/" - - if ({exists {chanpath}}) - return - end - - - - - create Ca_concen {chanpath} - - - - - - - - - - - Time - - - { 1.0 / - - - - InvTime - } - - - - - // Setting params for a decaying_pool_model - - setfield {chanpath} \ - tau \ - Ca_base - - - - Concentration - - - - addfield {chanpath} beta -description "Inverse of tau, needed as this is parameter used in some implementations. If beta > 0, this will be used in preference to tau" - setfield {chanpath} beta -1 - - - - setfield {chanpath} \ - thick - - - - Length - - - - - - - addfield {chanpath} ceiling -description "Maximum concentration pool will be allowed reach" - setfield {chanpath} ceiling - - - - Concentration - - - addaction {chanpath} PROCESS __catchCeiling__ - - - - -end - -function init_(chanpath) - - float curr_beta = {getfield {chanpath} beta} - if (curr_beta > 0) - - echo "Using the value of beta " {curr_beta} " in place of tau" - setfield {chanpath} tau {1 / {curr_beta}} - else - echo "Keeping existing tau: " {getfield {chanpath} tau} " not beta: " {curr_beta} - end - - -end - - - - - - - - - - - -function connectGapJunction_(compartmentA, compartmentB, weight) - - // Note: implementation based on suggestion of Reinoud Maex - - str compartmentA - str compartmentB - float conductance = - - Conductance - - str diffampname = {strcat "diffamp_" {rand 0 99999999}} // to ensure a different diffamp name for each gap junc on this comp - - create diffamp {compartmentA}/{diffampname} - - addmsg {compartmentA} {compartmentA}/{diffampname} PLUS Vm - addmsg {compartmentB} {compartmentA}/{diffampname} MINUS Vm - - setfield {compartmentA}/{diffampname} gain {conductance * weight} - setfield {compartmentA}/{diffampname} saturation 10e8 - - addmsg {compartmentA}/{diffampname} {compartmentB} INJECT output - - - create diffamp {compartmentB}/{diffampname} - - addmsg {compartmentB} {compartmentB}/{diffampname} PLUS Vm - addmsg {compartmentA} {compartmentB}/{diffampname} MINUS Vm - - setfield {compartmentB}/{diffampname} gain {conductance * weight} - setfield {compartmentB}/{diffampname} saturation 10e8 - - addmsg {compartmentB}/{diffampname} {compartmentA} INJECT output - -end - - - -function makechannel_(compartment, name) - - /* - - */ - - str compartment - str name - - if (!({exists {compartment}/{name}})) - - create synchan {compartment}/{name} - - setfield ^ \ - Ek - - Voltage \ - tau1 - - Time \ - tau2 - - Time \ - gmax - - Conductance - - float tau2 = {getfield {compartment}/{name} tau2} - - if (tau2 == 0) // Single exponential synapse - setfield {compartment}/{name} tau2 1e-9 - end - - addmsg {compartment}/{name} {compartment} CHANNEL Gk Ek - addmsg {compartment} {compartment}/{name} VOLTAGE Vm - - - - setfield ^ \ - Ek - - Voltage \ - tau1 - - Time \ - tau2 - - Time \ - gmax - - Conductance - - float tau1 = {getfield {compartment}/{name} tau1} - if (tau1 == 0) - setfield {compartment}/{name} tau1 1e-9 - end - - addmsg {compartment} {compartment}/{name} VOLTAGE Vm - - if (! {exists {compartment}/{name}/Mg_BLOCK}) - - float CMg = - - Concentration - - float eta = - - InvConcentration - - float gamma = - - InvVoltage - - create Mg_block {compartment}/{name}/Mg_BLOCK - - setfield {compartment}/{name}/Mg_BLOCK \ - CMg {CMg} \ - KMg_A {1/eta} \ - KMg_B {1.0/gamma} - - addmsg {compartment}/{name} {compartment}/{name}/Mg_BLOCK CHANNEL Gk Ek - addmsg {compartment}/{name}/Mg_BLOCK {compartment} CHANNEL Gk Ek - addmsg {compartment} {compartment}/{name}/Mg_BLOCK VOLTAGE Vm - end - - - - end - -end - - - - - - - - - - - - - 1 - 2 - 3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - si - - - - - - - - - - - - - - - - - // ChannelML form of equation: = , with params: - // A = , k = , d = , in units: - - - - A = - - InvTime - - - - A = - - Time - - - - A = - - - A = // Warning: unrecognised rate variable! Don't know how to convert units! - - - k = - - InvVoltage - - B = 1/k - V0 = - - Voltage - - - - - - - = A * {exp {(v - V0) / B}} - - - = A / ( {exp {(v - V0) / B}} + 1) - - - - if ( {abs {(v - V0)/ B}} < 1e-6) - = A * (1 + (v - V0)/B/2) - else - = A * ((v - V0) / B) /(1 - {exp {-1 * (v - V0)/B}}) - end - - - - - - - - = 1 // Gate is not present, power should = 0 so value of is not relevant - - - - - - - - - - - - - - - - // ChannelML form of equation: which is of form , with params: - // A = , B = , Vhalf = , in units: - - - - A = - - InvTime - - - - A = - - Time - - - - A = - - - A = // Warning: unrecognised rate variable! Don't know how to convert units! - - - B = - - Voltage - - Vhalf = - - Voltage - - - - - - - = A * {exp {(v - Vhalf) / B}} - - - = A / ( {exp {(v - Vhalf) / B}} + 1) - - - - if ( {abs {(v - Vhalf)/ B}} < 1e-6) - = A * (1 + (v - Vhalf)/B/2) - else - = A * ((v - Vhalf) / B) /(1 - {exp {-1 * (v - Vhalf)/B}}) - end - - - - - - - - = 1 // Gate is not present, power should = 0 so value of is not relevant - - - - - - - - - - - - - - - - - - if () - = - else - = - end - - - = - - - - - \ No newline at end of file diff --git a/tests/python/two_cells_nml_1.8/cellMechanisms/DoubExpSyn/ChannelML_v1.8.1_NEURONmod.xsl b/tests/python/two_cells_nml_1.8/cellMechanisms/DoubExpSyn/ChannelML_v1.8.1_NEURONmod.xsl deleted file mode 100644 index 04a6a65a..00000000 --- a/tests/python/two_cells_nml_1.8/cellMechanisms/DoubExpSyn/ChannelML_v1.8.1_NEURONmod.xsl +++ /dev/null @@ -1,1974 +0,0 @@ - - - - - - - - - - - - - -0 - -0 - -1 - -0 - - - - - - -? This is a NEURON mod file generated from a ChannelML file - -? Unit system of original ChannelML file: - - - - *** Note: Kinetic scheme based ChannelML description cannot be mapped in to mod files in this version. *** - Please use the alternative XSL file which maps on to NEURON's KS Channel Builder format - (should be ChannelML_v1.X.X_NEURONChanBuild.xsl) - - - -COMMENT - -ENDCOMMENT - - - - - - - - - - - - - - -TITLE Channel: - - - -COMMENT - -ENDCOMMENT - - -UNITS { - (mA) = (milliamp) - (mV) = (millivolt) - (S) = (siemens) - (um) = (micrometer) - (molar) = (1/liter) - (mM) = (millimolar) - (l) = (liter) -} - - - - yes - yes - no - - - - - - yes - yes - no - - - -NEURON { - - - SUFFIX - - - - - USEION WRITE i VALENCE ? reversal potential of ion is **NOT READ**, outgoing current is written - - - USEION READ i VALENCE ? internal concentration of ion is read - - - USEION READ i WRITE i VALENCE ? outgoing current of ion is read, internal concentration is written - - - USEION READ e WRITE i VALENCE ? reversal potential of ion is read, outgoing current is written - - - - - - VALENCE - VALENCE 1 - USEION READ e WRITE i ? reversal potential of ion is read, outgoing current is written - - - - - VALENCE - VALENCE 1 - USEION READ i ? internal concentration of ion is read - - - - VALENCE - VALENCE 1 - USEION READ i ? internal concentration of ion is read - - - - - - ? A non specific current is present - RANGE e - NONSPECIFIC_CURRENT i - - RANGE gmax, gion - - - RANGE inf, tau - - , __ - - - - - - RANGE inf, tau - - - - - RANGE - - - - - - - - RANGE - - - - ? Note this implementation is based on that used in the COBA based I and F model as used in Brette et al (2006) - ? and the NEURON script files from http://senselab.med.yale.edu/SenseLab/ModelDB/ShowModel.asp?model=83319 - - POINT_PROCESS - GLOBAL thresh, t_refrac, v_reset, g_refrac - NONSPECIFIC_CURRENT i - - -} - -PARAMETER { - - - gmax = - - Conductance Density - (S/cm2) ? default value, should be overwritten when conductance placed on cell - - e = - - Voltage - (mV) ? default value, should be overwritten when conductance placed on cell - - - - - __ = - - - - - - - gmax = - - Conductance Density - (S/cm2) ? default value, should be overwritten when conductance placed on cell - - e = - - Voltage - (mV) ? default value, should be overwritten when conductance placed on cell - - - - thresh = - - Voltage - (mV) - t_refrac = - - Time - (ms) - v_reset = - - Voltage - (mV) - g_refrac = - - Conductance - (uS) - - - - = : Note units of this will be determined by its usage in the generic functions - -} - - - -ASSIGNED { - - - v (mV) - - - i (mA/cm2) - - - celsius (degC) - - - - ? The internal concentration of ion: is used in the rate equations... - i (mM) - - - ? Error!! ion: with role="SignallingSubstance" shouldn't be in a channel_type... - - - ? Reversal potential of - e (mV) - ? The outward flow of ion: calculated by rate equations... - i (mA/cm2) - - - - - - ? Reversal potential of - e (mV) - ? The outward flow of ion: calculated by rate equations... - i (mA/cm2) - - - - ? The internal concentration of ion: is used in the rate equations... - i (mM) - - - ? The internal concentration of ion: is used in the rate equations... - i (mM) - - - gion (S/cm2) - - inf - tau (ms) - - - inf - tau (ms) - - - - - (/ms) - - - - - - - - - i (nanoamp) - v (millivolt) - g (microsiemens) - - - -} - -BREAKPOINT { LOCAL g_factor, - - -LOCAL g_factor, - - - - - - - - - i = gmax*(v - e) - - - - - - SOLVE kin METHOD sparse - - - SOLVE states METHOD derivimplicit - - - - SOLVE states METHOD cnexp - - - - gion = gmax*(( - *)^) - - - - - gion = gmax * (( + (*) )^) - - - - - = i / - 1 - Concentration - - - g_factor - - - - - - gion = gion * g_factor - - - - - i = gion*(v - e) - - - - i = gion*(v - e) - - - - - - i = g*(v - v_reset) - - - -} - - - - -INITIAL { - net_send(0, 3) - g = 0 -} - -NET_RECEIVE(w) { - - if (flag == 1) { - v = v_reset - g = g_refrac - - printf("+++++++ Spiking cell at: %g, v: %g\n", t, v) - - net_event(t) - net_send(t_refrac, 2) - }else if (flag == 2) { - g = 0 - - printf("+++++++ Finished refract at: %g, v: %g\n", t, v) - - }else if (flag == 3) { - WATCH (v > thresh) 1 - } -} - - - -INITIAL { - - - - Voltage - - - - e = - - - - - e = - - - - - - settables(v,cai) - - - rates(v) - - - - - - = inf - - = : Hard coded initialisation!! - - - = : Hard coded initialisation!! - - - - - - - - - = inf - - = : Hard coded initialisation!! - - SOLVE kin STEADYSTATE sparse - - - -} - -STATE { - - - - - - - - - - - - - - - - -} - - - - -KINETIC kin { - - settables(v,cai) - - rates(v) - - - - - - - - - - - - ~ <-> (, ) - - CONSERVE + = 1 -} - - - - -DERIVATIVE states { - - settables(v,cai) - - rates(v) - - - - ' = (inf - )/tau - - - - - - ' = (inf - )/tau - - - - - - ' = 0 + * (1 - ) - - * - - - - - - -} - - - - - - - PROCEDURE settables(v(mV), cai(mM)) { - PROCEDURE rates(v(mV)) { - - - ? Note: not all of these may be used, depending on the form of rate equations - LOCAL alpha, beta, tau, inf, gamma, zeta, - , - , temp_adj_, A__, k__, d__ - - - , temp_adj_ - , - A__, B__, Vhalf__ - - - - - - - - - - - - - 100 - - - - Voltage - - - - - - - - -100 - - - - Voltage - - - - - - - - 400 - - - - - - - - - - TABLE inf, tau, - inf, tau, - DEPEND celsius - - , __ - FROM TO WITH - - - : NOT USING TABLE: as there are some changable parameters ( ) - : which may be different on different sections, using a TABLE for computing these values can lead to errors. - - - - - - - UNITSOFF - - - ? There is a Q10 factor which will alter the tau of the gates - - - - - temp_adj_ = ^((celsius - )/10) - - temp_adj_ = - - - - - ^((celsius - )/10) - - temp_adj_ = - - - temp_adj_ = - - - - - temp_adj_ = - - - temp_adj_ = - - - - - - - - temp_adj_ = 1 - - temp_adj_ = 1 - - - - - - - - ? There is a voltage offset of . This will shift the dependency of the rate equations - v = v - ( - - Voltage - ) - - - - - - - - - - - - ? Gate depends on the concentration of - - = i ? In NEURON, the variable for the concentration of is i - - - ? *** Adding rate equations for gate: *** - - - - - - - ? Found a parameterised form of rate equation for , using expression: - A*(k*(v-d)) / (1 - exp(-(k*(v-d)))) - A*exp(k*(v-d)) - A / (1 + exp(k*(v-d))) - Unsupported expression type! - - - A__ - k__ - d__ - - - - __ = - - - - - ? Unit system in ChannelML file is SI units, therefore need to - ? convert these to NEURON quanities... - - - = * - 1 - InvTime - ? 1/ms - - - = * - 1 - Time - ? ms - - - = ? Dimensionless - - - = * - 1 - InvVoltage - ? mV - = * - 1 - Voltage - ? mV - - - - - - - - = * exp((v - ) * ) - - - - - = / (exp((v - ) * ) + 1) - - - - - = * vtrap((v - ), (1/)) - - - - - - - - - - ? Found a generic form of the rate equation for , using expression: - - - ? Note: Equation (and all ChannelML file values) in so need to convert v first... - - v = v * - 1 - InvVoltage - ? temporarily set v to units of equation... - - - - ? Equation depends on alpha/beta, so converting them too... - alpha = alpha * - 1 - Time - - beta = beta * - 1 - Time - - - - - - ? Equations can depend on concentration. NEURON uses 'SI Units' internally for concentration, - ? but ChannelML file is in Physiological Units... - = / - 1 - Concentration - - - - - - - - - - - - - - - - ? Set correct units of for NEURON - - = * - 1 - InvTime - - - - - ? Set correct units of for NEURON - - = * - 1 - Time - - - - v = v * - 1 - Voltage - ? reset v - - alpha = alpha * - 1 - InvTime - ? resetting alpha - beta = beta * - 1 - InvTime - ? resetting beta - - - - ? Resetting concentration... - = * - 1 - Concentration - - - - - - - - ? ERROR: Unrecognised form of the rate equation for - - - - - - - tau = tau/temp_adj_ - - - - - inf = inf - - - - - - - - - - tau = 1/(temp_adj_*(alpha + beta)) - - - - - inf = alpha/(alpha + beta) - - - - - ? *** Finished rate equations for gate: *** - - - - - - - - - - - ? Gate depends on the concentration of - - = i ? In NEURON, the variable for the concentration of is i - - - - - - - - - - - ? *** Adding rate equations for gate: *** - - - - - - - - ? Found a parameterised form of rate equation for , using expression: - A*((v-Vhalf)/B) / (1 - exp(-((v-Vhalf)/B))) - A*exp((v-Vhalf)/B) - A / (1 + exp((v-Vhalf)/B)) - Unsupported expression type! - - - A__ - B__ - Vhalf__ - - - - = - - = - - = - - - - ? Unit system in ChannelML file is SI units, therefore need to convert these to NEURON quanities... - - - - = * - 1 - InvTime - ? 1/ms - - - = * - 1 - Time - ? ms - - - = ? Dimensionless - - - = * - 1 - Voltage - ? mV - = * - 1 - Voltage - ? mV - - - - - - - = * exp((v - ) / ) - - - - - = / (exp((v - ) / ) + 1) - - - - - = * vtrap((v - ), ) - - - - - - - - - - ? Found a generic form of the rate equation for , using expression: - - - ? Note: Equation (and all ChannelML file values) in so need to convert v first... - - v = v * - 1 - InvVoltage - ? temporarily set v to units of equation... - - - - ? Equation depends on alpha/beta, so converting them too... - alpha = alpha * - 1 - Time - - beta = beta * - 1 - Time - - - - - - ? Equations can depend on concentration. NEURON uses 'SI Units' internally for concentration, - ? but the ChannelML file is in Physiological Units... - = / - 1 - Concentration - - - - - - - - - - - - - - - - ? Set correct units of for NEURON - - = * - 1 - InvTime - - - - - ? Set correct units of for NEURON - - = * - 1 - Time - - - - v = v * - 1 - Voltage - ? reset v - - alpha = alpha * - 1 - InvTime - ? resetting alpha - beta = beta * - 1 - InvTime - ? resetting beta - - - - ? Resetting concentration... - = * - 1 - Concentration - - - - - - - - ? ERROR: Unrecognised form of the rate equation for - - - - - - = * temp_adj_ ? Applying temp adj here as channel has KS description - - - - - tau = tau/temp_adj_ - - - - - inf = inf - - - - - - - - - - - tau = 1/(temp_adj_*(alpha + beta)) - - - - - inf = alpha/(alpha + beta) - - - - - - ? *** Finished rate equations for gate: *** - - - -} - - -? Function to assist with parameterised expressions of type linoid/exp_linear - -FUNCTION vtrap(VminV0, B) { - if (fabs(VminV0/B) < 1e-6) { - vtrap = (1 + VminV0/B/2) -}else{ - vtrap = (VminV0 / B) /(1 - exp((-1 *VminV0)/B)) - } -} - -UNITSON - - - - - - - - - -? Creating ion concentration - -TITLE Channel: - - - -COMMENT - -ENDCOMMENT - - -UNITS { - (mV) = (millivolt) - (mA) = (milliamp) - (um) = (micrometer) - (l) = (liter) - (molar) = (1/liter) - (mM) = (millimolar) -} - - -NEURON { - SUFFIX - - - USEION READ i WRITE i VALENCE - - - - - - - RANGE i - - RANGE rest_conc - - - RANGE tau - - - RANGE beta - - - RANGE ceiling - - - - RANGE thickness, F - - - RANGE total_current - RANGE volume_pool - - - - RANGE phi - - -} - -ASSIGNED { - - i (mA/cm2) - diam (um) - area (um) -} - -INITIAL { - - - LOCAL pi, shell_inner_diam, cylinderLen, circumference, circumference_shell, volumeOuter, volumeInner, volumeSph, volumeCyl - - pi = 3.14159265 - - shell_inner_diam = diam - (2*thickness) - - - ? Volume of the pool if it is a shell inside a sphere of diameter diam - - volumeSph = (diam*diam*diam) * pi / 6 - (shell_inner_diam*shell_inner_diam*shell_inner_diam)* pi / 6 - - - ? Volume of the pool if it is a cylinder - - circumference = diam * pi - circumference_shell = shell_inner_diam * pi - - cylinderLen = area/circumference - - volumeOuter = (diam * diam/4) * pi * cylinderLen - volumeInner = (shell_inner_diam * shell_inner_diam/4) * pi * cylinderLen - volumeCyl = volumeOuter - volumeInner - - if ((area - (pi * diam * diam)) < 1e-3 && (area - (pi * diam * diam)) > -1e-3 ) { - - ? Assume the segment is a sphere - printf("+++++++ Assume a sphere: %g, %g, %g\n", area, (pi * diam * diam), (area - (pi * diam * diam))) - - volume_pool = volumeSph - - } else { - - ? assume segment is a cylinder - printf("+++++++ Assume a cylinder: %g, %g, %g\n", area, (pi * diam * diam), (area - (pi * diam * diam))) - - volume_pool = volumeCyl - } - - printf("+++++++ Init ca, diam: %g, cylinderLen: %g, volume_pool: %g, volumeSph: %g, volumeCyl: %g, area as sph: %g, area x d: %g, area: %g\n", diam, cylinderLen, volume_pool, volumeSph, volumeCyl, (pi * diam * diam), (area*thickness), area) - - - i = rest_conc - -} - -PARAMETER { - - total_current - rest_conc = - - - - Concentration - (mM) - - - tau = - - - - Time - (ms) - - - beta = - - - - InvTime - (/ms) - - - - ceiling = - - - - Concentration - (mM) - - - F = 96494 (C) - - thickness = - - - - Length - (um) - - volume_pool - - - phi = - - -} - -STATE { - - i (mM) - -} - -BREAKPOINT { - - SOLVE conc METHOD derivimplicit - - if( i < 0 ){ i = 0 } - if( i > ceiling ){ i = ceiling } - - -} - -DERIVATIVE conc { - - * beta - /tau - - - LOCAL thickness_cm, surf_area_cm2, volume_cm3 ? Note, normally dimensions are in um, but curr dens is in mA/cm2, etc - - thickness_cm = thickness *(1e-4) - surf_area_cm2 = area * 1e-8 - volume_cm3 = volume_pool * 1e-12 - - total_current = i * surf_area_cm2 - - - i' = ((-1 * total_current)/( * F * volume_cm3)) - ((i - rest_conc)) - - - i' = - (phi * i) - ((i - rest_conc)) - - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -? Creating synaptic mechanism, based on NEURON source impl of Exp2Syn - - -? Creating NMDA like synaptic mechanism, based on NEURON source impl of Exp2Syn - - -? Creating synaptic mechanism, based on Volker Steuber & Chiara Saviane implementation of 3 decay component facilitating synapse - - -? Creating synaptic mechanism for an electrical synapse - - -? Creating synaptic mechanism, based on Volker Steuber & Chiara Saviane implementation of 3 decay component facilitating synapse - - -? Creating synaptic mechanism, based on Andrew Davison's impl of Song and Abbot's STDP model - - - - yes - no - - - -TITLE Channel: - - - -COMMENT - -ENDCOMMENT - - -UNITS { - (nA) = (nanoamp) - (mV) = (millivolt) - (uS) = (microsiemens) -} - - -NEURON { - POINT_PROCESS - - - - NONSPECIFIC_CURRENT i - RANGE g, i - RANGE weight - - - RANGE vgap : Using a RANGE variable as opposed to POINTER for parallel mode - - - POINTER vgap : Using a POINTER as opposed to RANGE for serial mode - - - - - - RANGE tau_rise, tau_decay - GLOBAL total - - - RANGE _conc, eta, gamma, gblock - GLOBAL total - - - - RANGE tau_decay_2, tau_decay_3, gmax_2, gmax_3, ampl - - - RANGE tau_rec : time course of recovery from synaptic depression - RANGE tau_facil : time course of facilitation - RANGE U, Uinit : release probability and initial value - - - RANGE post_spike_thresh : voltage at which post syn cell will be considered spiking - RANGE t_post_spike, t_pre_spike : times of last post and pre spikes - RANGE stdp_weight_factor : multiplicative factor for weight which changes based on activity - - RANGE M, P - RANGE wmax : maximum synaptic weight which can be reached - RANGE del_weight_ltp, del_weight_ltd : - - RANGE tau_ltp, tau_ltd - - - RANGE i, e, gmax - NONSPECIFIC_CURRENT i - RANGE g, factor, factor_2, factor_3 - - - -} - -PARAMETER { - gmax = - - Conductance - tau_rise = - - Time (ms) <1e-9,1e9> - tau_decay = - - Time (ms) <1e-9,1e9> - e = - - Voltage (mV) - - - _conc = - - Concentration - - eta = - - InvConcentration - - gamma = - - InvVoltage - - - - - - - gmax_2 = - - - 0 - - Conductance - - tau_decay_2 = - - - 0 - - Time (ms) <1e-9,1e9> - - - gmax_2 = 0 - tau_decay_2 = 100000 - - - - - - gmax_3 = - - - 0 - - Conductance - - tau_decay_3 = - - - 0 - - Time (ms) <1e-9,1e9> - - - gmax_3 = 0 - tau_decay_3 = 100000 - - - - - - - - tau_rec = - - Time (ms) < 1e-9, 1e9 > - tau_facil = - - Time (ms) < 0 ,1e9 > - - Uinit = (1) < 0, 1 > :release probability - - - - tau_ltp= - - Time (ms) < 1e-9, 1e9 > - tau_ltd= - - Time (ms) < 1e-9, 1e9 > - - del_weight_ltp= (1) < 0, 1e9 > - del_weight_ltd= (1) < 0, 1e9 > - - wmax= (1) < 0, 1e9 > - - - post_spike_thresh = - - Voltage (mV) - - in_post_spike = 0 : 1 if post cell is spiking, 0 otherwise - - - - v (millivolt) - vgap (millivolt) - g = - - Conductance (microsiemens) - weight = 1 - -} - - -ASSIGNED { - i (nanoamp) -} - -BREAKPOINT { - i = weight * g * (v - vgap) -} - - - -ASSIGNED { - v (mV) - i (nA) - g (uS) - factor - factor_2 - factor_3 - - total (uS) - - R - U - gblock - - M - P - deltaw - t_post_spike (ms) - t_pre_spike (ms) - stdp_weight_factor - -} - -STATE { - A (uS) - B (uS) - C (uS) - D (uS) -} - -INITIAL { - LOCAL tp, tp_2, tp_3 - total = 0 - - if (tau_rise == 0) { - tau_rise = 1e-9 : will effectively give a single exponential timecourse synapse - } - - if (tau_rise/tau_decay > .999999) { - tau_rise = .999999*tau_decay : will result in an "alpha" synapse waveform - } - A = 0 - B = 0 - C = 0 - D = 0 - - tp = (tau_rise*tau_decay)/(tau_decay - tau_rise) * log(tau_decay/tau_rise) - factor = -exp(-tp/tau_rise) + exp(-tp/tau_decay) - factor = 1/factor - - tp_2 = (tau_rise*tau_decay_2)/(tau_decay_2 - tau_rise) * log(tau_decay_2/tau_rise) - factor_2 = -exp(-tp_2/tau_rise) + exp(-tp_2/tau_decay_2) - factor_2 = 1/factor_2 - - tp_3 = (tau_rise*tau_decay_3)/(tau_decay_3 - tau_rise) * log(tau_decay_3/tau_rise) - factor_3 = -exp(-tp_3/tau_rise) + exp(-tp_3/tau_decay_3) - factor_3 = 1/factor_3 - - - - - - M = 0 - P = 0 - deltaw = 0 - t_post_spike = 0 - t_pre_spike = 0 - stdp_weight_factor = 1 - -} - -BREAKPOINT { - SOLVE state METHOD cnexp - - gblock = 1 / (1+ (_conc * eta * exp(-1 * gamma * v))) - g = gmax * gblock * (B - A) - g = (gmax * (B - A)) + (gmax_2 * (C - A)) + (gmax_3 * (D - A)) - g = gmax * (B - A) - - i = g*(v - e) - -} - - -DERIVATIVE state { - A' = -A/tau_rise - B' = -B/tau_decay - C' = -C/tau_decay_2 - D' = -D/tau_decay_3 - -} - -NET_RECEIVE(weight (uS), U, R, tsyn (ms)) { - - LOCAL RUD - - INITIAL { - tsyn = -1 - printf("-- In the INITIAL statement in NET_RECEIVE\n") - U = Uinit - R = 1 - printf("-- t: %g, delt: %g, g: %g, U: %g, R: %g\n", t, t-tsyn, g, U, R) - } - - printf("------------------------------------------------------------\n") - - printf("-- t: %g, delt: %g, g: %g, U: %g, R: %g\n", t, t-tsyn, g, U, R) - - - if (tsyn > 0) { - - R = R * (1-U) * exp(-(t - tsyn)/tau_rec) + 1 - exp(-(t - tsyn)/tau_rec) - - if (tau_facil > 0) { - U = U * exp(-(t - tsyn)/tau_facil) + Uinit * (1 - (U * exp(-(t - tsyn)/tau_facil))) - } else { - U = Uinit - } - - } else { - printf("-- At first spike...\n") - } - - RUD = (U*R) - - printf("-- t: %g, delt: %g, g: %g, U: %g, R: %g, RUD: %g\n", t, t-tsyn, g, U, R, RUD) - - - - printf("------------------------------------------------------------\n") - - - printf("-- SPIKE at time: %f (%g), with weight %g!\n", t, t, weight) - - - - - if (t_post_spike >= 0) { - printf("-- Last post spike ago: %g\n", t-t_post_spike) - } - if (t_pre_spike >= 0) { - printf("-- Last pre spike ago: %g\n", t-t_pre_spike) - } - - if (weight >= 0) { : this is a pre-synaptic spike - - P = P*exp((t_pre_spike-t)/tau_ltp) + del_weight_ltp - - deltaw = wmax * M * exp((t_post_spike - t)/tau_ltd) - - t_pre_spike = t - - } else { : this is a post-synaptic spike - - M = M*exp((t_post_spike-t)/tau_ltd) - del_weight_ltd - - //Todo: double check this! - //? deltaw = wmax * P * exp(-(t - t_pre_spike)/tau_ltp) - deltaw = deltaw + wmax * P * exp(-(t - t_pre_spike)/tau_ltp) - - t_post_spike = t - - } - - - - - stdp_weight_factor = stdp_weight_factor + deltaw - - if (stdp_weight_factor > wmax) { stdp_weight_factor = wmax} - if (stdp_weight_factor < 0) { stdp_weight_factor = 0} - - - printf("pg-- stdp_weight_factor: %g, deltaw: %g, P: %g, M: %g\n", stdp_weight_factor,deltaw, P, M) - - if (weight >= 0) { : this is a pre-synaptic spike - - - - - LOCAL Ajump, Bjump, Cjump, Djump - Bjump = weight*factor*stdp_weight_factor - Cjump = weight*factor_2*stdp_weight_factor - Djump = weight*factor_3*stdp_weight_factor - - Ajump = (gmax*Bjump + gmax_2*Cjump + gmax_3*Djump)/(gmax + gmax_2 + gmax_3) - - state_discontinuity(A, A + Ajump) - state_discontinuity(B, B + Bjump) - state_discontinuity(C, C + Cjump) - state_discontinuity(D, D + Djump) - - - state_discontinuity(A, A + weight*factor*RUD*stdp_weight_factor) - state_discontinuity(B, B + weight*factor*RUD*stdp_weight_factor) - - - - - - - tsyn = t - - - } - - -} - - - - - - - - - - - - - - - - - - - - if () { - = - } else { - = - } - - = - - - - - - - diff --git a/tests/python/two_cells_nml_1.8/cellMechanisms/DoubExpSyn/DoubExpSyn.xml b/tests/python/two_cells_nml_1.8/cellMechanisms/DoubExpSyn/DoubExpSyn.xml deleted file mode 100644 index 1e82acab..00000000 --- a/tests/python/two_cells_nml_1.8/cellMechanisms/DoubExpSyn/DoubExpSyn.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - ChannelML file describing a single synaptic mechanism - - - - - - - Padraig Gleeson - - - - Simple example of a synaptic mechanism, which consists of a postsynaptic conductance which changes as - double exponential function of time. Mappings exist for NEURON and GENESIS. - - - Receptor properties - http://senselab.med.yale.edu/senselab/NeuronDB/receptors2.asp - - - - - - - - \ No newline at end of file diff --git a/tests/python/two_cells_nml_1.8/cellMechanisms/DoubExpSyn/properties.xml b/tests/python/two_cells_nml_1.8/cellMechanisms/DoubExpSyn/properties.xml deleted file mode 100644 index c99dd21a..00000000 --- a/tests/python/two_cells_nml_1.8/cellMechanisms/DoubExpSyn/properties.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - -Properties associated with the Cell Mechanism which allow it to be loaded into neuroConstruct. - -Note the following: - The Cell Mechanism name should not contain spaces and should match the name of the directory it's in - The name and description here will be replaced by the corresponding values in a ChannelML file if found - The filenames for the mappings are relative to the cellMechanism/(cellMechInstanceName) directory - Mechanism Type should only have values: Channel mechanism, Synaptic mechanism, Ion concentration, Point process, Gap junction - - -Simple example of a synaptic mechanism, which consists of a postsynaptic conductance which changes as - double exponential function of time. Mappings exist for NEURON and GENESIS. -ChannelML_v1.8.1_NEURONmod.xsl -ChannelML_v1.8.1_GENESIStab.xsl -ChannelML based Cell Mechanism -true -Synaptic mechanism -DoubExpSyn.xml -false -DoubExpSyn -Template based ChannelML file - diff --git a/tests/python/two_cells_nml_1.8/cellMechanisms/KConductance/ChannelML_v1.8.1_GENESIStab.xsl b/tests/python/two_cells_nml_1.8/cellMechanisms/KConductance/ChannelML_v1.8.1_GENESIStab.xsl deleted file mode 100644 index dd6ea88c..00000000 --- a/tests/python/two_cells_nml_1.8/cellMechanisms/KConductance/ChannelML_v1.8.1_GENESIStab.xsl +++ /dev/null @@ -1,1503 +0,0 @@ - - - - - - - - - -no - - - - - -Physiological Units - - - - -// This is a GENESIS script file generated from a ChannelML v1.8.1 file -// The ChannelML file is mapped onto a tabchannel object - - -// Units of ChannelML file: , units of GENESIS file generated: - - - -/* - -*/ - - - - - *** Note: Kinetic scheme based ChannelML descriptions cannot be mapped on to GENESIS at the present time. *** - - - *** Note: Integrate and Fire mechanisms cannot be mapped on to GENESIS at the present time. *** - - - - - - - - - - - - - - - - - - - - - - - no - yes - - - - - - - yes - yes - no - - - - - - - no - yes - - - - - - - yes - no - - - - -// NOTE: There are parameters in the ChannelML file, so there will be a seperate init of the table -extern init_ - - - - -function make_ - - - /* - - - Reference: - Pubmed: - */ - - - str chanpath = "/library/" - - if ({exists {chanpath}}) - return - end - - - - - - - - - - - - - - - - - - - create leakage {chanpath} - - - create tabchannel {chanpath} - - - create tab2Dchannel {chanpath} - - - create tabchannel {chanpath} - - - - setfield {chanpath} \ - Ek - - Voltage - \ - Ik 0 \ - Xpower - \ - Ypower - \ - Zpower - \ - Zpower 1 - \ - Xpower - \ - Ypower - \ - Zpower - \ - Zpower 1 - \ - Zpower - - - - - - setfield {chanpath} Gk - - Conductance Density - - - - - - setfield {chanpath} Gk - - Conductance Density - - - - - - setfield {chanpath} \ - Gbar - - Conductance Density - \ - Gk 0 - - - - - setfield {chanpath} \ - Gbar - - Conductance Density - \ - Gk 0 - - - - - - - // There are parameters in the ChannelML file, which may be changed after initialisation which could mean the tables - // will need to be updated. Seperating out the generation of the table values into init function. - - - addfield {chanpath} - setfield {chanpath} // Note units of this will be determined by its usage in the generic functions - - - init_ {chanpath} // Initialisation of the tables - -end // End of main channel definition - - -// calling this function after changing the extra parameters/added fields will updated the table -function init_(chanpath) - - str chanpath - - // Retrieving the param values as local variables - - float = {getfield {chanpath} } - - - - - - - - - // There is a Q10 factor which will alter the tau of the gates - - - - - float temp_adj_ = {pow {(celsius - )/10}} - - float temp_adj_ = - - - - - {pow {(celsius - )/10}} - - float temp_adj_ = - - float temp_adj_ = - - - - - float temp_adj_ = - - - float temp_adj_ = - - - - - - - - // No Q10 temperature adjustment found - float temp_adj_ = 1 - - float temp_adj_ = 1 - - - - - - - - - - 100 - 0.1 - - - - - Voltage - - - - - - - - - -100 - -0.1 - - - - - Voltage - - - - - - - - 400 - - - - - float tab_divs = - - - - float v_min = - - float v_max = - - float v, dv, i - - - - - - - - X - Y - Z - - - - // Creating table for gate , using name for it here - - float dv = ({v_max} - {v_min})/{tab_divs} - - - - - - - - - // Channel is dependent on concentration of: , rate equations will involve variable: - float c - float conc_min = - - Concentration - - float conc_max = - - Concentration - - - float dc = ({conc_max} - {conc_min})/{tab_divs} - - float = {conc_min} - - - - - // Setting up the volt/conc dependent 2D table - setfield {chanpath} index {VOLT_C1_INDEX} // assumes all gates are volt/conc dep - - - - call {chanpath} TABCREATE {tab_divs} {v_min} {v_max} {tab_divs} {conc_min} {conc_max} - - - - call {chanpath} TABCREATE Z {tab_divs} {conc_min} {conc_max} - - - for (c = 0; c <= ({tab_divs}); c = c + 1) - - - - call {chanpath} TABCREATE {tab_divs} {v_min} {v_max} - - - - - v = {v_min} - - - // There is a voltage offset of . This will shift the dependency of the rate equations - v = v - - - Voltage - - - - - for (i = 0; i <= ({tab_divs}); i = i + 1) - - - - - // Looking at rate: - - float - - - - - float A, B, k, V0 - - - - - - - - - - - - // Found a generic form of rate equation for , using expression: - // Will translate this for GENESIS compatibility... - - - // Equation (and all ChannelML file values) in but this script in - - v = v * - 1 - InvVoltage - // temporarily set v to units of equation... - - - // Equation depends on alpha/beta, so converting them too... - alpha = alpha * - 1 - Time - - beta = beta * - 1 - Time - - - - - // Equation depends on alpha, so converting it... - alpha = alpha * - 1 - Time - - - - - - // Equation depends on concentration, so converting that too... - - = * - 1 - InvConcentration - - - - - - - - - - - - - - - - - - - v = v * - 1 - Voltage - // reset v - - - alpha = alpha * - 1 - InvTime - // resetting alpha - beta = beta * - 1 - InvTime - // resetting beta - - - - alpha = alpha * - 1 - InvTime - // resetting alpha - - - - = * - 1 - Concentration - // resetting ca_conc - - - - - - - - - - // Set correct units of - - = * - 1 - InvTime - - - - - - - // Set correct units of - - = * - 1 - Time - - - - - - - - ? ERROR: Unrecognised form of the rate equation for ... - - - - - - - - - table[{i}] - table[{i}][{c}] - - - - - - - - // Using the alpha and beta expressions to populate the tables - - float tau = 1/(temp_adj_ * (alpha + beta)) - echo "Tab : v: "{v} ", a: "{alpha} ", b: "{beta} ", tau: "{tau} - - echo "Tab : conc: " {} - - - setfield {chanpath} _A-> {temp_adj_ * alpha} - setfield {chanpath} _B-> {temp_adj_ * (alpha + beta)} - - - - // Evaluating the tau and inf expressions - - - - float tau = 1/(temp_adj_ * (alpha + beta)) - - - tau = tau/temp_adj_ - - - - float inf = alpha/(alpha + beta) - - - echo "Tab : v: "{v} ", tau: "{tau} ", inf: "{inf} - - echo "Tab : conc: " {} - - - - - // Working out the "real" alpha and beta expressions from the tau and inf - - float alpha - - float beta - alpha = inf / tau - beta = (1- inf)/tau - - - setfield {chanpath} _A-> {alpha} - setfield {chanpath} _B-> {alpha + beta} - - - - - - - - // Looking at rate: - - float - - - - - float A, B, Vhalf - - - - - - - - - - - // Found a generic form of rate equation for , using expression: - // Will translate this for GENESIS compatibility... - - - // Equation (and all ChannelML file values) in but this script in - - v = v * - 1 - InvVoltage - // temporarily set v to units of equation... - - - // Equation depends on alpha/beta, so converting them too... - alpha = alpha * - 1 - Time - - beta = beta * - 1 - Time - - - - - // Equation depends on alpha, so converting it... - alpha = alpha * - 1 - Time - - - - - - // Equation depends on concentration, so converting that too... - - = * - 1 - InvConcentration - - - - - - - - - - - - - - - - - - - v = v * - 1 - Voltage - // reset v - - - alpha = alpha * - 1 - InvTime - // resetting alpha - beta = beta * - 1 - InvTime - // resetting beta - - - - alpha = alpha * - 1 - InvTime - // resetting alpha - - - - = * - 1 - Concentration - // resetting ca_conc - - - - - - - - - - // Set correct units of - - = * - 1 - InvTime - - - - - - - // Set correct units of - - = * - 1 - Time - - - - - - - - ? ERROR: Unrecognised form of the rate equation for ... - - - - - - - - - table[{c}] - table[{i}] - table[{i}][{c}] - - - - - - - - // Using the alpha and beta expressions to populate the tables - - float tau = 1/(temp_adj_ * (alpha + beta)) - echo "Tab : v: "{v} ", a: "{alpha} ", b: "{beta} ", tau: "{tau} - - echo "Tab : conc: " {} - - - - - - setfield {chanpath} _A-> {temp_adj_ * alpha} - setfield {chanpath} _B-> {temp_adj_ * (alpha + beta)} - - - setfield {chanpath} Z_A-> {temp_adj_ * alpha} - setfield {chanpath} Z_B-> {temp_adj_ * (alpha + beta)} - - - - - - - // Evaluating the tau and inf expressions - - - - float tau = 1/(temp_adj_ * (alpha + beta)) - - - tau = tau/temp_adj_ - - - - float inf = alpha/(alpha + beta) - - - echo "Tab : v: "{v} ", tau: "{tau} ", inf: "{inf} - - echo "Tab : conc: " {} - - - - - // Working out the "real" alpha and beta expressions from the tau and inf - - float alpha - - float beta - alpha = inf / tau - beta = (1- inf)/tau - - - setfield {chanpath} _A-> {alpha} - setfield {chanpath} _B-> {alpha + beta} - - - - - - - v = v + dv - - end // end of for (i = 0; i <= ({tab_divs}); i = i + 1) - - - - - - = + dc - - - = + dc - - - - end // end of for (c = 0; c <= ({tab_divs}); c = c + 1) - - - - - - - - setfield {chanpath} _A->calc_mode 1 _B->calc_mode 1 - - - setfield {chanpath} Z_conc 1 - setfield {chanpath} Z_A->calc_mode 1 Z_B->calc_mode 1 - - - - - - - - - // Adding voltage independent concentration term - - - float conc_min = - - Concentration - - float conc_max = - - Concentration - - - float dc = ({conc_max} - {conc_min})/{tab_divs} - - float = {conc_min} - - call {chanpath} TABCREATE Z {tab_divs} {conc_min} {conc_max} - - float const_state - - for (i = 0; i <= ({tab_divs}); i = i + 1) - - - - - // Equation is in different set of units... - = * - 1 - InvConcentration - - - - - - - const_state - - - - - - - - - // Converting back... - = * - 1 - Concentration - - - - - - - setfield {chanpath} Z_A->table[{i}] {0} - setfield {chanpath} Z_B->table[{i}] {const_state} - - - = + dc - - end - - tweaktau {chanpath} Z - - - -end - - - - - - - - - - - -function __catchCeiling__(action) - - call . PROCESS -parent // Carry out all normal actions - - float caval = {getfield Ca} - float cabase = {getfield Ca_base} - float ceil = {getfield ceiling} - - if (caval > ceil) - setfield Ca {ceil} - setfield C {ceil - cabase} - end - -end - - -function make_ - - - /* - - */ - - - str chanpath = "/library/" - - if ({exists {chanpath}}) - return - end - - - - - create Ca_concen {chanpath} - - - - - - - - - - - Time - - - { 1.0 / - - - - InvTime - } - - - - - // Setting params for a decaying_pool_model - - setfield {chanpath} \ - tau \ - Ca_base - - - - Concentration - - - - addfield {chanpath} beta -description "Inverse of tau, needed as this is parameter used in some implementations. If beta > 0, this will be used in preference to tau" - setfield {chanpath} beta -1 - - - - setfield {chanpath} \ - thick - - - - Length - - - - - - - addfield {chanpath} ceiling -description "Maximum concentration pool will be allowed reach" - setfield {chanpath} ceiling - - - - Concentration - - - addaction {chanpath} PROCESS __catchCeiling__ - - - - -end - -function init_(chanpath) - - float curr_beta = {getfield {chanpath} beta} - if (curr_beta > 0) - - echo "Using the value of beta " {curr_beta} " in place of tau" - setfield {chanpath} tau {1 / {curr_beta}} - else - echo "Keeping existing tau: " {getfield {chanpath} tau} " not beta: " {curr_beta} - end - - -end - - - - - - - - - - - -function connectGapJunction_(compartmentA, compartmentB, weight) - - // Note: implementation based on suggestion of Reinoud Maex - - str compartmentA - str compartmentB - float conductance = - - Conductance - - str diffampname = {strcat "diffamp_" {rand 0 99999999}} // to ensure a different diffamp name for each gap junc on this comp - - create diffamp {compartmentA}/{diffampname} - - addmsg {compartmentA} {compartmentA}/{diffampname} PLUS Vm - addmsg {compartmentB} {compartmentA}/{diffampname} MINUS Vm - - setfield {compartmentA}/{diffampname} gain {conductance * weight} - setfield {compartmentA}/{diffampname} saturation 10e8 - - addmsg {compartmentA}/{diffampname} {compartmentB} INJECT output - - - create diffamp {compartmentB}/{diffampname} - - addmsg {compartmentB} {compartmentB}/{diffampname} PLUS Vm - addmsg {compartmentA} {compartmentB}/{diffampname} MINUS Vm - - setfield {compartmentB}/{diffampname} gain {conductance * weight} - setfield {compartmentB}/{diffampname} saturation 10e8 - - addmsg {compartmentB}/{diffampname} {compartmentA} INJECT output - -end - - - -function makechannel_(compartment, name) - - /* - - */ - - str compartment - str name - - if (!({exists {compartment}/{name}})) - - create synchan {compartment}/{name} - - setfield ^ \ - Ek - - Voltage \ - tau1 - - Time \ - tau2 - - Time \ - gmax - - Conductance - - float tau2 = {getfield {compartment}/{name} tau2} - - if (tau2 == 0) // Single exponential synapse - setfield {compartment}/{name} tau2 1e-9 - end - - addmsg {compartment}/{name} {compartment} CHANNEL Gk Ek - addmsg {compartment} {compartment}/{name} VOLTAGE Vm - - - - setfield ^ \ - Ek - - Voltage \ - tau1 - - Time \ - tau2 - - Time \ - gmax - - Conductance - - float tau1 = {getfield {compartment}/{name} tau1} - if (tau1 == 0) - setfield {compartment}/{name} tau1 1e-9 - end - - addmsg {compartment} {compartment}/{name} VOLTAGE Vm - - if (! {exists {compartment}/{name}/Mg_BLOCK}) - - float CMg = - - Concentration - - float eta = - - InvConcentration - - float gamma = - - InvVoltage - - create Mg_block {compartment}/{name}/Mg_BLOCK - - setfield {compartment}/{name}/Mg_BLOCK \ - CMg {CMg} \ - KMg_A {1/eta} \ - KMg_B {1.0/gamma} - - addmsg {compartment}/{name} {compartment}/{name}/Mg_BLOCK CHANNEL Gk Ek - addmsg {compartment}/{name}/Mg_BLOCK {compartment} CHANNEL Gk Ek - addmsg {compartment} {compartment}/{name}/Mg_BLOCK VOLTAGE Vm - end - - - - end - -end - - - - - - - - - - - - - 1 - 2 - 3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - si - - - - - - - - - - - - - - - - - // ChannelML form of equation: = , with params: - // A = , k = , d = , in units: - - - - A = - - InvTime - - - - A = - - Time - - - - A = - - - A = // Warning: unrecognised rate variable! Don't know how to convert units! - - - k = - - InvVoltage - - B = 1/k - V0 = - - Voltage - - - - - - - = A * {exp {(v - V0) / B}} - - - = A / ( {exp {(v - V0) / B}} + 1) - - - - if ( {abs {(v - V0)/ B}} < 1e-6) - = A * (1 + (v - V0)/B/2) - else - = A * ((v - V0) / B) /(1 - {exp {-1 * (v - V0)/B}}) - end - - - - - - - - = 1 // Gate is not present, power should = 0 so value of is not relevant - - - - - - - - - - - - - - - - // ChannelML form of equation: which is of form , with params: - // A = , B = , Vhalf = , in units: - - - - A = - - InvTime - - - - A = - - Time - - - - A = - - - A = // Warning: unrecognised rate variable! Don't know how to convert units! - - - B = - - Voltage - - Vhalf = - - Voltage - - - - - - - = A * {exp {(v - Vhalf) / B}} - - - = A / ( {exp {(v - Vhalf) / B}} + 1) - - - - if ( {abs {(v - Vhalf)/ B}} < 1e-6) - = A * (1 + (v - Vhalf)/B/2) - else - = A * ((v - Vhalf) / B) /(1 - {exp {-1 * (v - Vhalf)/B}}) - end - - - - - - - - = 1 // Gate is not present, power should = 0 so value of is not relevant - - - - - - - - - - - - - - - - - - if () - = - else - = - end - - - = - - - - - \ No newline at end of file diff --git a/tests/python/two_cells_nml_1.8/cellMechanisms/KConductance/ChannelML_v1.8.1_NEURONmod.xsl b/tests/python/two_cells_nml_1.8/cellMechanisms/KConductance/ChannelML_v1.8.1_NEURONmod.xsl deleted file mode 100644 index 04a6a65a..00000000 --- a/tests/python/two_cells_nml_1.8/cellMechanisms/KConductance/ChannelML_v1.8.1_NEURONmod.xsl +++ /dev/null @@ -1,1974 +0,0 @@ - - - - - - - - - - - - - -0 - -0 - -1 - -0 - - - - - - -? This is a NEURON mod file generated from a ChannelML file - -? Unit system of original ChannelML file: - - - - *** Note: Kinetic scheme based ChannelML description cannot be mapped in to mod files in this version. *** - Please use the alternative XSL file which maps on to NEURON's KS Channel Builder format - (should be ChannelML_v1.X.X_NEURONChanBuild.xsl) - - - -COMMENT - -ENDCOMMENT - - - - - - - - - - - - - - -TITLE Channel: - - - -COMMENT - -ENDCOMMENT - - -UNITS { - (mA) = (milliamp) - (mV) = (millivolt) - (S) = (siemens) - (um) = (micrometer) - (molar) = (1/liter) - (mM) = (millimolar) - (l) = (liter) -} - - - - yes - yes - no - - - - - - yes - yes - no - - - -NEURON { - - - SUFFIX - - - - - USEION WRITE i VALENCE ? reversal potential of ion is **NOT READ**, outgoing current is written - - - USEION READ i VALENCE ? internal concentration of ion is read - - - USEION READ i WRITE i VALENCE ? outgoing current of ion is read, internal concentration is written - - - USEION READ e WRITE i VALENCE ? reversal potential of ion is read, outgoing current is written - - - - - - VALENCE - VALENCE 1 - USEION READ e WRITE i ? reversal potential of ion is read, outgoing current is written - - - - - VALENCE - VALENCE 1 - USEION READ i ? internal concentration of ion is read - - - - VALENCE - VALENCE 1 - USEION READ i ? internal concentration of ion is read - - - - - - ? A non specific current is present - RANGE e - NONSPECIFIC_CURRENT i - - RANGE gmax, gion - - - RANGE inf, tau - - , __ - - - - - - RANGE inf, tau - - - - - RANGE - - - - - - - - RANGE - - - - ? Note this implementation is based on that used in the COBA based I and F model as used in Brette et al (2006) - ? and the NEURON script files from http://senselab.med.yale.edu/SenseLab/ModelDB/ShowModel.asp?model=83319 - - POINT_PROCESS - GLOBAL thresh, t_refrac, v_reset, g_refrac - NONSPECIFIC_CURRENT i - - -} - -PARAMETER { - - - gmax = - - Conductance Density - (S/cm2) ? default value, should be overwritten when conductance placed on cell - - e = - - Voltage - (mV) ? default value, should be overwritten when conductance placed on cell - - - - - __ = - - - - - - - gmax = - - Conductance Density - (S/cm2) ? default value, should be overwritten when conductance placed on cell - - e = - - Voltage - (mV) ? default value, should be overwritten when conductance placed on cell - - - - thresh = - - Voltage - (mV) - t_refrac = - - Time - (ms) - v_reset = - - Voltage - (mV) - g_refrac = - - Conductance - (uS) - - - - = : Note units of this will be determined by its usage in the generic functions - -} - - - -ASSIGNED { - - - v (mV) - - - i (mA/cm2) - - - celsius (degC) - - - - ? The internal concentration of ion: is used in the rate equations... - i (mM) - - - ? Error!! ion: with role="SignallingSubstance" shouldn't be in a channel_type... - - - ? Reversal potential of - e (mV) - ? The outward flow of ion: calculated by rate equations... - i (mA/cm2) - - - - - - ? Reversal potential of - e (mV) - ? The outward flow of ion: calculated by rate equations... - i (mA/cm2) - - - - ? The internal concentration of ion: is used in the rate equations... - i (mM) - - - ? The internal concentration of ion: is used in the rate equations... - i (mM) - - - gion (S/cm2) - - inf - tau (ms) - - - inf - tau (ms) - - - - - (/ms) - - - - - - - - - i (nanoamp) - v (millivolt) - g (microsiemens) - - - -} - -BREAKPOINT { LOCAL g_factor, - - -LOCAL g_factor, - - - - - - - - - i = gmax*(v - e) - - - - - - SOLVE kin METHOD sparse - - - SOLVE states METHOD derivimplicit - - - - SOLVE states METHOD cnexp - - - - gion = gmax*(( - *)^) - - - - - gion = gmax * (( + (*) )^) - - - - - = i / - 1 - Concentration - - - g_factor - - - - - - gion = gion * g_factor - - - - - i = gion*(v - e) - - - - i = gion*(v - e) - - - - - - i = g*(v - v_reset) - - - -} - - - - -INITIAL { - net_send(0, 3) - g = 0 -} - -NET_RECEIVE(w) { - - if (flag == 1) { - v = v_reset - g = g_refrac - - printf("+++++++ Spiking cell at: %g, v: %g\n", t, v) - - net_event(t) - net_send(t_refrac, 2) - }else if (flag == 2) { - g = 0 - - printf("+++++++ Finished refract at: %g, v: %g\n", t, v) - - }else if (flag == 3) { - WATCH (v > thresh) 1 - } -} - - - -INITIAL { - - - - Voltage - - - - e = - - - - - e = - - - - - - settables(v,cai) - - - rates(v) - - - - - - = inf - - = : Hard coded initialisation!! - - - = : Hard coded initialisation!! - - - - - - - - - = inf - - = : Hard coded initialisation!! - - SOLVE kin STEADYSTATE sparse - - - -} - -STATE { - - - - - - - - - - - - - - - - -} - - - - -KINETIC kin { - - settables(v,cai) - - rates(v) - - - - - - - - - - - - ~ <-> (, ) - - CONSERVE + = 1 -} - - - - -DERIVATIVE states { - - settables(v,cai) - - rates(v) - - - - ' = (inf - )/tau - - - - - - ' = (inf - )/tau - - - - - - ' = 0 + * (1 - ) - - * - - - - - - -} - - - - - - - PROCEDURE settables(v(mV), cai(mM)) { - PROCEDURE rates(v(mV)) { - - - ? Note: not all of these may be used, depending on the form of rate equations - LOCAL alpha, beta, tau, inf, gamma, zeta, - , - , temp_adj_, A__, k__, d__ - - - , temp_adj_ - , - A__, B__, Vhalf__ - - - - - - - - - - - - - 100 - - - - Voltage - - - - - - - - -100 - - - - Voltage - - - - - - - - 400 - - - - - - - - - - TABLE inf, tau, - inf, tau, - DEPEND celsius - - , __ - FROM TO WITH - - - : NOT USING TABLE: as there are some changable parameters ( ) - : which may be different on different sections, using a TABLE for computing these values can lead to errors. - - - - - - - UNITSOFF - - - ? There is a Q10 factor which will alter the tau of the gates - - - - - temp_adj_ = ^((celsius - )/10) - - temp_adj_ = - - - - - ^((celsius - )/10) - - temp_adj_ = - - - temp_adj_ = - - - - - temp_adj_ = - - - temp_adj_ = - - - - - - - - temp_adj_ = 1 - - temp_adj_ = 1 - - - - - - - - ? There is a voltage offset of . This will shift the dependency of the rate equations - v = v - ( - - Voltage - ) - - - - - - - - - - - - ? Gate depends on the concentration of - - = i ? In NEURON, the variable for the concentration of is i - - - ? *** Adding rate equations for gate: *** - - - - - - - ? Found a parameterised form of rate equation for , using expression: - A*(k*(v-d)) / (1 - exp(-(k*(v-d)))) - A*exp(k*(v-d)) - A / (1 + exp(k*(v-d))) - Unsupported expression type! - - - A__ - k__ - d__ - - - - __ = - - - - - ? Unit system in ChannelML file is SI units, therefore need to - ? convert these to NEURON quanities... - - - = * - 1 - InvTime - ? 1/ms - - - = * - 1 - Time - ? ms - - - = ? Dimensionless - - - = * - 1 - InvVoltage - ? mV - = * - 1 - Voltage - ? mV - - - - - - - - = * exp((v - ) * ) - - - - - = / (exp((v - ) * ) + 1) - - - - - = * vtrap((v - ), (1/)) - - - - - - - - - - ? Found a generic form of the rate equation for , using expression: - - - ? Note: Equation (and all ChannelML file values) in so need to convert v first... - - v = v * - 1 - InvVoltage - ? temporarily set v to units of equation... - - - - ? Equation depends on alpha/beta, so converting them too... - alpha = alpha * - 1 - Time - - beta = beta * - 1 - Time - - - - - - ? Equations can depend on concentration. NEURON uses 'SI Units' internally for concentration, - ? but ChannelML file is in Physiological Units... - = / - 1 - Concentration - - - - - - - - - - - - - - - - ? Set correct units of for NEURON - - = * - 1 - InvTime - - - - - ? Set correct units of for NEURON - - = * - 1 - Time - - - - v = v * - 1 - Voltage - ? reset v - - alpha = alpha * - 1 - InvTime - ? resetting alpha - beta = beta * - 1 - InvTime - ? resetting beta - - - - ? Resetting concentration... - = * - 1 - Concentration - - - - - - - - ? ERROR: Unrecognised form of the rate equation for - - - - - - - tau = tau/temp_adj_ - - - - - inf = inf - - - - - - - - - - tau = 1/(temp_adj_*(alpha + beta)) - - - - - inf = alpha/(alpha + beta) - - - - - ? *** Finished rate equations for gate: *** - - - - - - - - - - - ? Gate depends on the concentration of - - = i ? In NEURON, the variable for the concentration of is i - - - - - - - - - - - ? *** Adding rate equations for gate: *** - - - - - - - - ? Found a parameterised form of rate equation for , using expression: - A*((v-Vhalf)/B) / (1 - exp(-((v-Vhalf)/B))) - A*exp((v-Vhalf)/B) - A / (1 + exp((v-Vhalf)/B)) - Unsupported expression type! - - - A__ - B__ - Vhalf__ - - - - = - - = - - = - - - - ? Unit system in ChannelML file is SI units, therefore need to convert these to NEURON quanities... - - - - = * - 1 - InvTime - ? 1/ms - - - = * - 1 - Time - ? ms - - - = ? Dimensionless - - - = * - 1 - Voltage - ? mV - = * - 1 - Voltage - ? mV - - - - - - - = * exp((v - ) / ) - - - - - = / (exp((v - ) / ) + 1) - - - - - = * vtrap((v - ), ) - - - - - - - - - - ? Found a generic form of the rate equation for , using expression: - - - ? Note: Equation (and all ChannelML file values) in so need to convert v first... - - v = v * - 1 - InvVoltage - ? temporarily set v to units of equation... - - - - ? Equation depends on alpha/beta, so converting them too... - alpha = alpha * - 1 - Time - - beta = beta * - 1 - Time - - - - - - ? Equations can depend on concentration. NEURON uses 'SI Units' internally for concentration, - ? but the ChannelML file is in Physiological Units... - = / - 1 - Concentration - - - - - - - - - - - - - - - - ? Set correct units of for NEURON - - = * - 1 - InvTime - - - - - ? Set correct units of for NEURON - - = * - 1 - Time - - - - v = v * - 1 - Voltage - ? reset v - - alpha = alpha * - 1 - InvTime - ? resetting alpha - beta = beta * - 1 - InvTime - ? resetting beta - - - - ? Resetting concentration... - = * - 1 - Concentration - - - - - - - - ? ERROR: Unrecognised form of the rate equation for - - - - - - = * temp_adj_ ? Applying temp adj here as channel has KS description - - - - - tau = tau/temp_adj_ - - - - - inf = inf - - - - - - - - - - - tau = 1/(temp_adj_*(alpha + beta)) - - - - - inf = alpha/(alpha + beta) - - - - - - ? *** Finished rate equations for gate: *** - - - -} - - -? Function to assist with parameterised expressions of type linoid/exp_linear - -FUNCTION vtrap(VminV0, B) { - if (fabs(VminV0/B) < 1e-6) { - vtrap = (1 + VminV0/B/2) -}else{ - vtrap = (VminV0 / B) /(1 - exp((-1 *VminV0)/B)) - } -} - -UNITSON - - - - - - - - - -? Creating ion concentration - -TITLE Channel: - - - -COMMENT - -ENDCOMMENT - - -UNITS { - (mV) = (millivolt) - (mA) = (milliamp) - (um) = (micrometer) - (l) = (liter) - (molar) = (1/liter) - (mM) = (millimolar) -} - - -NEURON { - SUFFIX - - - USEION READ i WRITE i VALENCE - - - - - - - RANGE i - - RANGE rest_conc - - - RANGE tau - - - RANGE beta - - - RANGE ceiling - - - - RANGE thickness, F - - - RANGE total_current - RANGE volume_pool - - - - RANGE phi - - -} - -ASSIGNED { - - i (mA/cm2) - diam (um) - area (um) -} - -INITIAL { - - - LOCAL pi, shell_inner_diam, cylinderLen, circumference, circumference_shell, volumeOuter, volumeInner, volumeSph, volumeCyl - - pi = 3.14159265 - - shell_inner_diam = diam - (2*thickness) - - - ? Volume of the pool if it is a shell inside a sphere of diameter diam - - volumeSph = (diam*diam*diam) * pi / 6 - (shell_inner_diam*shell_inner_diam*shell_inner_diam)* pi / 6 - - - ? Volume of the pool if it is a cylinder - - circumference = diam * pi - circumference_shell = shell_inner_diam * pi - - cylinderLen = area/circumference - - volumeOuter = (diam * diam/4) * pi * cylinderLen - volumeInner = (shell_inner_diam * shell_inner_diam/4) * pi * cylinderLen - volumeCyl = volumeOuter - volumeInner - - if ((area - (pi * diam * diam)) < 1e-3 && (area - (pi * diam * diam)) > -1e-3 ) { - - ? Assume the segment is a sphere - printf("+++++++ Assume a sphere: %g, %g, %g\n", area, (pi * diam * diam), (area - (pi * diam * diam))) - - volume_pool = volumeSph - - } else { - - ? assume segment is a cylinder - printf("+++++++ Assume a cylinder: %g, %g, %g\n", area, (pi * diam * diam), (area - (pi * diam * diam))) - - volume_pool = volumeCyl - } - - printf("+++++++ Init ca, diam: %g, cylinderLen: %g, volume_pool: %g, volumeSph: %g, volumeCyl: %g, area as sph: %g, area x d: %g, area: %g\n", diam, cylinderLen, volume_pool, volumeSph, volumeCyl, (pi * diam * diam), (area*thickness), area) - - - i = rest_conc - -} - -PARAMETER { - - total_current - rest_conc = - - - - Concentration - (mM) - - - tau = - - - - Time - (ms) - - - beta = - - - - InvTime - (/ms) - - - - ceiling = - - - - Concentration - (mM) - - - F = 96494 (C) - - thickness = - - - - Length - (um) - - volume_pool - - - phi = - - -} - -STATE { - - i (mM) - -} - -BREAKPOINT { - - SOLVE conc METHOD derivimplicit - - if( i < 0 ){ i = 0 } - if( i > ceiling ){ i = ceiling } - - -} - -DERIVATIVE conc { - - * beta - /tau - - - LOCAL thickness_cm, surf_area_cm2, volume_cm3 ? Note, normally dimensions are in um, but curr dens is in mA/cm2, etc - - thickness_cm = thickness *(1e-4) - surf_area_cm2 = area * 1e-8 - volume_cm3 = volume_pool * 1e-12 - - total_current = i * surf_area_cm2 - - - i' = ((-1 * total_current)/( * F * volume_cm3)) - ((i - rest_conc)) - - - i' = - (phi * i) - ((i - rest_conc)) - - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -? Creating synaptic mechanism, based on NEURON source impl of Exp2Syn - - -? Creating NMDA like synaptic mechanism, based on NEURON source impl of Exp2Syn - - -? Creating synaptic mechanism, based on Volker Steuber & Chiara Saviane implementation of 3 decay component facilitating synapse - - -? Creating synaptic mechanism for an electrical synapse - - -? Creating synaptic mechanism, based on Volker Steuber & Chiara Saviane implementation of 3 decay component facilitating synapse - - -? Creating synaptic mechanism, based on Andrew Davison's impl of Song and Abbot's STDP model - - - - yes - no - - - -TITLE Channel: - - - -COMMENT - -ENDCOMMENT - - -UNITS { - (nA) = (nanoamp) - (mV) = (millivolt) - (uS) = (microsiemens) -} - - -NEURON { - POINT_PROCESS - - - - NONSPECIFIC_CURRENT i - RANGE g, i - RANGE weight - - - RANGE vgap : Using a RANGE variable as opposed to POINTER for parallel mode - - - POINTER vgap : Using a POINTER as opposed to RANGE for serial mode - - - - - - RANGE tau_rise, tau_decay - GLOBAL total - - - RANGE _conc, eta, gamma, gblock - GLOBAL total - - - - RANGE tau_decay_2, tau_decay_3, gmax_2, gmax_3, ampl - - - RANGE tau_rec : time course of recovery from synaptic depression - RANGE tau_facil : time course of facilitation - RANGE U, Uinit : release probability and initial value - - - RANGE post_spike_thresh : voltage at which post syn cell will be considered spiking - RANGE t_post_spike, t_pre_spike : times of last post and pre spikes - RANGE stdp_weight_factor : multiplicative factor for weight which changes based on activity - - RANGE M, P - RANGE wmax : maximum synaptic weight which can be reached - RANGE del_weight_ltp, del_weight_ltd : - - RANGE tau_ltp, tau_ltd - - - RANGE i, e, gmax - NONSPECIFIC_CURRENT i - RANGE g, factor, factor_2, factor_3 - - - -} - -PARAMETER { - gmax = - - Conductance - tau_rise = - - Time (ms) <1e-9,1e9> - tau_decay = - - Time (ms) <1e-9,1e9> - e = - - Voltage (mV) - - - _conc = - - Concentration - - eta = - - InvConcentration - - gamma = - - InvVoltage - - - - - - - gmax_2 = - - - 0 - - Conductance - - tau_decay_2 = - - - 0 - - Time (ms) <1e-9,1e9> - - - gmax_2 = 0 - tau_decay_2 = 100000 - - - - - - gmax_3 = - - - 0 - - Conductance - - tau_decay_3 = - - - 0 - - Time (ms) <1e-9,1e9> - - - gmax_3 = 0 - tau_decay_3 = 100000 - - - - - - - - tau_rec = - - Time (ms) < 1e-9, 1e9 > - tau_facil = - - Time (ms) < 0 ,1e9 > - - Uinit = (1) < 0, 1 > :release probability - - - - tau_ltp= - - Time (ms) < 1e-9, 1e9 > - tau_ltd= - - Time (ms) < 1e-9, 1e9 > - - del_weight_ltp= (1) < 0, 1e9 > - del_weight_ltd= (1) < 0, 1e9 > - - wmax= (1) < 0, 1e9 > - - - post_spike_thresh = - - Voltage (mV) - - in_post_spike = 0 : 1 if post cell is spiking, 0 otherwise - - - - v (millivolt) - vgap (millivolt) - g = - - Conductance (microsiemens) - weight = 1 - -} - - -ASSIGNED { - i (nanoamp) -} - -BREAKPOINT { - i = weight * g * (v - vgap) -} - - - -ASSIGNED { - v (mV) - i (nA) - g (uS) - factor - factor_2 - factor_3 - - total (uS) - - R - U - gblock - - M - P - deltaw - t_post_spike (ms) - t_pre_spike (ms) - stdp_weight_factor - -} - -STATE { - A (uS) - B (uS) - C (uS) - D (uS) -} - -INITIAL { - LOCAL tp, tp_2, tp_3 - total = 0 - - if (tau_rise == 0) { - tau_rise = 1e-9 : will effectively give a single exponential timecourse synapse - } - - if (tau_rise/tau_decay > .999999) { - tau_rise = .999999*tau_decay : will result in an "alpha" synapse waveform - } - A = 0 - B = 0 - C = 0 - D = 0 - - tp = (tau_rise*tau_decay)/(tau_decay - tau_rise) * log(tau_decay/tau_rise) - factor = -exp(-tp/tau_rise) + exp(-tp/tau_decay) - factor = 1/factor - - tp_2 = (tau_rise*tau_decay_2)/(tau_decay_2 - tau_rise) * log(tau_decay_2/tau_rise) - factor_2 = -exp(-tp_2/tau_rise) + exp(-tp_2/tau_decay_2) - factor_2 = 1/factor_2 - - tp_3 = (tau_rise*tau_decay_3)/(tau_decay_3 - tau_rise) * log(tau_decay_3/tau_rise) - factor_3 = -exp(-tp_3/tau_rise) + exp(-tp_3/tau_decay_3) - factor_3 = 1/factor_3 - - - - - - M = 0 - P = 0 - deltaw = 0 - t_post_spike = 0 - t_pre_spike = 0 - stdp_weight_factor = 1 - -} - -BREAKPOINT { - SOLVE state METHOD cnexp - - gblock = 1 / (1+ (_conc * eta * exp(-1 * gamma * v))) - g = gmax * gblock * (B - A) - g = (gmax * (B - A)) + (gmax_2 * (C - A)) + (gmax_3 * (D - A)) - g = gmax * (B - A) - - i = g*(v - e) - -} - - -DERIVATIVE state { - A' = -A/tau_rise - B' = -B/tau_decay - C' = -C/tau_decay_2 - D' = -D/tau_decay_3 - -} - -NET_RECEIVE(weight (uS), U, R, tsyn (ms)) { - - LOCAL RUD - - INITIAL { - tsyn = -1 - printf("-- In the INITIAL statement in NET_RECEIVE\n") - U = Uinit - R = 1 - printf("-- t: %g, delt: %g, g: %g, U: %g, R: %g\n", t, t-tsyn, g, U, R) - } - - printf("------------------------------------------------------------\n") - - printf("-- t: %g, delt: %g, g: %g, U: %g, R: %g\n", t, t-tsyn, g, U, R) - - - if (tsyn > 0) { - - R = R * (1-U) * exp(-(t - tsyn)/tau_rec) + 1 - exp(-(t - tsyn)/tau_rec) - - if (tau_facil > 0) { - U = U * exp(-(t - tsyn)/tau_facil) + Uinit * (1 - (U * exp(-(t - tsyn)/tau_facil))) - } else { - U = Uinit - } - - } else { - printf("-- At first spike...\n") - } - - RUD = (U*R) - - printf("-- t: %g, delt: %g, g: %g, U: %g, R: %g, RUD: %g\n", t, t-tsyn, g, U, R, RUD) - - - - printf("------------------------------------------------------------\n") - - - printf("-- SPIKE at time: %f (%g), with weight %g!\n", t, t, weight) - - - - - if (t_post_spike >= 0) { - printf("-- Last post spike ago: %g\n", t-t_post_spike) - } - if (t_pre_spike >= 0) { - printf("-- Last pre spike ago: %g\n", t-t_pre_spike) - } - - if (weight >= 0) { : this is a pre-synaptic spike - - P = P*exp((t_pre_spike-t)/tau_ltp) + del_weight_ltp - - deltaw = wmax * M * exp((t_post_spike - t)/tau_ltd) - - t_pre_spike = t - - } else { : this is a post-synaptic spike - - M = M*exp((t_post_spike-t)/tau_ltd) - del_weight_ltd - - //Todo: double check this! - //? deltaw = wmax * P * exp(-(t - t_pre_spike)/tau_ltp) - deltaw = deltaw + wmax * P * exp(-(t - t_pre_spike)/tau_ltp) - - t_post_spike = t - - } - - - - - stdp_weight_factor = stdp_weight_factor + deltaw - - if (stdp_weight_factor > wmax) { stdp_weight_factor = wmax} - if (stdp_weight_factor < 0) { stdp_weight_factor = 0} - - - printf("pg-- stdp_weight_factor: %g, deltaw: %g, P: %g, M: %g\n", stdp_weight_factor,deltaw, P, M) - - if (weight >= 0) { : this is a pre-synaptic spike - - - - - LOCAL Ajump, Bjump, Cjump, Djump - Bjump = weight*factor*stdp_weight_factor - Cjump = weight*factor_2*stdp_weight_factor - Djump = weight*factor_3*stdp_weight_factor - - Ajump = (gmax*Bjump + gmax_2*Cjump + gmax_3*Djump)/(gmax + gmax_2 + gmax_3) - - state_discontinuity(A, A + Ajump) - state_discontinuity(B, B + Bjump) - state_discontinuity(C, C + Cjump) - state_discontinuity(D, D + Djump) - - - state_discontinuity(A, A + weight*factor*RUD*stdp_weight_factor) - state_discontinuity(B, B + weight*factor*RUD*stdp_weight_factor) - - - - - - - tsyn = t - - - } - - -} - - - - - - - - - - - - - - - - - - - - if () { - = - } else { - = - } - - = - - - - - - - diff --git a/tests/python/two_cells_nml_1.8/cellMechanisms/KConductance/ChannelML_v1.8.1_PSICS.xsl b/tests/python/two_cells_nml_1.8/cellMechanisms/KConductance/ChannelML_v1.8.1_PSICS.xsl deleted file mode 100644 index c31895cf..00000000 --- a/tests/python/two_cells_nml_1.8/cellMechanisms/KConductance/ChannelML_v1.8.1_PSICS.xsl +++ /dev/null @@ -1,471 +0,0 @@ - - - - - - - - -0 - -30 - - - - true - false - - - - - - mV - V - - - - - - per_ms - per_s - - - - - - - - - This is a PSICS channel model file generated from a ChannelML v1.8.1 file. - - - - - - - - - - - - Error: this channel contains an Integrate and Fire mechanisms that cannot be mapped to PSICS. - - - - - - - - - - - - - - - Error: Ion concentration pools not yet supported in PSICS! - - - - - Error: Synapses not yet supported in PSICS! - - - - - - Error: the channel has a voltage_conc gate that is not supported in PSICS - - - Error: the channel has a conc dependent gate that is not supported in PSICS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - double offset = ; - v = v + offset; - - - - - - double temp_adj_ = 1; - - - - - - - double temp_adj_ = Math.pow(, (temperature - )/10); - - - double temp_adj_ = ; - - - - - - - - - - - - - - double = 0; - - - - - - - - - - - - - - - - - - - - - - - tau - - - - - tau - - - - - - - tau = 1/(alpha + beta); - - - tau = tau/temp_adj_; - - - - - - - inf - - - - - - inf - - - - - - - - inf = alpha/(alpha + beta); - - - - - - double rate = 0; - double scale = 0; - double midpoint = 0; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - unsupported transition type - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - double = 0; - rate = - - InvTime - ; - - - rate = - - Time - ; - - - rate = ; - - - double = 0; - rate = ; // Warning: unrecognised rate variable! Don't know how to convert units! - - - scale = - - Voltage - ; - midpoint = - - Voltage - ; - - - - - = rate * Math.exp((v - midpoint) / scale); - - - = rate / (Math.exp((v - midpoint) / scale) + 1); - - - if ( 1e-6 > (Math.abs((v - midpoint)/ scale))) { - = rate * (1 + (v - midpoint)/scale/2); - } else { - = rate * ((v - midpoint) / scale) /(1 - (Math.exp(-1 * (v - midpoint)/scale))); - } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - exp - Math.exp - - - - - - celsius - temperature - - - - - - - - - - - if () { - = ; - } else { - = ; - } - - - = ; - - - - - - \ No newline at end of file diff --git a/tests/python/two_cells_nml_1.8/cellMechanisms/KConductance/KChannel_HH.xml b/tests/python/two_cells_nml_1.8/cellMechanisms/KConductance/KChannel_HH.xml deleted file mode 100644 index dfd1d3c6..00000000 --- a/tests/python/two_cells_nml_1.8/cellMechanisms/KConductance/KChannel_HH.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - ChannelML file containing a single Channel description - - - - - Equations adapted from HH paper for modern convention of external potential being zero - - Padraig Gleeson - - - - Simple example of K conductance in squid giant axon. Based on channel from Hodgkin and Huxley 1952 - - - - Padraig Gleeson - UCL - p.gleeson - at - ucl.ac.uk - - - - - A. L. Hodgkin and A. F. Huxley, A quantitative description of membrane current and its application - to conduction and excitation in nerve, J. Physiol., vol. 117, pp. 500-544, 1952. - http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&db=pubmed&dopt=Abstract&list_uids=12991237 - - - - K channels - http://senselab.med.yale.edu/senselab/NeuronDB/channelGene2.htm#table3 - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tests/python/two_cells_nml_1.8/cellMechanisms/KConductance/properties.xml b/tests/python/two_cells_nml_1.8/cellMechanisms/KConductance/properties.xml deleted file mode 100644 index 393415e3..00000000 --- a/tests/python/two_cells_nml_1.8/cellMechanisms/KConductance/properties.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - -Properties associated with the Cell Mechanism which allow it to be loaded into neuroConstruct. - -Note the following: - The Cell Mechanism name should not contain spaces and should match the name of the directory it's in - The name and description here will be replaced by the corresponding values in a ChannelML file if found - The filenames for the mappings are relative to the cellMechanism/(cellMechInstanceName) directory - Mechanism Type should only have values: Channel mechanism, Synaptic mechanism, Ion concentration, Point process, Gap junction - - -Simple example of K conductance in squid giant axon. Based on channel from Hodgkin and Huxley 1952 -ChannelML_v1.8.1_NEURONmod.xsl -ChannelML_v1.8.1_GENESIStab.xsl -false -ChannelML based Cell Mechanism -true -Channel mechanism -KChannel_HH.xml -ChannelML_v1.8.1_PSICS.xsl -false -KConductance -Template based ChannelML file - diff --git a/tests/python/two_cells_nml_1.8/cellMechanisms/LeakConductance/ChannelML_v1.8.1_GENESIStab.xsl b/tests/python/two_cells_nml_1.8/cellMechanisms/LeakConductance/ChannelML_v1.8.1_GENESIStab.xsl deleted file mode 100644 index dd6ea88c..00000000 --- a/tests/python/two_cells_nml_1.8/cellMechanisms/LeakConductance/ChannelML_v1.8.1_GENESIStab.xsl +++ /dev/null @@ -1,1503 +0,0 @@ - - - - - - - - - -no - - - - - -Physiological Units - - - - -// This is a GENESIS script file generated from a ChannelML v1.8.1 file -// The ChannelML file is mapped onto a tabchannel object - - -// Units of ChannelML file: , units of GENESIS file generated: - - - -/* - -*/ - - - - - *** Note: Kinetic scheme based ChannelML descriptions cannot be mapped on to GENESIS at the present time. *** - - - *** Note: Integrate and Fire mechanisms cannot be mapped on to GENESIS at the present time. *** - - - - - - - - - - - - - - - - - - - - - - - no - yes - - - - - - - yes - yes - no - - - - - - - no - yes - - - - - - - yes - no - - - - -// NOTE: There are parameters in the ChannelML file, so there will be a seperate init of the table -extern init_ - - - - -function make_ - - - /* - - - Reference: - Pubmed: - */ - - - str chanpath = "/library/" - - if ({exists {chanpath}}) - return - end - - - - - - - - - - - - - - - - - - - create leakage {chanpath} - - - create tabchannel {chanpath} - - - create tab2Dchannel {chanpath} - - - create tabchannel {chanpath} - - - - setfield {chanpath} \ - Ek - - Voltage - \ - Ik 0 \ - Xpower - \ - Ypower - \ - Zpower - \ - Zpower 1 - \ - Xpower - \ - Ypower - \ - Zpower - \ - Zpower 1 - \ - Zpower - - - - - - setfield {chanpath} Gk - - Conductance Density - - - - - - setfield {chanpath} Gk - - Conductance Density - - - - - - setfield {chanpath} \ - Gbar - - Conductance Density - \ - Gk 0 - - - - - setfield {chanpath} \ - Gbar - - Conductance Density - \ - Gk 0 - - - - - - - // There are parameters in the ChannelML file, which may be changed after initialisation which could mean the tables - // will need to be updated. Seperating out the generation of the table values into init function. - - - addfield {chanpath} - setfield {chanpath} // Note units of this will be determined by its usage in the generic functions - - - init_ {chanpath} // Initialisation of the tables - -end // End of main channel definition - - -// calling this function after changing the extra parameters/added fields will updated the table -function init_(chanpath) - - str chanpath - - // Retrieving the param values as local variables - - float = {getfield {chanpath} } - - - - - - - - - // There is a Q10 factor which will alter the tau of the gates - - - - - float temp_adj_ = {pow {(celsius - )/10}} - - float temp_adj_ = - - - - - {pow {(celsius - )/10}} - - float temp_adj_ = - - float temp_adj_ = - - - - - float temp_adj_ = - - - float temp_adj_ = - - - - - - - - // No Q10 temperature adjustment found - float temp_adj_ = 1 - - float temp_adj_ = 1 - - - - - - - - - - 100 - 0.1 - - - - - Voltage - - - - - - - - - -100 - -0.1 - - - - - Voltage - - - - - - - - 400 - - - - - float tab_divs = - - - - float v_min = - - float v_max = - - float v, dv, i - - - - - - - - X - Y - Z - - - - // Creating table for gate , using name for it here - - float dv = ({v_max} - {v_min})/{tab_divs} - - - - - - - - - // Channel is dependent on concentration of: , rate equations will involve variable: - float c - float conc_min = - - Concentration - - float conc_max = - - Concentration - - - float dc = ({conc_max} - {conc_min})/{tab_divs} - - float = {conc_min} - - - - - // Setting up the volt/conc dependent 2D table - setfield {chanpath} index {VOLT_C1_INDEX} // assumes all gates are volt/conc dep - - - - call {chanpath} TABCREATE {tab_divs} {v_min} {v_max} {tab_divs} {conc_min} {conc_max} - - - - call {chanpath} TABCREATE Z {tab_divs} {conc_min} {conc_max} - - - for (c = 0; c <= ({tab_divs}); c = c + 1) - - - - call {chanpath} TABCREATE {tab_divs} {v_min} {v_max} - - - - - v = {v_min} - - - // There is a voltage offset of . This will shift the dependency of the rate equations - v = v - - - Voltage - - - - - for (i = 0; i <= ({tab_divs}); i = i + 1) - - - - - // Looking at rate: - - float - - - - - float A, B, k, V0 - - - - - - - - - - - - // Found a generic form of rate equation for , using expression: - // Will translate this for GENESIS compatibility... - - - // Equation (and all ChannelML file values) in but this script in - - v = v * - 1 - InvVoltage - // temporarily set v to units of equation... - - - // Equation depends on alpha/beta, so converting them too... - alpha = alpha * - 1 - Time - - beta = beta * - 1 - Time - - - - - // Equation depends on alpha, so converting it... - alpha = alpha * - 1 - Time - - - - - - // Equation depends on concentration, so converting that too... - - = * - 1 - InvConcentration - - - - - - - - - - - - - - - - - - - v = v * - 1 - Voltage - // reset v - - - alpha = alpha * - 1 - InvTime - // resetting alpha - beta = beta * - 1 - InvTime - // resetting beta - - - - alpha = alpha * - 1 - InvTime - // resetting alpha - - - - = * - 1 - Concentration - // resetting ca_conc - - - - - - - - - - // Set correct units of - - = * - 1 - InvTime - - - - - - - // Set correct units of - - = * - 1 - Time - - - - - - - - ? ERROR: Unrecognised form of the rate equation for ... - - - - - - - - - table[{i}] - table[{i}][{c}] - - - - - - - - // Using the alpha and beta expressions to populate the tables - - float tau = 1/(temp_adj_ * (alpha + beta)) - echo "Tab : v: "{v} ", a: "{alpha} ", b: "{beta} ", tau: "{tau} - - echo "Tab : conc: " {} - - - setfield {chanpath} _A-> {temp_adj_ * alpha} - setfield {chanpath} _B-> {temp_adj_ * (alpha + beta)} - - - - // Evaluating the tau and inf expressions - - - - float tau = 1/(temp_adj_ * (alpha + beta)) - - - tau = tau/temp_adj_ - - - - float inf = alpha/(alpha + beta) - - - echo "Tab : v: "{v} ", tau: "{tau} ", inf: "{inf} - - echo "Tab : conc: " {} - - - - - // Working out the "real" alpha and beta expressions from the tau and inf - - float alpha - - float beta - alpha = inf / tau - beta = (1- inf)/tau - - - setfield {chanpath} _A-> {alpha} - setfield {chanpath} _B-> {alpha + beta} - - - - - - - - // Looking at rate: - - float - - - - - float A, B, Vhalf - - - - - - - - - - - // Found a generic form of rate equation for , using expression: - // Will translate this for GENESIS compatibility... - - - // Equation (and all ChannelML file values) in but this script in - - v = v * - 1 - InvVoltage - // temporarily set v to units of equation... - - - // Equation depends on alpha/beta, so converting them too... - alpha = alpha * - 1 - Time - - beta = beta * - 1 - Time - - - - - // Equation depends on alpha, so converting it... - alpha = alpha * - 1 - Time - - - - - - // Equation depends on concentration, so converting that too... - - = * - 1 - InvConcentration - - - - - - - - - - - - - - - - - - - v = v * - 1 - Voltage - // reset v - - - alpha = alpha * - 1 - InvTime - // resetting alpha - beta = beta * - 1 - InvTime - // resetting beta - - - - alpha = alpha * - 1 - InvTime - // resetting alpha - - - - = * - 1 - Concentration - // resetting ca_conc - - - - - - - - - - // Set correct units of - - = * - 1 - InvTime - - - - - - - // Set correct units of - - = * - 1 - Time - - - - - - - - ? ERROR: Unrecognised form of the rate equation for ... - - - - - - - - - table[{c}] - table[{i}] - table[{i}][{c}] - - - - - - - - // Using the alpha and beta expressions to populate the tables - - float tau = 1/(temp_adj_ * (alpha + beta)) - echo "Tab : v: "{v} ", a: "{alpha} ", b: "{beta} ", tau: "{tau} - - echo "Tab : conc: " {} - - - - - - setfield {chanpath} _A-> {temp_adj_ * alpha} - setfield {chanpath} _B-> {temp_adj_ * (alpha + beta)} - - - setfield {chanpath} Z_A-> {temp_adj_ * alpha} - setfield {chanpath} Z_B-> {temp_adj_ * (alpha + beta)} - - - - - - - // Evaluating the tau and inf expressions - - - - float tau = 1/(temp_adj_ * (alpha + beta)) - - - tau = tau/temp_adj_ - - - - float inf = alpha/(alpha + beta) - - - echo "Tab : v: "{v} ", tau: "{tau} ", inf: "{inf} - - echo "Tab : conc: " {} - - - - - // Working out the "real" alpha and beta expressions from the tau and inf - - float alpha - - float beta - alpha = inf / tau - beta = (1- inf)/tau - - - setfield {chanpath} _A-> {alpha} - setfield {chanpath} _B-> {alpha + beta} - - - - - - - v = v + dv - - end // end of for (i = 0; i <= ({tab_divs}); i = i + 1) - - - - - - = + dc - - - = + dc - - - - end // end of for (c = 0; c <= ({tab_divs}); c = c + 1) - - - - - - - - setfield {chanpath} _A->calc_mode 1 _B->calc_mode 1 - - - setfield {chanpath} Z_conc 1 - setfield {chanpath} Z_A->calc_mode 1 Z_B->calc_mode 1 - - - - - - - - - // Adding voltage independent concentration term - - - float conc_min = - - Concentration - - float conc_max = - - Concentration - - - float dc = ({conc_max} - {conc_min})/{tab_divs} - - float = {conc_min} - - call {chanpath} TABCREATE Z {tab_divs} {conc_min} {conc_max} - - float const_state - - for (i = 0; i <= ({tab_divs}); i = i + 1) - - - - - // Equation is in different set of units... - = * - 1 - InvConcentration - - - - - - - const_state - - - - - - - - - // Converting back... - = * - 1 - Concentration - - - - - - - setfield {chanpath} Z_A->table[{i}] {0} - setfield {chanpath} Z_B->table[{i}] {const_state} - - - = + dc - - end - - tweaktau {chanpath} Z - - - -end - - - - - - - - - - - -function __catchCeiling__(action) - - call . PROCESS -parent // Carry out all normal actions - - float caval = {getfield Ca} - float cabase = {getfield Ca_base} - float ceil = {getfield ceiling} - - if (caval > ceil) - setfield Ca {ceil} - setfield C {ceil - cabase} - end - -end - - -function make_ - - - /* - - */ - - - str chanpath = "/library/" - - if ({exists {chanpath}}) - return - end - - - - - create Ca_concen {chanpath} - - - - - - - - - - - Time - - - { 1.0 / - - - - InvTime - } - - - - - // Setting params for a decaying_pool_model - - setfield {chanpath} \ - tau \ - Ca_base - - - - Concentration - - - - addfield {chanpath} beta -description "Inverse of tau, needed as this is parameter used in some implementations. If beta > 0, this will be used in preference to tau" - setfield {chanpath} beta -1 - - - - setfield {chanpath} \ - thick - - - - Length - - - - - - - addfield {chanpath} ceiling -description "Maximum concentration pool will be allowed reach" - setfield {chanpath} ceiling - - - - Concentration - - - addaction {chanpath} PROCESS __catchCeiling__ - - - - -end - -function init_(chanpath) - - float curr_beta = {getfield {chanpath} beta} - if (curr_beta > 0) - - echo "Using the value of beta " {curr_beta} " in place of tau" - setfield {chanpath} tau {1 / {curr_beta}} - else - echo "Keeping existing tau: " {getfield {chanpath} tau} " not beta: " {curr_beta} - end - - -end - - - - - - - - - - - -function connectGapJunction_(compartmentA, compartmentB, weight) - - // Note: implementation based on suggestion of Reinoud Maex - - str compartmentA - str compartmentB - float conductance = - - Conductance - - str diffampname = {strcat "diffamp_" {rand 0 99999999}} // to ensure a different diffamp name for each gap junc on this comp - - create diffamp {compartmentA}/{diffampname} - - addmsg {compartmentA} {compartmentA}/{diffampname} PLUS Vm - addmsg {compartmentB} {compartmentA}/{diffampname} MINUS Vm - - setfield {compartmentA}/{diffampname} gain {conductance * weight} - setfield {compartmentA}/{diffampname} saturation 10e8 - - addmsg {compartmentA}/{diffampname} {compartmentB} INJECT output - - - create diffamp {compartmentB}/{diffampname} - - addmsg {compartmentB} {compartmentB}/{diffampname} PLUS Vm - addmsg {compartmentA} {compartmentB}/{diffampname} MINUS Vm - - setfield {compartmentB}/{diffampname} gain {conductance * weight} - setfield {compartmentB}/{diffampname} saturation 10e8 - - addmsg {compartmentB}/{diffampname} {compartmentA} INJECT output - -end - - - -function makechannel_(compartment, name) - - /* - - */ - - str compartment - str name - - if (!({exists {compartment}/{name}})) - - create synchan {compartment}/{name} - - setfield ^ \ - Ek - - Voltage \ - tau1 - - Time \ - tau2 - - Time \ - gmax - - Conductance - - float tau2 = {getfield {compartment}/{name} tau2} - - if (tau2 == 0) // Single exponential synapse - setfield {compartment}/{name} tau2 1e-9 - end - - addmsg {compartment}/{name} {compartment} CHANNEL Gk Ek - addmsg {compartment} {compartment}/{name} VOLTAGE Vm - - - - setfield ^ \ - Ek - - Voltage \ - tau1 - - Time \ - tau2 - - Time \ - gmax - - Conductance - - float tau1 = {getfield {compartment}/{name} tau1} - if (tau1 == 0) - setfield {compartment}/{name} tau1 1e-9 - end - - addmsg {compartment} {compartment}/{name} VOLTAGE Vm - - if (! {exists {compartment}/{name}/Mg_BLOCK}) - - float CMg = - - Concentration - - float eta = - - InvConcentration - - float gamma = - - InvVoltage - - create Mg_block {compartment}/{name}/Mg_BLOCK - - setfield {compartment}/{name}/Mg_BLOCK \ - CMg {CMg} \ - KMg_A {1/eta} \ - KMg_B {1.0/gamma} - - addmsg {compartment}/{name} {compartment}/{name}/Mg_BLOCK CHANNEL Gk Ek - addmsg {compartment}/{name}/Mg_BLOCK {compartment} CHANNEL Gk Ek - addmsg {compartment} {compartment}/{name}/Mg_BLOCK VOLTAGE Vm - end - - - - end - -end - - - - - - - - - - - - - 1 - 2 - 3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - si - - - - - - - - - - - - - - - - - // ChannelML form of equation: = , with params: - // A = , k = , d = , in units: - - - - A = - - InvTime - - - - A = - - Time - - - - A = - - - A = // Warning: unrecognised rate variable! Don't know how to convert units! - - - k = - - InvVoltage - - B = 1/k - V0 = - - Voltage - - - - - - - = A * {exp {(v - V0) / B}} - - - = A / ( {exp {(v - V0) / B}} + 1) - - - - if ( {abs {(v - V0)/ B}} < 1e-6) - = A * (1 + (v - V0)/B/2) - else - = A * ((v - V0) / B) /(1 - {exp {-1 * (v - V0)/B}}) - end - - - - - - - - = 1 // Gate is not present, power should = 0 so value of is not relevant - - - - - - - - - - - - - - - - // ChannelML form of equation: which is of form , with params: - // A = , B = , Vhalf = , in units: - - - - A = - - InvTime - - - - A = - - Time - - - - A = - - - A = // Warning: unrecognised rate variable! Don't know how to convert units! - - - B = - - Voltage - - Vhalf = - - Voltage - - - - - - - = A * {exp {(v - Vhalf) / B}} - - - = A / ( {exp {(v - Vhalf) / B}} + 1) - - - - if ( {abs {(v - Vhalf)/ B}} < 1e-6) - = A * (1 + (v - Vhalf)/B/2) - else - = A * ((v - Vhalf) / B) /(1 - {exp {-1 * (v - Vhalf)/B}}) - end - - - - - - - - = 1 // Gate is not present, power should = 0 so value of is not relevant - - - - - - - - - - - - - - - - - - if () - = - else - = - end - - - = - - - - - \ No newline at end of file diff --git a/tests/python/two_cells_nml_1.8/cellMechanisms/LeakConductance/ChannelML_v1.8.1_NEURONmod.xsl b/tests/python/two_cells_nml_1.8/cellMechanisms/LeakConductance/ChannelML_v1.8.1_NEURONmod.xsl deleted file mode 100644 index 04a6a65a..00000000 --- a/tests/python/two_cells_nml_1.8/cellMechanisms/LeakConductance/ChannelML_v1.8.1_NEURONmod.xsl +++ /dev/null @@ -1,1974 +0,0 @@ - - - - - - - - - - - - - -0 - -0 - -1 - -0 - - - - - - -? This is a NEURON mod file generated from a ChannelML file - -? Unit system of original ChannelML file: - - - - *** Note: Kinetic scheme based ChannelML description cannot be mapped in to mod files in this version. *** - Please use the alternative XSL file which maps on to NEURON's KS Channel Builder format - (should be ChannelML_v1.X.X_NEURONChanBuild.xsl) - - - -COMMENT - -ENDCOMMENT - - - - - - - - - - - - - - -TITLE Channel: - - - -COMMENT - -ENDCOMMENT - - -UNITS { - (mA) = (milliamp) - (mV) = (millivolt) - (S) = (siemens) - (um) = (micrometer) - (molar) = (1/liter) - (mM) = (millimolar) - (l) = (liter) -} - - - - yes - yes - no - - - - - - yes - yes - no - - - -NEURON { - - - SUFFIX - - - - - USEION WRITE i VALENCE ? reversal potential of ion is **NOT READ**, outgoing current is written - - - USEION READ i VALENCE ? internal concentration of ion is read - - - USEION READ i WRITE i VALENCE ? outgoing current of ion is read, internal concentration is written - - - USEION READ e WRITE i VALENCE ? reversal potential of ion is read, outgoing current is written - - - - - - VALENCE - VALENCE 1 - USEION READ e WRITE i ? reversal potential of ion is read, outgoing current is written - - - - - VALENCE - VALENCE 1 - USEION READ i ? internal concentration of ion is read - - - - VALENCE - VALENCE 1 - USEION READ i ? internal concentration of ion is read - - - - - - ? A non specific current is present - RANGE e - NONSPECIFIC_CURRENT i - - RANGE gmax, gion - - - RANGE inf, tau - - , __ - - - - - - RANGE inf, tau - - - - - RANGE - - - - - - - - RANGE - - - - ? Note this implementation is based on that used in the COBA based I and F model as used in Brette et al (2006) - ? and the NEURON script files from http://senselab.med.yale.edu/SenseLab/ModelDB/ShowModel.asp?model=83319 - - POINT_PROCESS - GLOBAL thresh, t_refrac, v_reset, g_refrac - NONSPECIFIC_CURRENT i - - -} - -PARAMETER { - - - gmax = - - Conductance Density - (S/cm2) ? default value, should be overwritten when conductance placed on cell - - e = - - Voltage - (mV) ? default value, should be overwritten when conductance placed on cell - - - - - __ = - - - - - - - gmax = - - Conductance Density - (S/cm2) ? default value, should be overwritten when conductance placed on cell - - e = - - Voltage - (mV) ? default value, should be overwritten when conductance placed on cell - - - - thresh = - - Voltage - (mV) - t_refrac = - - Time - (ms) - v_reset = - - Voltage - (mV) - g_refrac = - - Conductance - (uS) - - - - = : Note units of this will be determined by its usage in the generic functions - -} - - - -ASSIGNED { - - - v (mV) - - - i (mA/cm2) - - - celsius (degC) - - - - ? The internal concentration of ion: is used in the rate equations... - i (mM) - - - ? Error!! ion: with role="SignallingSubstance" shouldn't be in a channel_type... - - - ? Reversal potential of - e (mV) - ? The outward flow of ion: calculated by rate equations... - i (mA/cm2) - - - - - - ? Reversal potential of - e (mV) - ? The outward flow of ion: calculated by rate equations... - i (mA/cm2) - - - - ? The internal concentration of ion: is used in the rate equations... - i (mM) - - - ? The internal concentration of ion: is used in the rate equations... - i (mM) - - - gion (S/cm2) - - inf - tau (ms) - - - inf - tau (ms) - - - - - (/ms) - - - - - - - - - i (nanoamp) - v (millivolt) - g (microsiemens) - - - -} - -BREAKPOINT { LOCAL g_factor, - - -LOCAL g_factor, - - - - - - - - - i = gmax*(v - e) - - - - - - SOLVE kin METHOD sparse - - - SOLVE states METHOD derivimplicit - - - - SOLVE states METHOD cnexp - - - - gion = gmax*(( - *)^) - - - - - gion = gmax * (( + (*) )^) - - - - - = i / - 1 - Concentration - - - g_factor - - - - - - gion = gion * g_factor - - - - - i = gion*(v - e) - - - - i = gion*(v - e) - - - - - - i = g*(v - v_reset) - - - -} - - - - -INITIAL { - net_send(0, 3) - g = 0 -} - -NET_RECEIVE(w) { - - if (flag == 1) { - v = v_reset - g = g_refrac - - printf("+++++++ Spiking cell at: %g, v: %g\n", t, v) - - net_event(t) - net_send(t_refrac, 2) - }else if (flag == 2) { - g = 0 - - printf("+++++++ Finished refract at: %g, v: %g\n", t, v) - - }else if (flag == 3) { - WATCH (v > thresh) 1 - } -} - - - -INITIAL { - - - - Voltage - - - - e = - - - - - e = - - - - - - settables(v,cai) - - - rates(v) - - - - - - = inf - - = : Hard coded initialisation!! - - - = : Hard coded initialisation!! - - - - - - - - - = inf - - = : Hard coded initialisation!! - - SOLVE kin STEADYSTATE sparse - - - -} - -STATE { - - - - - - - - - - - - - - - - -} - - - - -KINETIC kin { - - settables(v,cai) - - rates(v) - - - - - - - - - - - - ~ <-> (, ) - - CONSERVE + = 1 -} - - - - -DERIVATIVE states { - - settables(v,cai) - - rates(v) - - - - ' = (inf - )/tau - - - - - - ' = (inf - )/tau - - - - - - ' = 0 + * (1 - ) - - * - - - - - - -} - - - - - - - PROCEDURE settables(v(mV), cai(mM)) { - PROCEDURE rates(v(mV)) { - - - ? Note: not all of these may be used, depending on the form of rate equations - LOCAL alpha, beta, tau, inf, gamma, zeta, - , - , temp_adj_, A__, k__, d__ - - - , temp_adj_ - , - A__, B__, Vhalf__ - - - - - - - - - - - - - 100 - - - - Voltage - - - - - - - - -100 - - - - Voltage - - - - - - - - 400 - - - - - - - - - - TABLE inf, tau, - inf, tau, - DEPEND celsius - - , __ - FROM TO WITH - - - : NOT USING TABLE: as there are some changable parameters ( ) - : which may be different on different sections, using a TABLE for computing these values can lead to errors. - - - - - - - UNITSOFF - - - ? There is a Q10 factor which will alter the tau of the gates - - - - - temp_adj_ = ^((celsius - )/10) - - temp_adj_ = - - - - - ^((celsius - )/10) - - temp_adj_ = - - - temp_adj_ = - - - - - temp_adj_ = - - - temp_adj_ = - - - - - - - - temp_adj_ = 1 - - temp_adj_ = 1 - - - - - - - - ? There is a voltage offset of . This will shift the dependency of the rate equations - v = v - ( - - Voltage - ) - - - - - - - - - - - - ? Gate depends on the concentration of - - = i ? In NEURON, the variable for the concentration of is i - - - ? *** Adding rate equations for gate: *** - - - - - - - ? Found a parameterised form of rate equation for , using expression: - A*(k*(v-d)) / (1 - exp(-(k*(v-d)))) - A*exp(k*(v-d)) - A / (1 + exp(k*(v-d))) - Unsupported expression type! - - - A__ - k__ - d__ - - - - __ = - - - - - ? Unit system in ChannelML file is SI units, therefore need to - ? convert these to NEURON quanities... - - - = * - 1 - InvTime - ? 1/ms - - - = * - 1 - Time - ? ms - - - = ? Dimensionless - - - = * - 1 - InvVoltage - ? mV - = * - 1 - Voltage - ? mV - - - - - - - - = * exp((v - ) * ) - - - - - = / (exp((v - ) * ) + 1) - - - - - = * vtrap((v - ), (1/)) - - - - - - - - - - ? Found a generic form of the rate equation for , using expression: - - - ? Note: Equation (and all ChannelML file values) in so need to convert v first... - - v = v * - 1 - InvVoltage - ? temporarily set v to units of equation... - - - - ? Equation depends on alpha/beta, so converting them too... - alpha = alpha * - 1 - Time - - beta = beta * - 1 - Time - - - - - - ? Equations can depend on concentration. NEURON uses 'SI Units' internally for concentration, - ? but ChannelML file is in Physiological Units... - = / - 1 - Concentration - - - - - - - - - - - - - - - - ? Set correct units of for NEURON - - = * - 1 - InvTime - - - - - ? Set correct units of for NEURON - - = * - 1 - Time - - - - v = v * - 1 - Voltage - ? reset v - - alpha = alpha * - 1 - InvTime - ? resetting alpha - beta = beta * - 1 - InvTime - ? resetting beta - - - - ? Resetting concentration... - = * - 1 - Concentration - - - - - - - - ? ERROR: Unrecognised form of the rate equation for - - - - - - - tau = tau/temp_adj_ - - - - - inf = inf - - - - - - - - - - tau = 1/(temp_adj_*(alpha + beta)) - - - - - inf = alpha/(alpha + beta) - - - - - ? *** Finished rate equations for gate: *** - - - - - - - - - - - ? Gate depends on the concentration of - - = i ? In NEURON, the variable for the concentration of is i - - - - - - - - - - - ? *** Adding rate equations for gate: *** - - - - - - - - ? Found a parameterised form of rate equation for , using expression: - A*((v-Vhalf)/B) / (1 - exp(-((v-Vhalf)/B))) - A*exp((v-Vhalf)/B) - A / (1 + exp((v-Vhalf)/B)) - Unsupported expression type! - - - A__ - B__ - Vhalf__ - - - - = - - = - - = - - - - ? Unit system in ChannelML file is SI units, therefore need to convert these to NEURON quanities... - - - - = * - 1 - InvTime - ? 1/ms - - - = * - 1 - Time - ? ms - - - = ? Dimensionless - - - = * - 1 - Voltage - ? mV - = * - 1 - Voltage - ? mV - - - - - - - = * exp((v - ) / ) - - - - - = / (exp((v - ) / ) + 1) - - - - - = * vtrap((v - ), ) - - - - - - - - - - ? Found a generic form of the rate equation for , using expression: - - - ? Note: Equation (and all ChannelML file values) in so need to convert v first... - - v = v * - 1 - InvVoltage - ? temporarily set v to units of equation... - - - - ? Equation depends on alpha/beta, so converting them too... - alpha = alpha * - 1 - Time - - beta = beta * - 1 - Time - - - - - - ? Equations can depend on concentration. NEURON uses 'SI Units' internally for concentration, - ? but the ChannelML file is in Physiological Units... - = / - 1 - Concentration - - - - - - - - - - - - - - - - ? Set correct units of for NEURON - - = * - 1 - InvTime - - - - - ? Set correct units of for NEURON - - = * - 1 - Time - - - - v = v * - 1 - Voltage - ? reset v - - alpha = alpha * - 1 - InvTime - ? resetting alpha - beta = beta * - 1 - InvTime - ? resetting beta - - - - ? Resetting concentration... - = * - 1 - Concentration - - - - - - - - ? ERROR: Unrecognised form of the rate equation for - - - - - - = * temp_adj_ ? Applying temp adj here as channel has KS description - - - - - tau = tau/temp_adj_ - - - - - inf = inf - - - - - - - - - - - tau = 1/(temp_adj_*(alpha + beta)) - - - - - inf = alpha/(alpha + beta) - - - - - - ? *** Finished rate equations for gate: *** - - - -} - - -? Function to assist with parameterised expressions of type linoid/exp_linear - -FUNCTION vtrap(VminV0, B) { - if (fabs(VminV0/B) < 1e-6) { - vtrap = (1 + VminV0/B/2) -}else{ - vtrap = (VminV0 / B) /(1 - exp((-1 *VminV0)/B)) - } -} - -UNITSON - - - - - - - - - -? Creating ion concentration - -TITLE Channel: - - - -COMMENT - -ENDCOMMENT - - -UNITS { - (mV) = (millivolt) - (mA) = (milliamp) - (um) = (micrometer) - (l) = (liter) - (molar) = (1/liter) - (mM) = (millimolar) -} - - -NEURON { - SUFFIX - - - USEION READ i WRITE i VALENCE - - - - - - - RANGE i - - RANGE rest_conc - - - RANGE tau - - - RANGE beta - - - RANGE ceiling - - - - RANGE thickness, F - - - RANGE total_current - RANGE volume_pool - - - - RANGE phi - - -} - -ASSIGNED { - - i (mA/cm2) - diam (um) - area (um) -} - -INITIAL { - - - LOCAL pi, shell_inner_diam, cylinderLen, circumference, circumference_shell, volumeOuter, volumeInner, volumeSph, volumeCyl - - pi = 3.14159265 - - shell_inner_diam = diam - (2*thickness) - - - ? Volume of the pool if it is a shell inside a sphere of diameter diam - - volumeSph = (diam*diam*diam) * pi / 6 - (shell_inner_diam*shell_inner_diam*shell_inner_diam)* pi / 6 - - - ? Volume of the pool if it is a cylinder - - circumference = diam * pi - circumference_shell = shell_inner_diam * pi - - cylinderLen = area/circumference - - volumeOuter = (diam * diam/4) * pi * cylinderLen - volumeInner = (shell_inner_diam * shell_inner_diam/4) * pi * cylinderLen - volumeCyl = volumeOuter - volumeInner - - if ((area - (pi * diam * diam)) < 1e-3 && (area - (pi * diam * diam)) > -1e-3 ) { - - ? Assume the segment is a sphere - printf("+++++++ Assume a sphere: %g, %g, %g\n", area, (pi * diam * diam), (area - (pi * diam * diam))) - - volume_pool = volumeSph - - } else { - - ? assume segment is a cylinder - printf("+++++++ Assume a cylinder: %g, %g, %g\n", area, (pi * diam * diam), (area - (pi * diam * diam))) - - volume_pool = volumeCyl - } - - printf("+++++++ Init ca, diam: %g, cylinderLen: %g, volume_pool: %g, volumeSph: %g, volumeCyl: %g, area as sph: %g, area x d: %g, area: %g\n", diam, cylinderLen, volume_pool, volumeSph, volumeCyl, (pi * diam * diam), (area*thickness), area) - - - i = rest_conc - -} - -PARAMETER { - - total_current - rest_conc = - - - - Concentration - (mM) - - - tau = - - - - Time - (ms) - - - beta = - - - - InvTime - (/ms) - - - - ceiling = - - - - Concentration - (mM) - - - F = 96494 (C) - - thickness = - - - - Length - (um) - - volume_pool - - - phi = - - -} - -STATE { - - i (mM) - -} - -BREAKPOINT { - - SOLVE conc METHOD derivimplicit - - if( i < 0 ){ i = 0 } - if( i > ceiling ){ i = ceiling } - - -} - -DERIVATIVE conc { - - * beta - /tau - - - LOCAL thickness_cm, surf_area_cm2, volume_cm3 ? Note, normally dimensions are in um, but curr dens is in mA/cm2, etc - - thickness_cm = thickness *(1e-4) - surf_area_cm2 = area * 1e-8 - volume_cm3 = volume_pool * 1e-12 - - total_current = i * surf_area_cm2 - - - i' = ((-1 * total_current)/( * F * volume_cm3)) - ((i - rest_conc)) - - - i' = - (phi * i) - ((i - rest_conc)) - - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -? Creating synaptic mechanism, based on NEURON source impl of Exp2Syn - - -? Creating NMDA like synaptic mechanism, based on NEURON source impl of Exp2Syn - - -? Creating synaptic mechanism, based on Volker Steuber & Chiara Saviane implementation of 3 decay component facilitating synapse - - -? Creating synaptic mechanism for an electrical synapse - - -? Creating synaptic mechanism, based on Volker Steuber & Chiara Saviane implementation of 3 decay component facilitating synapse - - -? Creating synaptic mechanism, based on Andrew Davison's impl of Song and Abbot's STDP model - - - - yes - no - - - -TITLE Channel: - - - -COMMENT - -ENDCOMMENT - - -UNITS { - (nA) = (nanoamp) - (mV) = (millivolt) - (uS) = (microsiemens) -} - - -NEURON { - POINT_PROCESS - - - - NONSPECIFIC_CURRENT i - RANGE g, i - RANGE weight - - - RANGE vgap : Using a RANGE variable as opposed to POINTER for parallel mode - - - POINTER vgap : Using a POINTER as opposed to RANGE for serial mode - - - - - - RANGE tau_rise, tau_decay - GLOBAL total - - - RANGE _conc, eta, gamma, gblock - GLOBAL total - - - - RANGE tau_decay_2, tau_decay_3, gmax_2, gmax_3, ampl - - - RANGE tau_rec : time course of recovery from synaptic depression - RANGE tau_facil : time course of facilitation - RANGE U, Uinit : release probability and initial value - - - RANGE post_spike_thresh : voltage at which post syn cell will be considered spiking - RANGE t_post_spike, t_pre_spike : times of last post and pre spikes - RANGE stdp_weight_factor : multiplicative factor for weight which changes based on activity - - RANGE M, P - RANGE wmax : maximum synaptic weight which can be reached - RANGE del_weight_ltp, del_weight_ltd : - - RANGE tau_ltp, tau_ltd - - - RANGE i, e, gmax - NONSPECIFIC_CURRENT i - RANGE g, factor, factor_2, factor_3 - - - -} - -PARAMETER { - gmax = - - Conductance - tau_rise = - - Time (ms) <1e-9,1e9> - tau_decay = - - Time (ms) <1e-9,1e9> - e = - - Voltage (mV) - - - _conc = - - Concentration - - eta = - - InvConcentration - - gamma = - - InvVoltage - - - - - - - gmax_2 = - - - 0 - - Conductance - - tau_decay_2 = - - - 0 - - Time (ms) <1e-9,1e9> - - - gmax_2 = 0 - tau_decay_2 = 100000 - - - - - - gmax_3 = - - - 0 - - Conductance - - tau_decay_3 = - - - 0 - - Time (ms) <1e-9,1e9> - - - gmax_3 = 0 - tau_decay_3 = 100000 - - - - - - - - tau_rec = - - Time (ms) < 1e-9, 1e9 > - tau_facil = - - Time (ms) < 0 ,1e9 > - - Uinit = (1) < 0, 1 > :release probability - - - - tau_ltp= - - Time (ms) < 1e-9, 1e9 > - tau_ltd= - - Time (ms) < 1e-9, 1e9 > - - del_weight_ltp= (1) < 0, 1e9 > - del_weight_ltd= (1) < 0, 1e9 > - - wmax= (1) < 0, 1e9 > - - - post_spike_thresh = - - Voltage (mV) - - in_post_spike = 0 : 1 if post cell is spiking, 0 otherwise - - - - v (millivolt) - vgap (millivolt) - g = - - Conductance (microsiemens) - weight = 1 - -} - - -ASSIGNED { - i (nanoamp) -} - -BREAKPOINT { - i = weight * g * (v - vgap) -} - - - -ASSIGNED { - v (mV) - i (nA) - g (uS) - factor - factor_2 - factor_3 - - total (uS) - - R - U - gblock - - M - P - deltaw - t_post_spike (ms) - t_pre_spike (ms) - stdp_weight_factor - -} - -STATE { - A (uS) - B (uS) - C (uS) - D (uS) -} - -INITIAL { - LOCAL tp, tp_2, tp_3 - total = 0 - - if (tau_rise == 0) { - tau_rise = 1e-9 : will effectively give a single exponential timecourse synapse - } - - if (tau_rise/tau_decay > .999999) { - tau_rise = .999999*tau_decay : will result in an "alpha" synapse waveform - } - A = 0 - B = 0 - C = 0 - D = 0 - - tp = (tau_rise*tau_decay)/(tau_decay - tau_rise) * log(tau_decay/tau_rise) - factor = -exp(-tp/tau_rise) + exp(-tp/tau_decay) - factor = 1/factor - - tp_2 = (tau_rise*tau_decay_2)/(tau_decay_2 - tau_rise) * log(tau_decay_2/tau_rise) - factor_2 = -exp(-tp_2/tau_rise) + exp(-tp_2/tau_decay_2) - factor_2 = 1/factor_2 - - tp_3 = (tau_rise*tau_decay_3)/(tau_decay_3 - tau_rise) * log(tau_decay_3/tau_rise) - factor_3 = -exp(-tp_3/tau_rise) + exp(-tp_3/tau_decay_3) - factor_3 = 1/factor_3 - - - - - - M = 0 - P = 0 - deltaw = 0 - t_post_spike = 0 - t_pre_spike = 0 - stdp_weight_factor = 1 - -} - -BREAKPOINT { - SOLVE state METHOD cnexp - - gblock = 1 / (1+ (_conc * eta * exp(-1 * gamma * v))) - g = gmax * gblock * (B - A) - g = (gmax * (B - A)) + (gmax_2 * (C - A)) + (gmax_3 * (D - A)) - g = gmax * (B - A) - - i = g*(v - e) - -} - - -DERIVATIVE state { - A' = -A/tau_rise - B' = -B/tau_decay - C' = -C/tau_decay_2 - D' = -D/tau_decay_3 - -} - -NET_RECEIVE(weight (uS), U, R, tsyn (ms)) { - - LOCAL RUD - - INITIAL { - tsyn = -1 - printf("-- In the INITIAL statement in NET_RECEIVE\n") - U = Uinit - R = 1 - printf("-- t: %g, delt: %g, g: %g, U: %g, R: %g\n", t, t-tsyn, g, U, R) - } - - printf("------------------------------------------------------------\n") - - printf("-- t: %g, delt: %g, g: %g, U: %g, R: %g\n", t, t-tsyn, g, U, R) - - - if (tsyn > 0) { - - R = R * (1-U) * exp(-(t - tsyn)/tau_rec) + 1 - exp(-(t - tsyn)/tau_rec) - - if (tau_facil > 0) { - U = U * exp(-(t - tsyn)/tau_facil) + Uinit * (1 - (U * exp(-(t - tsyn)/tau_facil))) - } else { - U = Uinit - } - - } else { - printf("-- At first spike...\n") - } - - RUD = (U*R) - - printf("-- t: %g, delt: %g, g: %g, U: %g, R: %g, RUD: %g\n", t, t-tsyn, g, U, R, RUD) - - - - printf("------------------------------------------------------------\n") - - - printf("-- SPIKE at time: %f (%g), with weight %g!\n", t, t, weight) - - - - - if (t_post_spike >= 0) { - printf("-- Last post spike ago: %g\n", t-t_post_spike) - } - if (t_pre_spike >= 0) { - printf("-- Last pre spike ago: %g\n", t-t_pre_spike) - } - - if (weight >= 0) { : this is a pre-synaptic spike - - P = P*exp((t_pre_spike-t)/tau_ltp) + del_weight_ltp - - deltaw = wmax * M * exp((t_post_spike - t)/tau_ltd) - - t_pre_spike = t - - } else { : this is a post-synaptic spike - - M = M*exp((t_post_spike-t)/tau_ltd) - del_weight_ltd - - //Todo: double check this! - //? deltaw = wmax * P * exp(-(t - t_pre_spike)/tau_ltp) - deltaw = deltaw + wmax * P * exp(-(t - t_pre_spike)/tau_ltp) - - t_post_spike = t - - } - - - - - stdp_weight_factor = stdp_weight_factor + deltaw - - if (stdp_weight_factor > wmax) { stdp_weight_factor = wmax} - if (stdp_weight_factor < 0) { stdp_weight_factor = 0} - - - printf("pg-- stdp_weight_factor: %g, deltaw: %g, P: %g, M: %g\n", stdp_weight_factor,deltaw, P, M) - - if (weight >= 0) { : this is a pre-synaptic spike - - - - - LOCAL Ajump, Bjump, Cjump, Djump - Bjump = weight*factor*stdp_weight_factor - Cjump = weight*factor_2*stdp_weight_factor - Djump = weight*factor_3*stdp_weight_factor - - Ajump = (gmax*Bjump + gmax_2*Cjump + gmax_3*Djump)/(gmax + gmax_2 + gmax_3) - - state_discontinuity(A, A + Ajump) - state_discontinuity(B, B + Bjump) - state_discontinuity(C, C + Cjump) - state_discontinuity(D, D + Djump) - - - state_discontinuity(A, A + weight*factor*RUD*stdp_weight_factor) - state_discontinuity(B, B + weight*factor*RUD*stdp_weight_factor) - - - - - - - tsyn = t - - - } - - -} - - - - - - - - - - - - - - - - - - - - if () { - = - } else { - = - } - - = - - - - - - - diff --git a/tests/python/two_cells_nml_1.8/cellMechanisms/LeakConductance/ChannelML_v1.8.1_PSICS.xsl b/tests/python/two_cells_nml_1.8/cellMechanisms/LeakConductance/ChannelML_v1.8.1_PSICS.xsl deleted file mode 100644 index c31895cf..00000000 --- a/tests/python/two_cells_nml_1.8/cellMechanisms/LeakConductance/ChannelML_v1.8.1_PSICS.xsl +++ /dev/null @@ -1,471 +0,0 @@ - - - - - - - - -0 - -30 - - - - true - false - - - - - - mV - V - - - - - - per_ms - per_s - - - - - - - - - This is a PSICS channel model file generated from a ChannelML v1.8.1 file. - - - - - - - - - - - - Error: this channel contains an Integrate and Fire mechanisms that cannot be mapped to PSICS. - - - - - - - - - - - - - - - Error: Ion concentration pools not yet supported in PSICS! - - - - - Error: Synapses not yet supported in PSICS! - - - - - - Error: the channel has a voltage_conc gate that is not supported in PSICS - - - Error: the channel has a conc dependent gate that is not supported in PSICS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - double offset = ; - v = v + offset; - - - - - - double temp_adj_ = 1; - - - - - - - double temp_adj_ = Math.pow(, (temperature - )/10); - - - double temp_adj_ = ; - - - - - - - - - - - - - - double = 0; - - - - - - - - - - - - - - - - - - - - - - - tau - - - - - tau - - - - - - - tau = 1/(alpha + beta); - - - tau = tau/temp_adj_; - - - - - - - inf - - - - - - inf - - - - - - - - inf = alpha/(alpha + beta); - - - - - - double rate = 0; - double scale = 0; - double midpoint = 0; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - unsupported transition type - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - double = 0; - rate = - - InvTime - ; - - - rate = - - Time - ; - - - rate = ; - - - double = 0; - rate = ; // Warning: unrecognised rate variable! Don't know how to convert units! - - - scale = - - Voltage - ; - midpoint = - - Voltage - ; - - - - - = rate * Math.exp((v - midpoint) / scale); - - - = rate / (Math.exp((v - midpoint) / scale) + 1); - - - if ( 1e-6 > (Math.abs((v - midpoint)/ scale))) { - = rate * (1 + (v - midpoint)/scale/2); - } else { - = rate * ((v - midpoint) / scale) /(1 - (Math.exp(-1 * (v - midpoint)/scale))); - } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - exp - Math.exp - - - - - - celsius - temperature - - - - - - - - - - - if () { - = ; - } else { - = ; - } - - - = ; - - - - - - \ No newline at end of file diff --git a/tests/python/two_cells_nml_1.8/cellMechanisms/LeakConductance/LeakConductance.xml b/tests/python/two_cells_nml_1.8/cellMechanisms/LeakConductance/LeakConductance.xml deleted file mode 100644 index c40270d9..00000000 --- a/tests/python/two_cells_nml_1.8/cellMechanisms/LeakConductance/LeakConductance.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - ChannelML file containing a single Channel description - - - - - - Simple example of a leak/passive conductance. Note: for GENESIS cells with a single leak conductance, - it is better to use the Rm and Em variables for a passive current. - - - - - - \ No newline at end of file diff --git a/tests/python/two_cells_nml_1.8/cellMechanisms/LeakConductance/properties.xml b/tests/python/two_cells_nml_1.8/cellMechanisms/LeakConductance/properties.xml deleted file mode 100644 index f71b7d05..00000000 --- a/tests/python/two_cells_nml_1.8/cellMechanisms/LeakConductance/properties.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - -Properties associated with the Cell Mechanism which allow it to be loaded into neuroConstruct. - -Note the following: - The Cell Mechanism name should not contain spaces and should match the name of the directory it's in - The name and description here will be replaced by the corresponding values in a ChannelML file if found - The filenames for the mappings are relative to the cellMechanism/(cellMechInstanceName) directory - Mechanism Type should only have values: Channel mechanism, Synaptic mechanism, Ion concentration, Point process, Gap junction - - -Simple example of a leak/passive conductance. Note: for GENESIS cells with a single leak conductance, - it is better to use the Rm and Em variables for a passive current. -ChannelML_v1.8.1_NEURONmod.xsl -ChannelML_v1.8.1_GENESIStab.xsl -false -ChannelML based Cell Mechanism -true -Channel mechanism -LeakConductance.xml -ChannelML_v1.8.1_PSICS.xsl -false -LeakConductance -Template based ChannelML file - diff --git a/tests/python/two_cells_nml_1.8/cellMechanisms/NaConductance/ChannelML_v1.8.1_GENESIStab.xsl b/tests/python/two_cells_nml_1.8/cellMechanisms/NaConductance/ChannelML_v1.8.1_GENESIStab.xsl deleted file mode 100644 index dd6ea88c..00000000 --- a/tests/python/two_cells_nml_1.8/cellMechanisms/NaConductance/ChannelML_v1.8.1_GENESIStab.xsl +++ /dev/null @@ -1,1503 +0,0 @@ - - - - - - - - - -no - - - - - -Physiological Units - - - - -// This is a GENESIS script file generated from a ChannelML v1.8.1 file -// The ChannelML file is mapped onto a tabchannel object - - -// Units of ChannelML file: , units of GENESIS file generated: - - - -/* - -*/ - - - - - *** Note: Kinetic scheme based ChannelML descriptions cannot be mapped on to GENESIS at the present time. *** - - - *** Note: Integrate and Fire mechanisms cannot be mapped on to GENESIS at the present time. *** - - - - - - - - - - - - - - - - - - - - - - - no - yes - - - - - - - yes - yes - no - - - - - - - no - yes - - - - - - - yes - no - - - - -// NOTE: There are parameters in the ChannelML file, so there will be a seperate init of the table -extern init_ - - - - -function make_ - - - /* - - - Reference: - Pubmed: - */ - - - str chanpath = "/library/" - - if ({exists {chanpath}}) - return - end - - - - - - - - - - - - - - - - - - - create leakage {chanpath} - - - create tabchannel {chanpath} - - - create tab2Dchannel {chanpath} - - - create tabchannel {chanpath} - - - - setfield {chanpath} \ - Ek - - Voltage - \ - Ik 0 \ - Xpower - \ - Ypower - \ - Zpower - \ - Zpower 1 - \ - Xpower - \ - Ypower - \ - Zpower - \ - Zpower 1 - \ - Zpower - - - - - - setfield {chanpath} Gk - - Conductance Density - - - - - - setfield {chanpath} Gk - - Conductance Density - - - - - - setfield {chanpath} \ - Gbar - - Conductance Density - \ - Gk 0 - - - - - setfield {chanpath} \ - Gbar - - Conductance Density - \ - Gk 0 - - - - - - - // There are parameters in the ChannelML file, which may be changed after initialisation which could mean the tables - // will need to be updated. Seperating out the generation of the table values into init function. - - - addfield {chanpath} - setfield {chanpath} // Note units of this will be determined by its usage in the generic functions - - - init_ {chanpath} // Initialisation of the tables - -end // End of main channel definition - - -// calling this function after changing the extra parameters/added fields will updated the table -function init_(chanpath) - - str chanpath - - // Retrieving the param values as local variables - - float = {getfield {chanpath} } - - - - - - - - - // There is a Q10 factor which will alter the tau of the gates - - - - - float temp_adj_ = {pow {(celsius - )/10}} - - float temp_adj_ = - - - - - {pow {(celsius - )/10}} - - float temp_adj_ = - - float temp_adj_ = - - - - - float temp_adj_ = - - - float temp_adj_ = - - - - - - - - // No Q10 temperature adjustment found - float temp_adj_ = 1 - - float temp_adj_ = 1 - - - - - - - - - - 100 - 0.1 - - - - - Voltage - - - - - - - - - -100 - -0.1 - - - - - Voltage - - - - - - - - 400 - - - - - float tab_divs = - - - - float v_min = - - float v_max = - - float v, dv, i - - - - - - - - X - Y - Z - - - - // Creating table for gate , using name for it here - - float dv = ({v_max} - {v_min})/{tab_divs} - - - - - - - - - // Channel is dependent on concentration of: , rate equations will involve variable: - float c - float conc_min = - - Concentration - - float conc_max = - - Concentration - - - float dc = ({conc_max} - {conc_min})/{tab_divs} - - float = {conc_min} - - - - - // Setting up the volt/conc dependent 2D table - setfield {chanpath} index {VOLT_C1_INDEX} // assumes all gates are volt/conc dep - - - - call {chanpath} TABCREATE {tab_divs} {v_min} {v_max} {tab_divs} {conc_min} {conc_max} - - - - call {chanpath} TABCREATE Z {tab_divs} {conc_min} {conc_max} - - - for (c = 0; c <= ({tab_divs}); c = c + 1) - - - - call {chanpath} TABCREATE {tab_divs} {v_min} {v_max} - - - - - v = {v_min} - - - // There is a voltage offset of . This will shift the dependency of the rate equations - v = v - - - Voltage - - - - - for (i = 0; i <= ({tab_divs}); i = i + 1) - - - - - // Looking at rate: - - float - - - - - float A, B, k, V0 - - - - - - - - - - - - // Found a generic form of rate equation for , using expression: - // Will translate this for GENESIS compatibility... - - - // Equation (and all ChannelML file values) in but this script in - - v = v * - 1 - InvVoltage - // temporarily set v to units of equation... - - - // Equation depends on alpha/beta, so converting them too... - alpha = alpha * - 1 - Time - - beta = beta * - 1 - Time - - - - - // Equation depends on alpha, so converting it... - alpha = alpha * - 1 - Time - - - - - - // Equation depends on concentration, so converting that too... - - = * - 1 - InvConcentration - - - - - - - - - - - - - - - - - - - v = v * - 1 - Voltage - // reset v - - - alpha = alpha * - 1 - InvTime - // resetting alpha - beta = beta * - 1 - InvTime - // resetting beta - - - - alpha = alpha * - 1 - InvTime - // resetting alpha - - - - = * - 1 - Concentration - // resetting ca_conc - - - - - - - - - - // Set correct units of - - = * - 1 - InvTime - - - - - - - // Set correct units of - - = * - 1 - Time - - - - - - - - ? ERROR: Unrecognised form of the rate equation for ... - - - - - - - - - table[{i}] - table[{i}][{c}] - - - - - - - - // Using the alpha and beta expressions to populate the tables - - float tau = 1/(temp_adj_ * (alpha + beta)) - echo "Tab : v: "{v} ", a: "{alpha} ", b: "{beta} ", tau: "{tau} - - echo "Tab : conc: " {} - - - setfield {chanpath} _A-> {temp_adj_ * alpha} - setfield {chanpath} _B-> {temp_adj_ * (alpha + beta)} - - - - // Evaluating the tau and inf expressions - - - - float tau = 1/(temp_adj_ * (alpha + beta)) - - - tau = tau/temp_adj_ - - - - float inf = alpha/(alpha + beta) - - - echo "Tab : v: "{v} ", tau: "{tau} ", inf: "{inf} - - echo "Tab : conc: " {} - - - - - // Working out the "real" alpha and beta expressions from the tau and inf - - float alpha - - float beta - alpha = inf / tau - beta = (1- inf)/tau - - - setfield {chanpath} _A-> {alpha} - setfield {chanpath} _B-> {alpha + beta} - - - - - - - - // Looking at rate: - - float - - - - - float A, B, Vhalf - - - - - - - - - - - // Found a generic form of rate equation for , using expression: - // Will translate this for GENESIS compatibility... - - - // Equation (and all ChannelML file values) in but this script in - - v = v * - 1 - InvVoltage - // temporarily set v to units of equation... - - - // Equation depends on alpha/beta, so converting them too... - alpha = alpha * - 1 - Time - - beta = beta * - 1 - Time - - - - - // Equation depends on alpha, so converting it... - alpha = alpha * - 1 - Time - - - - - - // Equation depends on concentration, so converting that too... - - = * - 1 - InvConcentration - - - - - - - - - - - - - - - - - - - v = v * - 1 - Voltage - // reset v - - - alpha = alpha * - 1 - InvTime - // resetting alpha - beta = beta * - 1 - InvTime - // resetting beta - - - - alpha = alpha * - 1 - InvTime - // resetting alpha - - - - = * - 1 - Concentration - // resetting ca_conc - - - - - - - - - - // Set correct units of - - = * - 1 - InvTime - - - - - - - // Set correct units of - - = * - 1 - Time - - - - - - - - ? ERROR: Unrecognised form of the rate equation for ... - - - - - - - - - table[{c}] - table[{i}] - table[{i}][{c}] - - - - - - - - // Using the alpha and beta expressions to populate the tables - - float tau = 1/(temp_adj_ * (alpha + beta)) - echo "Tab : v: "{v} ", a: "{alpha} ", b: "{beta} ", tau: "{tau} - - echo "Tab : conc: " {} - - - - - - setfield {chanpath} _A-> {temp_adj_ * alpha} - setfield {chanpath} _B-> {temp_adj_ * (alpha + beta)} - - - setfield {chanpath} Z_A-> {temp_adj_ * alpha} - setfield {chanpath} Z_B-> {temp_adj_ * (alpha + beta)} - - - - - - - // Evaluating the tau and inf expressions - - - - float tau = 1/(temp_adj_ * (alpha + beta)) - - - tau = tau/temp_adj_ - - - - float inf = alpha/(alpha + beta) - - - echo "Tab : v: "{v} ", tau: "{tau} ", inf: "{inf} - - echo "Tab : conc: " {} - - - - - // Working out the "real" alpha and beta expressions from the tau and inf - - float alpha - - float beta - alpha = inf / tau - beta = (1- inf)/tau - - - setfield {chanpath} _A-> {alpha} - setfield {chanpath} _B-> {alpha + beta} - - - - - - - v = v + dv - - end // end of for (i = 0; i <= ({tab_divs}); i = i + 1) - - - - - - = + dc - - - = + dc - - - - end // end of for (c = 0; c <= ({tab_divs}); c = c + 1) - - - - - - - - setfield {chanpath} _A->calc_mode 1 _B->calc_mode 1 - - - setfield {chanpath} Z_conc 1 - setfield {chanpath} Z_A->calc_mode 1 Z_B->calc_mode 1 - - - - - - - - - // Adding voltage independent concentration term - - - float conc_min = - - Concentration - - float conc_max = - - Concentration - - - float dc = ({conc_max} - {conc_min})/{tab_divs} - - float = {conc_min} - - call {chanpath} TABCREATE Z {tab_divs} {conc_min} {conc_max} - - float const_state - - for (i = 0; i <= ({tab_divs}); i = i + 1) - - - - - // Equation is in different set of units... - = * - 1 - InvConcentration - - - - - - - const_state - - - - - - - - - // Converting back... - = * - 1 - Concentration - - - - - - - setfield {chanpath} Z_A->table[{i}] {0} - setfield {chanpath} Z_B->table[{i}] {const_state} - - - = + dc - - end - - tweaktau {chanpath} Z - - - -end - - - - - - - - - - - -function __catchCeiling__(action) - - call . PROCESS -parent // Carry out all normal actions - - float caval = {getfield Ca} - float cabase = {getfield Ca_base} - float ceil = {getfield ceiling} - - if (caval > ceil) - setfield Ca {ceil} - setfield C {ceil - cabase} - end - -end - - -function make_ - - - /* - - */ - - - str chanpath = "/library/" - - if ({exists {chanpath}}) - return - end - - - - - create Ca_concen {chanpath} - - - - - - - - - - - Time - - - { 1.0 / - - - - InvTime - } - - - - - // Setting params for a decaying_pool_model - - setfield {chanpath} \ - tau \ - Ca_base - - - - Concentration - - - - addfield {chanpath} beta -description "Inverse of tau, needed as this is parameter used in some implementations. If beta > 0, this will be used in preference to tau" - setfield {chanpath} beta -1 - - - - setfield {chanpath} \ - thick - - - - Length - - - - - - - addfield {chanpath} ceiling -description "Maximum concentration pool will be allowed reach" - setfield {chanpath} ceiling - - - - Concentration - - - addaction {chanpath} PROCESS __catchCeiling__ - - - - -end - -function init_(chanpath) - - float curr_beta = {getfield {chanpath} beta} - if (curr_beta > 0) - - echo "Using the value of beta " {curr_beta} " in place of tau" - setfield {chanpath} tau {1 / {curr_beta}} - else - echo "Keeping existing tau: " {getfield {chanpath} tau} " not beta: " {curr_beta} - end - - -end - - - - - - - - - - - -function connectGapJunction_(compartmentA, compartmentB, weight) - - // Note: implementation based on suggestion of Reinoud Maex - - str compartmentA - str compartmentB - float conductance = - - Conductance - - str diffampname = {strcat "diffamp_" {rand 0 99999999}} // to ensure a different diffamp name for each gap junc on this comp - - create diffamp {compartmentA}/{diffampname} - - addmsg {compartmentA} {compartmentA}/{diffampname} PLUS Vm - addmsg {compartmentB} {compartmentA}/{diffampname} MINUS Vm - - setfield {compartmentA}/{diffampname} gain {conductance * weight} - setfield {compartmentA}/{diffampname} saturation 10e8 - - addmsg {compartmentA}/{diffampname} {compartmentB} INJECT output - - - create diffamp {compartmentB}/{diffampname} - - addmsg {compartmentB} {compartmentB}/{diffampname} PLUS Vm - addmsg {compartmentA} {compartmentB}/{diffampname} MINUS Vm - - setfield {compartmentB}/{diffampname} gain {conductance * weight} - setfield {compartmentB}/{diffampname} saturation 10e8 - - addmsg {compartmentB}/{diffampname} {compartmentA} INJECT output - -end - - - -function makechannel_(compartment, name) - - /* - - */ - - str compartment - str name - - if (!({exists {compartment}/{name}})) - - create synchan {compartment}/{name} - - setfield ^ \ - Ek - - Voltage \ - tau1 - - Time \ - tau2 - - Time \ - gmax - - Conductance - - float tau2 = {getfield {compartment}/{name} tau2} - - if (tau2 == 0) // Single exponential synapse - setfield {compartment}/{name} tau2 1e-9 - end - - addmsg {compartment}/{name} {compartment} CHANNEL Gk Ek - addmsg {compartment} {compartment}/{name} VOLTAGE Vm - - - - setfield ^ \ - Ek - - Voltage \ - tau1 - - Time \ - tau2 - - Time \ - gmax - - Conductance - - float tau1 = {getfield {compartment}/{name} tau1} - if (tau1 == 0) - setfield {compartment}/{name} tau1 1e-9 - end - - addmsg {compartment} {compartment}/{name} VOLTAGE Vm - - if (! {exists {compartment}/{name}/Mg_BLOCK}) - - float CMg = - - Concentration - - float eta = - - InvConcentration - - float gamma = - - InvVoltage - - create Mg_block {compartment}/{name}/Mg_BLOCK - - setfield {compartment}/{name}/Mg_BLOCK \ - CMg {CMg} \ - KMg_A {1/eta} \ - KMg_B {1.0/gamma} - - addmsg {compartment}/{name} {compartment}/{name}/Mg_BLOCK CHANNEL Gk Ek - addmsg {compartment}/{name}/Mg_BLOCK {compartment} CHANNEL Gk Ek - addmsg {compartment} {compartment}/{name}/Mg_BLOCK VOLTAGE Vm - end - - - - end - -end - - - - - - - - - - - - - 1 - 2 - 3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - si - - - - - - - - - - - - - - - - - // ChannelML form of equation: = , with params: - // A = , k = , d = , in units: - - - - A = - - InvTime - - - - A = - - Time - - - - A = - - - A = // Warning: unrecognised rate variable! Don't know how to convert units! - - - k = - - InvVoltage - - B = 1/k - V0 = - - Voltage - - - - - - - = A * {exp {(v - V0) / B}} - - - = A / ( {exp {(v - V0) / B}} + 1) - - - - if ( {abs {(v - V0)/ B}} < 1e-6) - = A * (1 + (v - V0)/B/2) - else - = A * ((v - V0) / B) /(1 - {exp {-1 * (v - V0)/B}}) - end - - - - - - - - = 1 // Gate is not present, power should = 0 so value of is not relevant - - - - - - - - - - - - - - - - // ChannelML form of equation: which is of form , with params: - // A = , B = , Vhalf = , in units: - - - - A = - - InvTime - - - - A = - - Time - - - - A = - - - A = // Warning: unrecognised rate variable! Don't know how to convert units! - - - B = - - Voltage - - Vhalf = - - Voltage - - - - - - - = A * {exp {(v - Vhalf) / B}} - - - = A / ( {exp {(v - Vhalf) / B}} + 1) - - - - if ( {abs {(v - Vhalf)/ B}} < 1e-6) - = A * (1 + (v - Vhalf)/B/2) - else - = A * ((v - Vhalf) / B) /(1 - {exp {-1 * (v - Vhalf)/B}}) - end - - - - - - - - = 1 // Gate is not present, power should = 0 so value of is not relevant - - - - - - - - - - - - - - - - - - if () - = - else - = - end - - - = - - - - - \ No newline at end of file diff --git a/tests/python/two_cells_nml_1.8/cellMechanisms/NaConductance/ChannelML_v1.8.1_NEURONmod.xsl b/tests/python/two_cells_nml_1.8/cellMechanisms/NaConductance/ChannelML_v1.8.1_NEURONmod.xsl deleted file mode 100644 index 04a6a65a..00000000 --- a/tests/python/two_cells_nml_1.8/cellMechanisms/NaConductance/ChannelML_v1.8.1_NEURONmod.xsl +++ /dev/null @@ -1,1974 +0,0 @@ - - - - - - - - - - - - - -0 - -0 - -1 - -0 - - - - - - -? This is a NEURON mod file generated from a ChannelML file - -? Unit system of original ChannelML file: - - - - *** Note: Kinetic scheme based ChannelML description cannot be mapped in to mod files in this version. *** - Please use the alternative XSL file which maps on to NEURON's KS Channel Builder format - (should be ChannelML_v1.X.X_NEURONChanBuild.xsl) - - - -COMMENT - -ENDCOMMENT - - - - - - - - - - - - - - -TITLE Channel: - - - -COMMENT - -ENDCOMMENT - - -UNITS { - (mA) = (milliamp) - (mV) = (millivolt) - (S) = (siemens) - (um) = (micrometer) - (molar) = (1/liter) - (mM) = (millimolar) - (l) = (liter) -} - - - - yes - yes - no - - - - - - yes - yes - no - - - -NEURON { - - - SUFFIX - - - - - USEION WRITE i VALENCE ? reversal potential of ion is **NOT READ**, outgoing current is written - - - USEION READ i VALENCE ? internal concentration of ion is read - - - USEION READ i WRITE i VALENCE ? outgoing current of ion is read, internal concentration is written - - - USEION READ e WRITE i VALENCE ? reversal potential of ion is read, outgoing current is written - - - - - - VALENCE - VALENCE 1 - USEION READ e WRITE i ? reversal potential of ion is read, outgoing current is written - - - - - VALENCE - VALENCE 1 - USEION READ i ? internal concentration of ion is read - - - - VALENCE - VALENCE 1 - USEION READ i ? internal concentration of ion is read - - - - - - ? A non specific current is present - RANGE e - NONSPECIFIC_CURRENT i - - RANGE gmax, gion - - - RANGE inf, tau - - , __ - - - - - - RANGE inf, tau - - - - - RANGE - - - - - - - - RANGE - - - - ? Note this implementation is based on that used in the COBA based I and F model as used in Brette et al (2006) - ? and the NEURON script files from http://senselab.med.yale.edu/SenseLab/ModelDB/ShowModel.asp?model=83319 - - POINT_PROCESS - GLOBAL thresh, t_refrac, v_reset, g_refrac - NONSPECIFIC_CURRENT i - - -} - -PARAMETER { - - - gmax = - - Conductance Density - (S/cm2) ? default value, should be overwritten when conductance placed on cell - - e = - - Voltage - (mV) ? default value, should be overwritten when conductance placed on cell - - - - - __ = - - - - - - - gmax = - - Conductance Density - (S/cm2) ? default value, should be overwritten when conductance placed on cell - - e = - - Voltage - (mV) ? default value, should be overwritten when conductance placed on cell - - - - thresh = - - Voltage - (mV) - t_refrac = - - Time - (ms) - v_reset = - - Voltage - (mV) - g_refrac = - - Conductance - (uS) - - - - = : Note units of this will be determined by its usage in the generic functions - -} - - - -ASSIGNED { - - - v (mV) - - - i (mA/cm2) - - - celsius (degC) - - - - ? The internal concentration of ion: is used in the rate equations... - i (mM) - - - ? Error!! ion: with role="SignallingSubstance" shouldn't be in a channel_type... - - - ? Reversal potential of - e (mV) - ? The outward flow of ion: calculated by rate equations... - i (mA/cm2) - - - - - - ? Reversal potential of - e (mV) - ? The outward flow of ion: calculated by rate equations... - i (mA/cm2) - - - - ? The internal concentration of ion: is used in the rate equations... - i (mM) - - - ? The internal concentration of ion: is used in the rate equations... - i (mM) - - - gion (S/cm2) - - inf - tau (ms) - - - inf - tau (ms) - - - - - (/ms) - - - - - - - - - i (nanoamp) - v (millivolt) - g (microsiemens) - - - -} - -BREAKPOINT { LOCAL g_factor, - - -LOCAL g_factor, - - - - - - - - - i = gmax*(v - e) - - - - - - SOLVE kin METHOD sparse - - - SOLVE states METHOD derivimplicit - - - - SOLVE states METHOD cnexp - - - - gion = gmax*(( - *)^) - - - - - gion = gmax * (( + (*) )^) - - - - - = i / - 1 - Concentration - - - g_factor - - - - - - gion = gion * g_factor - - - - - i = gion*(v - e) - - - - i = gion*(v - e) - - - - - - i = g*(v - v_reset) - - - -} - - - - -INITIAL { - net_send(0, 3) - g = 0 -} - -NET_RECEIVE(w) { - - if (flag == 1) { - v = v_reset - g = g_refrac - - printf("+++++++ Spiking cell at: %g, v: %g\n", t, v) - - net_event(t) - net_send(t_refrac, 2) - }else if (flag == 2) { - g = 0 - - printf("+++++++ Finished refract at: %g, v: %g\n", t, v) - - }else if (flag == 3) { - WATCH (v > thresh) 1 - } -} - - - -INITIAL { - - - - Voltage - - - - e = - - - - - e = - - - - - - settables(v,cai) - - - rates(v) - - - - - - = inf - - = : Hard coded initialisation!! - - - = : Hard coded initialisation!! - - - - - - - - - = inf - - = : Hard coded initialisation!! - - SOLVE kin STEADYSTATE sparse - - - -} - -STATE { - - - - - - - - - - - - - - - - -} - - - - -KINETIC kin { - - settables(v,cai) - - rates(v) - - - - - - - - - - - - ~ <-> (, ) - - CONSERVE + = 1 -} - - - - -DERIVATIVE states { - - settables(v,cai) - - rates(v) - - - - ' = (inf - )/tau - - - - - - ' = (inf - )/tau - - - - - - ' = 0 + * (1 - ) - - * - - - - - - -} - - - - - - - PROCEDURE settables(v(mV), cai(mM)) { - PROCEDURE rates(v(mV)) { - - - ? Note: not all of these may be used, depending on the form of rate equations - LOCAL alpha, beta, tau, inf, gamma, zeta, - , - , temp_adj_, A__, k__, d__ - - - , temp_adj_ - , - A__, B__, Vhalf__ - - - - - - - - - - - - - 100 - - - - Voltage - - - - - - - - -100 - - - - Voltage - - - - - - - - 400 - - - - - - - - - - TABLE inf, tau, - inf, tau, - DEPEND celsius - - , __ - FROM TO WITH - - - : NOT USING TABLE: as there are some changable parameters ( ) - : which may be different on different sections, using a TABLE for computing these values can lead to errors. - - - - - - - UNITSOFF - - - ? There is a Q10 factor which will alter the tau of the gates - - - - - temp_adj_ = ^((celsius - )/10) - - temp_adj_ = - - - - - ^((celsius - )/10) - - temp_adj_ = - - - temp_adj_ = - - - - - temp_adj_ = - - - temp_adj_ = - - - - - - - - temp_adj_ = 1 - - temp_adj_ = 1 - - - - - - - - ? There is a voltage offset of . This will shift the dependency of the rate equations - v = v - ( - - Voltage - ) - - - - - - - - - - - - ? Gate depends on the concentration of - - = i ? In NEURON, the variable for the concentration of is i - - - ? *** Adding rate equations for gate: *** - - - - - - - ? Found a parameterised form of rate equation for , using expression: - A*(k*(v-d)) / (1 - exp(-(k*(v-d)))) - A*exp(k*(v-d)) - A / (1 + exp(k*(v-d))) - Unsupported expression type! - - - A__ - k__ - d__ - - - - __ = - - - - - ? Unit system in ChannelML file is SI units, therefore need to - ? convert these to NEURON quanities... - - - = * - 1 - InvTime - ? 1/ms - - - = * - 1 - Time - ? ms - - - = ? Dimensionless - - - = * - 1 - InvVoltage - ? mV - = * - 1 - Voltage - ? mV - - - - - - - - = * exp((v - ) * ) - - - - - = / (exp((v - ) * ) + 1) - - - - - = * vtrap((v - ), (1/)) - - - - - - - - - - ? Found a generic form of the rate equation for , using expression: - - - ? Note: Equation (and all ChannelML file values) in so need to convert v first... - - v = v * - 1 - InvVoltage - ? temporarily set v to units of equation... - - - - ? Equation depends on alpha/beta, so converting them too... - alpha = alpha * - 1 - Time - - beta = beta * - 1 - Time - - - - - - ? Equations can depend on concentration. NEURON uses 'SI Units' internally for concentration, - ? but ChannelML file is in Physiological Units... - = / - 1 - Concentration - - - - - - - - - - - - - - - - ? Set correct units of for NEURON - - = * - 1 - InvTime - - - - - ? Set correct units of for NEURON - - = * - 1 - Time - - - - v = v * - 1 - Voltage - ? reset v - - alpha = alpha * - 1 - InvTime - ? resetting alpha - beta = beta * - 1 - InvTime - ? resetting beta - - - - ? Resetting concentration... - = * - 1 - Concentration - - - - - - - - ? ERROR: Unrecognised form of the rate equation for - - - - - - - tau = tau/temp_adj_ - - - - - inf = inf - - - - - - - - - - tau = 1/(temp_adj_*(alpha + beta)) - - - - - inf = alpha/(alpha + beta) - - - - - ? *** Finished rate equations for gate: *** - - - - - - - - - - - ? Gate depends on the concentration of - - = i ? In NEURON, the variable for the concentration of is i - - - - - - - - - - - ? *** Adding rate equations for gate: *** - - - - - - - - ? Found a parameterised form of rate equation for , using expression: - A*((v-Vhalf)/B) / (1 - exp(-((v-Vhalf)/B))) - A*exp((v-Vhalf)/B) - A / (1 + exp((v-Vhalf)/B)) - Unsupported expression type! - - - A__ - B__ - Vhalf__ - - - - = - - = - - = - - - - ? Unit system in ChannelML file is SI units, therefore need to convert these to NEURON quanities... - - - - = * - 1 - InvTime - ? 1/ms - - - = * - 1 - Time - ? ms - - - = ? Dimensionless - - - = * - 1 - Voltage - ? mV - = * - 1 - Voltage - ? mV - - - - - - - = * exp((v - ) / ) - - - - - = / (exp((v - ) / ) + 1) - - - - - = * vtrap((v - ), ) - - - - - - - - - - ? Found a generic form of the rate equation for , using expression: - - - ? Note: Equation (and all ChannelML file values) in so need to convert v first... - - v = v * - 1 - InvVoltage - ? temporarily set v to units of equation... - - - - ? Equation depends on alpha/beta, so converting them too... - alpha = alpha * - 1 - Time - - beta = beta * - 1 - Time - - - - - - ? Equations can depend on concentration. NEURON uses 'SI Units' internally for concentration, - ? but the ChannelML file is in Physiological Units... - = / - 1 - Concentration - - - - - - - - - - - - - - - - ? Set correct units of for NEURON - - = * - 1 - InvTime - - - - - ? Set correct units of for NEURON - - = * - 1 - Time - - - - v = v * - 1 - Voltage - ? reset v - - alpha = alpha * - 1 - InvTime - ? resetting alpha - beta = beta * - 1 - InvTime - ? resetting beta - - - - ? Resetting concentration... - = * - 1 - Concentration - - - - - - - - ? ERROR: Unrecognised form of the rate equation for - - - - - - = * temp_adj_ ? Applying temp adj here as channel has KS description - - - - - tau = tau/temp_adj_ - - - - - inf = inf - - - - - - - - - - - tau = 1/(temp_adj_*(alpha + beta)) - - - - - inf = alpha/(alpha + beta) - - - - - - ? *** Finished rate equations for gate: *** - - - -} - - -? Function to assist with parameterised expressions of type linoid/exp_linear - -FUNCTION vtrap(VminV0, B) { - if (fabs(VminV0/B) < 1e-6) { - vtrap = (1 + VminV0/B/2) -}else{ - vtrap = (VminV0 / B) /(1 - exp((-1 *VminV0)/B)) - } -} - -UNITSON - - - - - - - - - -? Creating ion concentration - -TITLE Channel: - - - -COMMENT - -ENDCOMMENT - - -UNITS { - (mV) = (millivolt) - (mA) = (milliamp) - (um) = (micrometer) - (l) = (liter) - (molar) = (1/liter) - (mM) = (millimolar) -} - - -NEURON { - SUFFIX - - - USEION READ i WRITE i VALENCE - - - - - - - RANGE i - - RANGE rest_conc - - - RANGE tau - - - RANGE beta - - - RANGE ceiling - - - - RANGE thickness, F - - - RANGE total_current - RANGE volume_pool - - - - RANGE phi - - -} - -ASSIGNED { - - i (mA/cm2) - diam (um) - area (um) -} - -INITIAL { - - - LOCAL pi, shell_inner_diam, cylinderLen, circumference, circumference_shell, volumeOuter, volumeInner, volumeSph, volumeCyl - - pi = 3.14159265 - - shell_inner_diam = diam - (2*thickness) - - - ? Volume of the pool if it is a shell inside a sphere of diameter diam - - volumeSph = (diam*diam*diam) * pi / 6 - (shell_inner_diam*shell_inner_diam*shell_inner_diam)* pi / 6 - - - ? Volume of the pool if it is a cylinder - - circumference = diam * pi - circumference_shell = shell_inner_diam * pi - - cylinderLen = area/circumference - - volumeOuter = (diam * diam/4) * pi * cylinderLen - volumeInner = (shell_inner_diam * shell_inner_diam/4) * pi * cylinderLen - volumeCyl = volumeOuter - volumeInner - - if ((area - (pi * diam * diam)) < 1e-3 && (area - (pi * diam * diam)) > -1e-3 ) { - - ? Assume the segment is a sphere - printf("+++++++ Assume a sphere: %g, %g, %g\n", area, (pi * diam * diam), (area - (pi * diam * diam))) - - volume_pool = volumeSph - - } else { - - ? assume segment is a cylinder - printf("+++++++ Assume a cylinder: %g, %g, %g\n", area, (pi * diam * diam), (area - (pi * diam * diam))) - - volume_pool = volumeCyl - } - - printf("+++++++ Init ca, diam: %g, cylinderLen: %g, volume_pool: %g, volumeSph: %g, volumeCyl: %g, area as sph: %g, area x d: %g, area: %g\n", diam, cylinderLen, volume_pool, volumeSph, volumeCyl, (pi * diam * diam), (area*thickness), area) - - - i = rest_conc - -} - -PARAMETER { - - total_current - rest_conc = - - - - Concentration - (mM) - - - tau = - - - - Time - (ms) - - - beta = - - - - InvTime - (/ms) - - - - ceiling = - - - - Concentration - (mM) - - - F = 96494 (C) - - thickness = - - - - Length - (um) - - volume_pool - - - phi = - - -} - -STATE { - - i (mM) - -} - -BREAKPOINT { - - SOLVE conc METHOD derivimplicit - - if( i < 0 ){ i = 0 } - if( i > ceiling ){ i = ceiling } - - -} - -DERIVATIVE conc { - - * beta - /tau - - - LOCAL thickness_cm, surf_area_cm2, volume_cm3 ? Note, normally dimensions are in um, but curr dens is in mA/cm2, etc - - thickness_cm = thickness *(1e-4) - surf_area_cm2 = area * 1e-8 - volume_cm3 = volume_pool * 1e-12 - - total_current = i * surf_area_cm2 - - - i' = ((-1 * total_current)/( * F * volume_cm3)) - ((i - rest_conc)) - - - i' = - (phi * i) - ((i - rest_conc)) - - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -? Creating synaptic mechanism, based on NEURON source impl of Exp2Syn - - -? Creating NMDA like synaptic mechanism, based on NEURON source impl of Exp2Syn - - -? Creating synaptic mechanism, based on Volker Steuber & Chiara Saviane implementation of 3 decay component facilitating synapse - - -? Creating synaptic mechanism for an electrical synapse - - -? Creating synaptic mechanism, based on Volker Steuber & Chiara Saviane implementation of 3 decay component facilitating synapse - - -? Creating synaptic mechanism, based on Andrew Davison's impl of Song and Abbot's STDP model - - - - yes - no - - - -TITLE Channel: - - - -COMMENT - -ENDCOMMENT - - -UNITS { - (nA) = (nanoamp) - (mV) = (millivolt) - (uS) = (microsiemens) -} - - -NEURON { - POINT_PROCESS - - - - NONSPECIFIC_CURRENT i - RANGE g, i - RANGE weight - - - RANGE vgap : Using a RANGE variable as opposed to POINTER for parallel mode - - - POINTER vgap : Using a POINTER as opposed to RANGE for serial mode - - - - - - RANGE tau_rise, tau_decay - GLOBAL total - - - RANGE _conc, eta, gamma, gblock - GLOBAL total - - - - RANGE tau_decay_2, tau_decay_3, gmax_2, gmax_3, ampl - - - RANGE tau_rec : time course of recovery from synaptic depression - RANGE tau_facil : time course of facilitation - RANGE U, Uinit : release probability and initial value - - - RANGE post_spike_thresh : voltage at which post syn cell will be considered spiking - RANGE t_post_spike, t_pre_spike : times of last post and pre spikes - RANGE stdp_weight_factor : multiplicative factor for weight which changes based on activity - - RANGE M, P - RANGE wmax : maximum synaptic weight which can be reached - RANGE del_weight_ltp, del_weight_ltd : - - RANGE tau_ltp, tau_ltd - - - RANGE i, e, gmax - NONSPECIFIC_CURRENT i - RANGE g, factor, factor_2, factor_3 - - - -} - -PARAMETER { - gmax = - - Conductance - tau_rise = - - Time (ms) <1e-9,1e9> - tau_decay = - - Time (ms) <1e-9,1e9> - e = - - Voltage (mV) - - - _conc = - - Concentration - - eta = - - InvConcentration - - gamma = - - InvVoltage - - - - - - - gmax_2 = - - - 0 - - Conductance - - tau_decay_2 = - - - 0 - - Time (ms) <1e-9,1e9> - - - gmax_2 = 0 - tau_decay_2 = 100000 - - - - - - gmax_3 = - - - 0 - - Conductance - - tau_decay_3 = - - - 0 - - Time (ms) <1e-9,1e9> - - - gmax_3 = 0 - tau_decay_3 = 100000 - - - - - - - - tau_rec = - - Time (ms) < 1e-9, 1e9 > - tau_facil = - - Time (ms) < 0 ,1e9 > - - Uinit = (1) < 0, 1 > :release probability - - - - tau_ltp= - - Time (ms) < 1e-9, 1e9 > - tau_ltd= - - Time (ms) < 1e-9, 1e9 > - - del_weight_ltp= (1) < 0, 1e9 > - del_weight_ltd= (1) < 0, 1e9 > - - wmax= (1) < 0, 1e9 > - - - post_spike_thresh = - - Voltage (mV) - - in_post_spike = 0 : 1 if post cell is spiking, 0 otherwise - - - - v (millivolt) - vgap (millivolt) - g = - - Conductance (microsiemens) - weight = 1 - -} - - -ASSIGNED { - i (nanoamp) -} - -BREAKPOINT { - i = weight * g * (v - vgap) -} - - - -ASSIGNED { - v (mV) - i (nA) - g (uS) - factor - factor_2 - factor_3 - - total (uS) - - R - U - gblock - - M - P - deltaw - t_post_spike (ms) - t_pre_spike (ms) - stdp_weight_factor - -} - -STATE { - A (uS) - B (uS) - C (uS) - D (uS) -} - -INITIAL { - LOCAL tp, tp_2, tp_3 - total = 0 - - if (tau_rise == 0) { - tau_rise = 1e-9 : will effectively give a single exponential timecourse synapse - } - - if (tau_rise/tau_decay > .999999) { - tau_rise = .999999*tau_decay : will result in an "alpha" synapse waveform - } - A = 0 - B = 0 - C = 0 - D = 0 - - tp = (tau_rise*tau_decay)/(tau_decay - tau_rise) * log(tau_decay/tau_rise) - factor = -exp(-tp/tau_rise) + exp(-tp/tau_decay) - factor = 1/factor - - tp_2 = (tau_rise*tau_decay_2)/(tau_decay_2 - tau_rise) * log(tau_decay_2/tau_rise) - factor_2 = -exp(-tp_2/tau_rise) + exp(-tp_2/tau_decay_2) - factor_2 = 1/factor_2 - - tp_3 = (tau_rise*tau_decay_3)/(tau_decay_3 - tau_rise) * log(tau_decay_3/tau_rise) - factor_3 = -exp(-tp_3/tau_rise) + exp(-tp_3/tau_decay_3) - factor_3 = 1/factor_3 - - - - - - M = 0 - P = 0 - deltaw = 0 - t_post_spike = 0 - t_pre_spike = 0 - stdp_weight_factor = 1 - -} - -BREAKPOINT { - SOLVE state METHOD cnexp - - gblock = 1 / (1+ (_conc * eta * exp(-1 * gamma * v))) - g = gmax * gblock * (B - A) - g = (gmax * (B - A)) + (gmax_2 * (C - A)) + (gmax_3 * (D - A)) - g = gmax * (B - A) - - i = g*(v - e) - -} - - -DERIVATIVE state { - A' = -A/tau_rise - B' = -B/tau_decay - C' = -C/tau_decay_2 - D' = -D/tau_decay_3 - -} - -NET_RECEIVE(weight (uS), U, R, tsyn (ms)) { - - LOCAL RUD - - INITIAL { - tsyn = -1 - printf("-- In the INITIAL statement in NET_RECEIVE\n") - U = Uinit - R = 1 - printf("-- t: %g, delt: %g, g: %g, U: %g, R: %g\n", t, t-tsyn, g, U, R) - } - - printf("------------------------------------------------------------\n") - - printf("-- t: %g, delt: %g, g: %g, U: %g, R: %g\n", t, t-tsyn, g, U, R) - - - if (tsyn > 0) { - - R = R * (1-U) * exp(-(t - tsyn)/tau_rec) + 1 - exp(-(t - tsyn)/tau_rec) - - if (tau_facil > 0) { - U = U * exp(-(t - tsyn)/tau_facil) + Uinit * (1 - (U * exp(-(t - tsyn)/tau_facil))) - } else { - U = Uinit - } - - } else { - printf("-- At first spike...\n") - } - - RUD = (U*R) - - printf("-- t: %g, delt: %g, g: %g, U: %g, R: %g, RUD: %g\n", t, t-tsyn, g, U, R, RUD) - - - - printf("------------------------------------------------------------\n") - - - printf("-- SPIKE at time: %f (%g), with weight %g!\n", t, t, weight) - - - - - if (t_post_spike >= 0) { - printf("-- Last post spike ago: %g\n", t-t_post_spike) - } - if (t_pre_spike >= 0) { - printf("-- Last pre spike ago: %g\n", t-t_pre_spike) - } - - if (weight >= 0) { : this is a pre-synaptic spike - - P = P*exp((t_pre_spike-t)/tau_ltp) + del_weight_ltp - - deltaw = wmax * M * exp((t_post_spike - t)/tau_ltd) - - t_pre_spike = t - - } else { : this is a post-synaptic spike - - M = M*exp((t_post_spike-t)/tau_ltd) - del_weight_ltd - - //Todo: double check this! - //? deltaw = wmax * P * exp(-(t - t_pre_spike)/tau_ltp) - deltaw = deltaw + wmax * P * exp(-(t - t_pre_spike)/tau_ltp) - - t_post_spike = t - - } - - - - - stdp_weight_factor = stdp_weight_factor + deltaw - - if (stdp_weight_factor > wmax) { stdp_weight_factor = wmax} - if (stdp_weight_factor < 0) { stdp_weight_factor = 0} - - - printf("pg-- stdp_weight_factor: %g, deltaw: %g, P: %g, M: %g\n", stdp_weight_factor,deltaw, P, M) - - if (weight >= 0) { : this is a pre-synaptic spike - - - - - LOCAL Ajump, Bjump, Cjump, Djump - Bjump = weight*factor*stdp_weight_factor - Cjump = weight*factor_2*stdp_weight_factor - Djump = weight*factor_3*stdp_weight_factor - - Ajump = (gmax*Bjump + gmax_2*Cjump + gmax_3*Djump)/(gmax + gmax_2 + gmax_3) - - state_discontinuity(A, A + Ajump) - state_discontinuity(B, B + Bjump) - state_discontinuity(C, C + Cjump) - state_discontinuity(D, D + Djump) - - - state_discontinuity(A, A + weight*factor*RUD*stdp_weight_factor) - state_discontinuity(B, B + weight*factor*RUD*stdp_weight_factor) - - - - - - - tsyn = t - - - } - - -} - - - - - - - - - - - - - - - - - - - - if () { - = - } else { - = - } - - = - - - - - - - diff --git a/tests/python/two_cells_nml_1.8/cellMechanisms/NaConductance/ChannelML_v1.8.1_PSICS.xsl b/tests/python/two_cells_nml_1.8/cellMechanisms/NaConductance/ChannelML_v1.8.1_PSICS.xsl deleted file mode 100644 index c31895cf..00000000 --- a/tests/python/two_cells_nml_1.8/cellMechanisms/NaConductance/ChannelML_v1.8.1_PSICS.xsl +++ /dev/null @@ -1,471 +0,0 @@ - - - - - - - - -0 - -30 - - - - true - false - - - - - - mV - V - - - - - - per_ms - per_s - - - - - - - - - This is a PSICS channel model file generated from a ChannelML v1.8.1 file. - - - - - - - - - - - - Error: this channel contains an Integrate and Fire mechanisms that cannot be mapped to PSICS. - - - - - - - - - - - - - - - Error: Ion concentration pools not yet supported in PSICS! - - - - - Error: Synapses not yet supported in PSICS! - - - - - - Error: the channel has a voltage_conc gate that is not supported in PSICS - - - Error: the channel has a conc dependent gate that is not supported in PSICS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - double offset = ; - v = v + offset; - - - - - - double temp_adj_ = 1; - - - - - - - double temp_adj_ = Math.pow(, (temperature - )/10); - - - double temp_adj_ = ; - - - - - - - - - - - - - - double = 0; - - - - - - - - - - - - - - - - - - - - - - - tau - - - - - tau - - - - - - - tau = 1/(alpha + beta); - - - tau = tau/temp_adj_; - - - - - - - inf - - - - - - inf - - - - - - - - inf = alpha/(alpha + beta); - - - - - - double rate = 0; - double scale = 0; - double midpoint = 0; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - unsupported transition type - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - double = 0; - rate = - - InvTime - ; - - - rate = - - Time - ; - - - rate = ; - - - double = 0; - rate = ; // Warning: unrecognised rate variable! Don't know how to convert units! - - - scale = - - Voltage - ; - midpoint = - - Voltage - ; - - - - - = rate * Math.exp((v - midpoint) / scale); - - - = rate / (Math.exp((v - midpoint) / scale) + 1); - - - if ( 1e-6 > (Math.abs((v - midpoint)/ scale))) { - = rate * (1 + (v - midpoint)/scale/2); - } else { - = rate * ((v - midpoint) / scale) /(1 - (Math.exp(-1 * (v - midpoint)/scale))); - } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - exp - Math.exp - - - - - - celsius - temperature - - - - - - - - - - - if () { - = ; - } else { - = ; - } - - - = ; - - - - - - \ No newline at end of file diff --git a/tests/python/two_cells_nml_1.8/cellMechanisms/NaConductance/NaChannel_HH.xml b/tests/python/two_cells_nml_1.8/cellMechanisms/NaConductance/NaChannel_HH.xml deleted file mode 100644 index 5e52c69e..00000000 --- a/tests/python/two_cells_nml_1.8/cellMechanisms/NaConductance/NaChannel_HH.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - ChannelML file containing a single Channel description - - - - - Equations adapted from HH paper for modern convention of external potential being zero - - Padraig Gleeson - - - - Simple example of Na conductance in squid giant axon. Based on channel from Hodgkin and Huxley 1952 - - - - Padraig Gleeson - UCL - p.gleeson - at - ucl.ac.uk - - - - - A. L. Hodgkin and A. F. Huxley, A quantitative description of membrane current and - its application to conduction and excitation in nerve, J. Physiol., vol. 117, pp. 500-544, 1952. - http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&db=pubmed&dopt=Abstract&list_uids=12991237 - - - - Na channels - http://senselab.med.yale.edu/senselab/NeuronDB/channelGene2.htm#table2 - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tests/python/two_cells_nml_1.8/cellMechanisms/NaConductance/properties.xml b/tests/python/two_cells_nml_1.8/cellMechanisms/NaConductance/properties.xml deleted file mode 100644 index dd174f31..00000000 --- a/tests/python/two_cells_nml_1.8/cellMechanisms/NaConductance/properties.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - -Properties associated with the Cell Mechanism which allow it to be loaded into neuroConstruct. - -Note the following: - The Cell Mechanism name should not contain spaces and should match the name of the directory it's in - The name and description here will be replaced by the corresponding values in a ChannelML file if found - The filenames for the mappings are relative to the cellMechanism/(cellMechInstanceName) directory - Mechanism Type should only have values: Channel mechanism, Synaptic mechanism, Ion concentration, Point process, Gap junction - - -Simple example of Na conductance in squid giant axon. Based on channel from Hodgkin and Huxley 1952 -ChannelML_v1.8.1_NEURONmod.xsl -ChannelML_v1.8.1_GENESIStab.xsl -false -ChannelML based Cell Mechanism -true -Channel mechanism -NaChannel_HH.xml -ChannelML_v1.8.1_PSICS.xsl -false -NaConductance -Template based ChannelML file - diff --git a/tests/python/two_cells_nml_1.8/cellMechanisms/README b/tests/python/two_cells_nml_1.8/cellMechanisms/README deleted file mode 100644 index a7aa3585..00000000 --- a/tests/python/two_cells_nml_1.8/cellMechanisms/README +++ /dev/null @@ -1,2 +0,0 @@ -This is the directory where Cell Mechanism (channel, synapse, etc) files are stored, either the native environment (e.g. *.mod) files, or ChannelML based files. -Unlike the older cellProcesses dir, simply cutting and pasting these cell mech directories into another neuroConstruct project is sufficient for copying the cell mech to that project. diff --git a/tests/python/two_cells_nml_1.8/chem_model_sbml.xml b/tests/python/two_cells_nml_1.8/chem_model_sbml.xml deleted file mode 100644 index 6b8594a9..00000000 --- a/tests/python/two_cells_nml_1.8/chem_model_sbml.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/tests/python/two_cells_nml_1.8/config.xml b/tests/python/two_cells_nml_1.8/config.xml deleted file mode 100644 index 0827ee44..00000000 --- a/tests/python/two_cells_nml_1.8/config.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/python/two_cells_nml_1.8/morphologies/README b/tests/python/two_cells_nml_1.8/morphologies/README deleted file mode 100644 index cb949a61..00000000 --- a/tests/python/two_cells_nml_1.8/morphologies/README +++ /dev/null @@ -1,14 +0,0 @@ -There are two possible ways to save morphologies in neuroConstruct projects, both based on a mapping from the -set of Java classes describing the cell internally in neuroConstruct: -- XML based Java serialisation (*.java.xml files): a mapping to an XML file of the classes. Note: not any part of NeuroML. -- Serialised Java object form (*.java.ser files): a serialised representation of the Java classes. - -The second of these is quicker to load and save and the files are smaller. The first however can be opened (and edited!) -with a text editor. Change which format to use via Settings -> General Properties & Project Defaults/Project properties. - -Cell morphologies are stored in the morphologies directory of the project home directory. *.bak files in that dir backup -the previously stored morphology before a new one is saved (if a problem occurs saving a morphology, close the application, remove -the .bak from the name of the morphology file to use the previous structure of the cell when reloading the project). - -Note that the cells aren't currently stored in neuroConstruct projects in NeuroML/MorphML format, since new functionality -is usually added to the neuroConstruct Cell class before it is supported in the specifications. \ No newline at end of file diff --git a/tests/python/two_cells_nml_1.8/morphologies/SampleCell.java.ser b/tests/python/two_cells_nml_1.8/morphologies/SampleCell.java.ser deleted file mode 100644 index 2160bd116a18425720aaf64b1d18d29a56709264..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3292 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 diff --git a/tests/python/two_cells_nml_1.8/mumbl.xml b/tests/python/two_cells_nml_1.8/mumbl.xml deleted file mode 100644 index 157adc1a..00000000 --- a/tests/python/two_cells_nml_1.8/mumbl.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1.5e14 - 1e-16 - - - - - diff --git a/tests/python/two_cells_nml_1.8/simulations/README b/tests/python/two_cells_nml_1.8/simulations/README deleted file mode 100644 index 68e813e1..00000000 --- a/tests/python/two_cells_nml_1.8/simulations/README +++ /dev/null @@ -1 +0,0 @@ -This is the directory for the simulation data associated with the project diff --git a/tests/python/two_cells_nml_1.8/two_cells.ncx b/tests/python/two_cells_nml_1.8/two_cells.ncx deleted file mode 100644 index 734456a5..00000000 --- a/tests/python/two_cells_nml_1.8/two_cells.ncx +++ /dev/null @@ -1,516 +0,0 @@ - - - - - - - - This is a simple project with a single cell placed randomly in a 3D rectangular box. - -Go to tab Generate, press Generate Cell Positions and Connections, and then to visualise the results, go to tab Visualisation and press View, with Latest Generated Positions selected in the drop down box. - -If NEURON or GENESIS are installed, the cell can be simulated via tab Export. - - - neuroConstruct v1.7.0 - - - two_cells - - - - - - Name - - SampleRegion - - - - Colour - - - 255 - 255 - 255 - 255 - - - - - Description - - - - - - value - - - 50.0 - - - - - - - - - - - - - Cell Packing Adapter - - - - - - - - - Cell Type - - cellA - - - cellB - - - - Priority - - 10 - - - 9 - - - - Colour - - - 18 - 42 - 138 - 255 - - - - - 75 - 197 - 151 - 255 - - - - - Region Name - - SampleRegion - - - SampleRegion - - - - Cell Group Name - - purkinjeGroup - - - granuleGroup - - - - - - - - - - SampleCellGroup - - - * - - - SampleGraph - - - 50.0 - - - -90.0 - - - Plot and save - - - SamplePlot - - - 0 - - - - - - - purkinjeGroup - - - * - - - purkinjeGroup_v - - - 50.0 - - - -90.0 - - - Plot and save - - - purkinjeGroup_v - - - 0 - - - - - - - granuleGroup - - - * - - - granuleGroup_v - - - 50.0 - - - -90.0 - - - Plot and save - - - granuleGroup_v - - - 0 - - - - - - - - Java Serialized Object Format - - - - - 1 - - - - 144 - 166 - 232 - 255 - - - - - 255 - 255 - 255 - 255 - - - - - - - - - 0.02 - - - 100.0 - - - Sim_1 - - - true - - - 2 - - - - - - - - - 0.2 - - - - granuleGroup - - - - numberType - - - 11 - - - - - SampleIClamp - - - - - - - - - - - - granuleGroup - - - purkinjeGroup - - - - This is the default configuration of the Cell Groups, stimulations, plots, etc for this project - - - - SampleIClamp - - - - Default Simulation Configuration - - - - NetConn_purkinjeGroup_granuleGroup - - - NetConn_purkinjeGroup_granuleGroup_1 - - - - - granuleGroup_v - - - purkinjeGroup_v - - - SamplePlot - - - - 100.0 - - - - - - - - - Name - - NetConn_purkinjeGroup_granuleGroup - - - NetConn_purkinjeGroup_granuleGroup_1 - - - - AP speed - - 3.4028235E38 - - - 3.4028235E38 - - - - Synapse Type - - - - - - - - numberType - - - 11 - - - - 5.0 - - - - - DoubExpSyn - - - -20.0 - - - - - numberType - - - 11 - - - - - - - - - - - - - - - - numberType - - - 11 - - - - 5.0 - - - - - DoubExpSyn - - - -20.0 - - - - - numberType - - - 11 - - - - - - - - - - - Max/min - - - - - - - - - Search Pattern - - - - type - - - 0 - - - - - - - - type - - - 0 - - - - - - - Source - - purkinjeGroup - - - purkinjeGroup - - - - Connectivity Conditions - - - - false - - - - - - - false - - - - - - Target - - granuleGroup - - - granuleGroup - - - - - - diff --git a/tests/python/two_cells_nml_1.8/two_cells.nml b/tests/python/two_cells_nml_1.8/two_cells.nml deleted file mode 100644 index 7930446a..00000000 --- a/tests/python/two_cells_nml_1.8/two_cells.nml +++ /dev/null @@ -1,715 +0,0 @@ - - - - - -Complete network structure generated with project: two_cells saved with neuroConstruct v1.7.0 on: 05:54:01, 29-Jan-14 - -Cell Group: granuleGroup contains 1 cells -Cell Group: purkinjeGroup contains 1 cells - -Network connection: NetConn_purkinjeGroup_granuleGroup_1 contains 1 individual synaptic connections -Network connection: NetConn_purkinjeGroup_granuleGroup contains 1 individual synaptic connections - - - - - - - - - - - - - - - - - - - A very simplified cerebellar Granule like Cell for testing purposes only - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - all - soma_group - - - - all - axon_group - - - - all - axon_group - - - - all - axon_group - - - - - - - - - - - all - - - - - - all - - - - - - all - - - - - - soma_group - - - - - - - A very simplified Purkinje Cell for testing purposes only - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - all - soma_group - - - - all - axon_group - - - - all - axon_group - - - - all - axon_group - - - - all - dendrite_group - - - - all - dendrite_group - - - - all - dendrite_group - - - - all - dendrite_group - - - - all - dendrite_group - - - - all - dendrite_group - - - - all - dendrite_group - - - - all - dendrite_group - - - - all - dendrite_group - - - - all - dendrite_group - - - - all - dendrite_group - - - - all - dendrite_group - - - - all - dendrite_group - - - - all - dendrite_group - main_dends - - - - all - dendrite_group - main_dends - - - - all - dendrite_group - main_dends - - - - all - dendrite_group - main_dends - - - - all - dendrite_group - main_dends - - - - all - dendrite_group - main_dends - - - - all - dendrite_group - main_dends - - - - all - dendrite_group - main_dends - - - - all - dendrite_group - main_dends - - - - all - dendrite_group - main_dends - - - - all - dendrite_group - main_dends - - - - all - dendrite_group - main_dends - - - - all - dendrite_group - main_dends - - - - all - dendrite_group - main_dends - - - - all - dendrite_group - main_dends - - - - all - dendrite_group - main_dends - - - - all - dendrite_group - main_dends - - - - all - dendrite_group - main_dends - - - - all - dendrite_group - main_dends - - - - all - dendrite_group - main_dends - - - - all - dendrite_group - main_dends - - - - all - dendrite_group - main_dends - - - - all - dendrite_group - main_dends - - - - all - dendrite_group - main_dends - - - - all - dendrite_group - main_dends - - - - all - dendrite_group - main_dends - - - - all - dendrite_group - main_dends - - - - - - - - - - - all - - - - - - all - - - - - - all - - - - - - axon_group - - - - - - - - - - - - Padraig Gleeson - - - - Simple example of a synaptic mechanism, which consists of a postsynaptic conductance which changes as - double exponential function of time. Mappings exist for NEURON and GENESIS. - - - Receptor properties - http://senselab.med.yale.edu/senselab/NeuronDB/receptors2.asp - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/requirements.txt b/tests/requirements.txt new file mode 100644 index 00000000..0483ee46 --- /dev/null +++ b/tests/requirements.txt @@ -0,0 +1,7 @@ +coverage +pytest +pytest-cov +python-libsbml +pyneuroml +scipy +matplotlib diff --git a/tests/python/_neuroml/CA1.net.xml b/tests/support/_neuroml/CA1.net.xml similarity index 100% rename from tests/python/_neuroml/CA1.net.xml rename to tests/support/_neuroml/CA1.net.xml diff --git a/tests/python/_neuroml/CA1.py b/tests/support/_neuroml/CA1.py similarity index 100% rename from tests/python/_neuroml/CA1.py rename to tests/support/_neuroml/CA1.py diff --git a/tests/python/_neuroml/CA1_hsolve.py b/tests/support/_neuroml/CA1_hsolve.py similarity index 100% rename from tests/python/_neuroml/CA1_hsolve.py rename to tests/support/_neuroml/CA1_hsolve.py diff --git a/tests/python/_neuroml/CA1inhomog.net.xml b/tests/support/_neuroml/CA1inhomog.net.xml similarity index 100% rename from tests/python/_neuroml/CA1inhomog.net.xml rename to tests/support/_neuroml/CA1inhomog.net.xml diff --git a/tests/python/_neuroml/CA1soma.net.xml b/tests/support/_neuroml/CA1soma.net.xml similarity index 100% rename from tests/python/_neuroml/CA1soma.net.xml rename to tests/support/_neuroml/CA1soma.net.xml diff --git a/tests/python/_neuroml/FvsI_CA1.py b/tests/support/_neuroml/FvsI_CA1.py similarity index 100% rename from tests/python/_neuroml/FvsI_CA1.py rename to tests/support/_neuroml/FvsI_CA1.py diff --git a/tests/python/_neuroml/README b/tests/support/_neuroml/README similarity index 100% rename from tests/python/_neuroml/README rename to tests/support/_neuroml/README diff --git a/tests/python/_neuroml/__init__.py b/tests/support/_neuroml/__init__.py similarity index 100% rename from tests/python/_neuroml/__init__.py rename to tests/support/_neuroml/__init__.py diff --git a/tests/python/_neuroml/cells_channels/CA1soma.morph.xml b/tests/support/_neuroml/cells_channels/CA1soma.morph.xml similarity index 100% rename from tests/python/_neuroml/cells_channels/CA1soma.morph.xml rename to tests/support/_neuroml/cells_channels/CA1soma.morph.xml diff --git a/tests/python/_neuroml/cells_channels/Gran_KDr_98.xml b/tests/support/_neuroml/cells_channels/Gran_KDr_98.xml similarity index 100% rename from tests/python/_neuroml/cells_channels/Gran_KDr_98.xml rename to tests/support/_neuroml/cells_channels/Gran_KDr_98.xml diff --git a/tests/python/_neuroml/cells_channels/Gran_NaF_98.xml b/tests/support/_neuroml/cells_channels/Gran_NaF_98.xml similarity index 100% rename from tests/python/_neuroml/cells_channels/Gran_NaF_98.xml rename to tests/support/_neuroml/cells_channels/Gran_NaF_98.xml diff --git a/tests/python/_neuroml/cells_channels/Purkinje_KA.xml b/tests/support/_neuroml/cells_channels/Purkinje_KA.xml similarity index 100% rename from tests/python/_neuroml/cells_channels/Purkinje_KA.xml rename to tests/support/_neuroml/cells_channels/Purkinje_KA.xml diff --git a/tests/python/_neuroml/cells_channels/README b/tests/support/_neuroml/cells_channels/README similarity index 100% rename from tests/python/_neuroml/cells_channels/README rename to tests/support/_neuroml/cells_channels/README diff --git a/tests/python/_neuroml/cells_channels/hd.xml b/tests/support/_neuroml/cells_channels/hd.xml similarity index 100% rename from tests/python/_neuroml/cells_channels/hd.xml rename to tests/support/_neuroml/cells_channels/hd.xml diff --git a/tests/python/_neuroml/cells_channels/hd_minus73.xml b/tests/support/_neuroml/cells_channels/hd_minus73.xml similarity index 100% rename from tests/python/_neuroml/cells_channels/hd_minus73.xml rename to tests/support/_neuroml/cells_channels/hd_minus73.xml diff --git a/tests/python/_neuroml/cells_channels/kad.xml b/tests/support/_neuroml/cells_channels/kad.xml similarity index 100% rename from tests/python/_neuroml/cells_channels/kad.xml rename to tests/support/_neuroml/cells_channels/kad.xml diff --git a/tests/python/_neuroml/cells_channels/kap.xml b/tests/support/_neuroml/cells_channels/kap.xml similarity index 100% rename from tests/python/_neuroml/cells_channels/kap.xml rename to tests/support/_neuroml/cells_channels/kap.xml diff --git a/tests/python/_neuroml/cells_channels/kdr.xml b/tests/support/_neuroml/cells_channels/kdr.xml similarity index 100% rename from tests/python/_neuroml/cells_channels/kdr.xml rename to tests/support/_neuroml/cells_channels/kdr.xml diff --git a/tests/python/_neuroml/cells_channels/na3.xml b/tests/support/_neuroml/cells_channels/na3.xml similarity index 100% rename from tests/python/_neuroml/cells_channels/na3.xml rename to tests/support/_neuroml/cells_channels/na3.xml diff --git a/tests/python/_neuroml/cells_channels/nax.xml b/tests/support/_neuroml/cells_channels/nax.xml similarity index 100% rename from tests/python/_neuroml/cells_channels/nax.xml rename to tests/support/_neuroml/cells_channels/nax.xml diff --git a/tests/python/_neuroml/cells_channels/pas.xml b/tests/support/_neuroml/cells_channels/pas.xml similarity index 100% rename from tests/python/_neuroml/cells_channels/pas.xml rename to tests/support/_neuroml/cells_channels/pas.xml diff --git a/tests/python/_neuroml/count.py b/tests/support/_neuroml/count.py similarity index 100% rename from tests/python/_neuroml/count.py rename to tests/support/_neuroml/count.py diff --git a/tests/python/test_files b/tests/support/test_files similarity index 100% rename from tests/python/test_files rename to tests/support/test_files diff --git a/tests/support/test_hhfit.py b/tests/support/test_hhfit.py new file mode 100644 index 00000000..0a77f075 --- /dev/null +++ b/tests/support/test_hhfit.py @@ -0,0 +1,131 @@ +# -*- coding: utf-8 -*- + +# Author: Subha +# Maintainer: Dilawar Singh +# Created: Tue May 21 16:34:45 2013 (+0530) +# This test is fragile. + +from __future__ import print_function, division, absolute_import +import numpy as np +import unittest +import matplotlib +matplotlib.use('Agg') +import matplotlib.pyplot as plt +import moose.neuroml2.hhfit as hhfit + +np.random.seed(10) + + +class TestFindRateFn(unittest.TestCase): + def setUp(self): + self.vmin = -120e-3 + self.vmax = 40e-3 + self.vdivs = 640 + self.v_array = np.linspace(self.vmin, self.vmax, self.vdivs + 1) + # Parameters for sigmoid function - from traub2005, NaF->m_inf + p_sigmoid = (1.0, 1 / -10e-3, -38e-3, 0.0) + self.sigmoid = p_sigmoid[0] / ( + 1.0 + np.exp(p_sigmoid[1] * + (self.v_array - p_sigmoid[2]))) + p_sigmoid[3] + self.p_sigmoid = p_sigmoid + # Parameters for exponential function - from traub2005, KC->n_inf + p_exp = (2e3, 1 / -27e-3, -53.5e-3, 0.0) + self.exp = p_exp[0] * np.exp(p_exp[1] * + (self.v_array - p_exp[2])) + p_exp[3] + self.p_exp = p_exp + # Parameters for linoid function: alpha_n from original Hodgkin-Huxley K channel. + p_linoid = (-0.01 * 1e3, -1 / 10e-3, 10e-3, 0.0) + self.linoid = p_linoid[3] + p_linoid[0] * \ + (self.v_array - p_linoid[2]) / (np.exp(p_linoid[1] * (self.v_array - p_linoid[2])) - 1) + self.p_linoid = p_linoid + # This is tau_m of transient Ca2+ current (eq. 7) from + # Huguenard and McCormick, J Neurophysiol, 68:1373-1383, + # 1992.; + #1e-3 * (0.612 + 1 / (np.exp((self.v_array*1e3 + 132)/-16.7) + np.exp((self.v_array*1e3 + 16.8)/18.2))) + p_dblexp = (1e-3, -1 / 16.7e-3, -132e-3, 1 / 18.2e-3, -16.8e-3, + 0.612e-3) + self.dblexp = p_dblexp[5] + p_dblexp[0] / ( + np.exp(p_dblexp[1] * (self.v_array - p_dblexp[2])) + + np.exp(p_dblexp[3] * (self.v_array - p_dblexp[4]))) + self.p_dblexp = p_dblexp + + def test_sigmoid(self): + print('Testing sigmoid') + fn, params = hhfit.find_ratefn(self.v_array, self.sigmoid) + print('Sigmoid params original:', self.p_sigmoid, 'detected:', params) + self.assertEqual(hhfit.sigmoid, fn) + rms_error = np.sqrt( + np.mean((self.sigmoid - fn(self.v_array, *params))**2)) + self.assertAlmostEqual(rms_error / max(abs(self.sigmoid)), + 0.0, + places=3) + plt.plot(self.v_array, self.sigmoid, 'y-', self.v_array, + hhfit.sigmoid(self.v_array, *self.p_sigmoid), 'b--', + self.v_array, fn(self.v_array, *params), 'r-.') + plt.legend('original sigmoid %s fitted %s' % (self.p_sigmoid, fn)) + plt.savefig("__test_sigmoid.png") + + def test_exponential(self): + print('Testing exponential') + fn, params = hhfit.find_ratefn(self.v_array, self.exp) + print('Exponential params original:', self.p_exp, 'detected:', params) + if params is not None: + # The `find_ratefn` might return a parameter array for different + # function sometimes. exponential takes only upto 5 parameters. + fnval = hhfit.exponential(self.v_array, *params[:4]) + self.assertEqual(hhfit.exponential, fn) + # The same exponential can be satisfied by an infinite number + # of parameter values. Hence we cannot compare the parameters, + # but only the fit + rms_error = np.sqrt(np.sum((self.exp - fnval)**2)) + print(rms_error, rms_error / max(self.exp)) + self.assertAlmostEqual(rms_error / max(self.exp), 0.0, places=3) + plt.plot(self.v_array, self.exp, 'y-', self.v_array, + hhfit.exponential(self.v_array, *self.p_exp), 'b--', + self.v_array, fnval, 'r-.') + plt.legend('original exp %s fitted %s' % (self.p_exp, fn)) + out = "__test_exponential.png" + plt.savefig(out) + print('Plot is saved saved to %s' % out) + else: + print("[INFO ] Failed find a suitable approximation...") + + + def test_linoid(self): + print('Testing linoid') + fn, params = hhfit.find_ratefn(self.v_array, self.linoid) + if params is not None: + print('Linoid params original:', self.p_linoid, 'detected:', params) + self.assertEqual(hhfit.linoid, fn) + fnval = fn(self.v_array, *params) + rms_error = np.sqrt(np.mean((self.linoid - fnval)**2)) + self.assertAlmostEqual(rms_error / max(self.linoid), 0.0, places=3) + plt.plot(self.v_array, self.linoid, 'y-', self.v_array, + hhfit.linoid(self.v_array, *self.p_linoid), 'b--', + self.v_array, fn(self.v_array, *params), 'r-.') + plt.legend('Original linoid %s fitted %s' % (self.p_linoid, fn)) + out = "__test_linoid.png" + plt.savefig(out) + print('Plot is saved saved to %s' % out) + else: + print('Failed to find a suitable fit.') + + def test_dblexponential(self): + print('Testing double exponential') + fn, params = hhfit.find_ratefn(self.v_array, self.dblexp) + fnval = fn(self.v_array, *params) + plt.plot(self.v_array, self.dblexp, 'y-', self.v_array, + hhfit.double_exp(self.v_array, *self.p_dblexp), 'b--', + self.v_array, fnval, 'r-.') + self.assertEqual(hhfit.double_exp, fn) + rms_error = np.sqrt(np.mean((self.dblexp - fnval)**2)) + print(params, rms_error) + self.assertAlmostEqual(rms_error / max(self.dblexp), 0.0, places=3) + plt.legend('Original dblexp %s, fitted %s' %(self.dblexp, fn)) + out = "__test_dblexponential.png" + plt.savefig(out) + print('Plot is saved saved to %s' % out) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/python/test_neuroml.py b/tests/support/test_neuroml.py similarity index 95% rename from tests/python/test_neuroml.py rename to tests/support/test_neuroml.py index 6bca818d..4a6cd83a 100644 --- a/tests/python/test_neuroml.py +++ b/tests/support/test_neuroml.py @@ -13,6 +13,8 @@ import sys import os +import moose + # the model lives in the same directory as the test script modeldir = os.path.dirname(__file__) @@ -20,10 +22,6 @@ from _neuroml.FvsI_CA1 import ca1_main, loadModel from _neuroml.CA1 import loadGran98NeuroML_L123 -def test_all(): - test_ca1() - test_gran() - def test_ca1(): p = os.path.join(modeldir, '_neuroml/cells_channels/CA1soma.morph.xml') loadModel(p) @@ -36,6 +34,9 @@ def test_gran(): p = os.path.join(modeldir, '_neuroml/CA1soma.net.xml') assert loadGran98NeuroML_L123(p) in [8,9] +def main(): + test_ca1() + test_gran() + if __name__ == '__main__': - #unittest.main() - test_all() + main() diff --git a/tests/python/test_neuroml2.py b/tests/support/test_neuroml2.py similarity index 84% rename from tests/python/test_neuroml2.py rename to tests/support/test_neuroml2.py index d1b34ea3..06275d62 100644 --- a/tests/python/test_neuroml2.py +++ b/tests/support/test_neuroml2.py @@ -10,24 +10,16 @@ # NOTE: This script does not work with python3 # See https://github.com/NeuroML/NeuroML2/issues/116 . If this bug is fixed then # remove this code block. -import neuroml as nml -a = nml.nml.nml.IonChannel() -try: - b = {a : 1 } -except TypeError as e: - print( 'Failed due to https://github.com/NeuroML/NeuroML2/issues/116' ) - quit( 0 ) import moose import moose.utils as mu -import sys import os import numpy as np SCRIPT_DIR = os.path.dirname( os.path.realpath( __file__ ) ) -def run( nogui = True ): +def test_nml2( nogui = True ): global SCRIPT_DIR filename = os.path.join(SCRIPT_DIR, 'test_files/passiveCell.nml' ) mu.info('Loading: %s' % filename ) @@ -51,7 +43,6 @@ def run( nogui = True ): moose.reinit() moose.start(simtime) print("Finished simulation!") - t = np.linspace(0, simtime, len(vm.vector)) yvec = vm.vector injvec = inj.vector * 1e12 m1, u1 = np.mean( yvec ), np.std( yvec ) @@ -60,7 +51,6 @@ def run( nogui = True ): assert np.isclose( u1, 0.0121968 ), u1 assert np.isclose( m2, 26.64890 ), m2 assert np.isclose( u2, 37.70607574 ), u2 - quit( 0 ) if __name__ == '__main__': - run( ) + test_nml2() diff --git a/tests/python/test_nsdf.py b/tests/support/test_nsdf.py similarity index 97% rename from tests/python/test_nsdf.py rename to tests/support/test_nsdf.py index eb9a7f77..d4ce10b4 100644 --- a/tests/python/test_nsdf.py +++ b/tests/support/test_nsdf.py @@ -80,12 +80,12 @@ def setup_model(): t_lead.fieldIndex) nsdf.stringAttr[eventDataPath] = 's' -if __name__ == '__main__': +def test_nsdf(): try: setup_model() except AttributeError as e: print( 'This MOOSE is not compiled with NSDF support' ) - quit(0) + return 0 except Exception as e: raise e # Very basic tests @@ -97,3 +97,9 @@ def setup_model(): data = np.loadtxt( nsdfFile ) assert len(data) == 4, "Expected 4 entries" + +def main(): + test_nsdf() + +if __name__ == '__main__': + main() diff --git a/tests/python/test_sbml.py b/tests/support/test_sbml.py similarity index 68% rename from tests/python/test_sbml.py rename to tests/support/test_sbml.py index 0a1eed99..3670d44a 100644 --- a/tests/python/test_sbml.py +++ b/tests/support/test_sbml.py @@ -12,31 +12,32 @@ __email__ = "dilawars@ncbs.res.in" __status__ = "Development" -import sys import os - import moose -import moose.utils as mu print( 'Using moose form %s' % moose.__file__ ) print( '\t Moose version %s' % moose.version( ) ) # the model lives in the same directory as the test script -modeldir = os.path.dirname( os.path.realpath( __file__ ) ) +sdir_ = os.path.dirname( os.path.realpath( __file__ ) ) -def main(): - modelname = os.path.join(modeldir, './chem_models/00001-sbml-l3v1.xml' ) +def test_sbml(): + modelname = os.path.join(sdir_, '..', 'data', '00001-sbml-l3v1.xml') model = moose.mooseReadSBML( modelname, '/sbml' ) - c = moose.element('/clock') + if not model: + print("Most likely python-libsbml is not installed.") + return 0 moose.reinit() moose.start(200) - check( ) - -def check( ): # TODO: Add more tests here. p = moose.wildcardFind( '/sbml/##' ) + assert len(p) == 8 + names = ['compartment', 'mesh', 'S1', 'info', 'S2', 'info', 'reaction1'] for x in p: - print( x ) + assert x.name in names + +def main(): + test_sbml() if __name__ == '__main__': main() diff --git a/utility/CMakeLists.txt b/utility/CMakeLists.txt index 00c014f1..9a79f1dc 100644 --- a/utility/CMakeLists.txt +++ b/utility/CMakeLists.txt @@ -17,5 +17,5 @@ add_library(utility Vec.cpp cnpy.cpp fileutils.cpp - #matrix_util.cpp + utility.cpp ) diff --git a/utility/boost_ode.h b/utility/boost_ode.h new file mode 100644 index 00000000..28818230 --- /dev/null +++ b/utility/boost_ode.h @@ -0,0 +1,39 @@ +/* + * ===================================================================================== + * + * Filename: boost_ode.h + * + * Description: Utility function for Boost ODEINT library. + * + * Version: 1.0 + * Created: Saturday 24 November 2018 04:54:32 IST + * Revision: none + * Compiler: gcc + * + * Author: Dilawar Singh (), dilawars@ncbs.res.in + * Organization: NCBS Bangalore + * + * ===================================================================================== + */ +#ifndef BOOST_ODE_H +#define BOOST_ODE_H + +#include +#include +#include + +typedef double value_type_; +typedef std::vector vector_type_; + +typedef boost::numeric::odeint::runge_kutta4< vector_type_ > rk4_stepper_type_; +typedef boost::numeric::odeint::runge_kutta_dopri5< vector_type_ > rk_dopri_stepper_type_; +typedef boost::numeric::odeint::modified_midpoint< vector_type_ > rk_midpoint_stepper_type_; + +/*----------------------------------------------------------------------------- + * This stepper type found to be most suitable for adaptive solver. The gsl + * implementation has runge_kutta_fehlberg78 solver. + *-----------------------------------------------------------------------------*/ +typedef boost::numeric::odeint::runge_kutta_cash_karp54< vector_type_ > rk_karp_stepper_type_; +typedef boost::numeric::odeint::runge_kutta_fehlberg78< vector_type_ > rk_felhberg_stepper_type_; + +#endif /* end of include guard: BOOST_ODE_H */ diff --git a/utility/matrix_util.cpp b/utility/matrix_util.cpp deleted file mode 100644 index fecb4a4b..00000000 --- a/utility/matrix_util.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - * ===================================================================================== - * - * Filename: matrix_util.cpp - * - * Description: Some matrix utility function. Used when boost library is - * used. - * - * Version: 1.0 - * Created: 05/10/2016 05:25:27 PM - * Revision: none - * Compiler: gcc - * - * Author: Dilawar Singh (), dilawars@ncbs.res.in - * Organization: NCBS Bangalore - * - * ===================================================================================== - */ - -#ifdef USE_BOOST_ODE - -#include "matrix_util.h" - -#define EPSILON 1e-9 /* Treat number below it as 0 */ - -/*----------------------------------------------------------------------------- - * These functions computes rank of a matrix. - *-----------------------------------------------------------------------------*/ - -/** - * @brief Swap row r1 and r2. - * - * @param mat Matrix input - * @param r1 index of row 1 - * @param r2 index of row 2 - */ - -void swapRows( ublas::matrix< value_type >& mat, unsigned int r1, unsigned int r2) -{ - ublas::vector temp( mat.size2() ); - for (size_t i = 0; i < mat.size2(); i++) - { - temp[i] = mat(r1, i ); - mat(r1, i ) = mat(r2, i ); - } - - for (size_t i = 0; i < mat.size2(); i++) - mat(r2, i) = temp[i]; -} - - -int reorderRows( ublas::matrix< value_type >& U, int start, int leftCol ) -{ - int leftMostRow = start; - int numReacs = U.size2() - U.size1(); - int newLeftCol = numReacs; - for ( size_t i = start; i < U.size1(); ++i ) - { - for ( int j = leftCol; j < numReacs; ++j ) - { - if ( fabs( U(i,j )) > EPSILON ) - { - if ( j < newLeftCol ) - { - newLeftCol = j; - leftMostRow = i; - } - break; - } - } - } - - if ( leftMostRow != start ) // swap them. - swapRows( U, start, leftMostRow ); - - return newLeftCol; -} - -void eliminateRowsBelow( ublas::matrix< value_type >& U, int start, int leftCol ) -{ - int numMols = U.size1(); - double pivot = U( start, leftCol ); - assert( fabs( pivot ) > EPSILON ); - for ( int i = start + 1; i < numMols; ++i ) - { - double factor = U(i, leftCol); - if( fabs ( factor ) > EPSILON ) - { - factor = factor / pivot; - for ( size_t j = leftCol + 1; j < U.size2(); ++j ) - { - double x = U(i,j); - double y = U( start, j ); - x -= y * factor; - if ( fabs( x ) < EPSILON ) - x = 0.0; - U( i, j ) = x; - } - } - U(i, leftCol) = 0.0; - } -} - -unsigned int rankUsingBoost( ublas::matrix& U ) -{ - int numMols = U.size1(); - int numReacs = U.size2() - numMols; - int i; - // Start out with a nonzero entry at 0,0 - int leftCol = reorderRows( U, 0, 0 ); - - for ( i = 0; i < numMols - 1; ++i ) - { - eliminateRowsBelow( U, i, leftCol ); - leftCol = reorderRows( U, i + 1, leftCol ); - if ( leftCol == numReacs ) - break; - } - return i + 1; -} - -#endif /* ----- not USE_BOOST_ODE ----- */ diff --git a/utility/numutil.cpp b/utility/numutil.cpp index 10b04195..4a30c043 100644 --- a/utility/numutil.cpp +++ b/utility/numutil.cpp @@ -6,9 +6,9 @@ * Created: 2007-11-02 11:46:40 ********************************************************************/ +#include "numutil.h" #include #include "../randnum/RNG.h" -#include "numutil.h" bool almostEqual(float x, float y, float epsilon) { @@ -61,6 +61,9 @@ double approximateWithInteger_debug(const char* name, const double x, moose::RNG double approximateWithInteger(const double x, moose::RNG& rng) { +#if 0 + return std::round(x); +#else assert(x >= 0.0); double xf = std::floor(x); double base = x - xf; @@ -69,5 +72,11 @@ double approximateWithInteger(const double x, moose::RNG& rng) if( rng.uniform() < base) return xf+1.0; return xf; +#endif +} + +double approximateWithInteger(const double x) +{ + return approximateWithInteger(x, moose::rng); } diff --git a/utility/numutil.h b/utility/numutil.h index b20bba5f..bdc01d73 100644 --- a/utility/numutil.h +++ b/utility/numutil.h @@ -13,16 +13,7 @@ #include #include #include "../randnum/RNG.h" - -#include "../randnum/RNG.h" - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -#ifndef M_E -#define M_E 2.7182818284590452353 -#endif +#include "../basecode/global.h" /** @@ -70,8 +61,8 @@ bool isClose( T a, T b, T tolerance ) bool almostEqual(float x, float y, float epsilon = FLT_EPSILON); bool almostEqual(double x, double y, double epsilon = DBL_EPSILON); bool almostEqual(long double x, long double y, long double epsilon = LDBL_EPSILON); - double approximateWithInteger(const double x, moose::RNG& rng); +double approximateWithInteger(const double x); double approximateWithInteger_debug(const char* name, const double x, moose::RNG& rng); #endif diff --git a/utility/print_function.hpp b/utility/print_function.hpp index e7ec0b90..76100961 100644 --- a/utility/print_function.hpp +++ b/utility/print_function.hpp @@ -70,7 +70,7 @@ using namespace std; #endif #define MOOSE_WARN( a ) { \ - stringstream ss; ss << a; \ + stringstream ss; ss << __func__ << ": " << a; \ moose::showWarn( ss.str() ); \ } @@ -214,8 +214,8 @@ namespace moose { /* Be safe than sorry */ if(!reset) ss << T_RESET; + cout << ss.str() << endl; - cout.flush( ); } /* @@ -307,5 +307,20 @@ namespace moose { logF.close(); } + template + void print_array( T* a, size_t n, const string prefix = "" ) + { + stringstream ss; + ss << prefix; + for (size_t i = 0; i < n; i++) + { + ss << a[i] << ' '; + if( (i+1) % 20 == 0 ) + ss << endl; + } + ss << endl; + cerr << ss.str(); + } + } #endif /* ----- #ifndef print_function_INC ----- */ diff --git a/utility/setupenv.cpp b/utility/setupenv.cpp index 088f84f4..80b5a91d 100644 --- a/utility/setupenv.cpp +++ b/utility/setupenv.cpp @@ -38,91 +38,79 @@ using namespace std; extern unsigned getNumCores(); -namespace moose { +namespace moose +{ - const map& getArgMap() +const map& getArgMap() +{ + static map argmap; + if (argmap.empty()) { - static map argmap; - if (argmap.empty()){ - char * verbosity = getenv("VERBOSITY"); - if (verbosity != NULL){ - argmap.insert(pair("VERBOSITY", string(verbosity))); - } else { - argmap.insert(pair("VERBOSITY", "0")); - } - char * isSingleThreaded = getenv("SINGLETHREADED"); - if (isSingleThreaded != NULL){ - argmap.insert(pair("SINGLETHREADED", string(isSingleThreaded))); - } - else { - argmap.insert(pair("SINGLETHREADED", "0")); - } - char * isInfinite = getenv("INFINITE"); - if (isInfinite != NULL){ - argmap.insert(pair("INFINITE", string(isInfinite))); - } - // else { - // argmap.insert(pair("INFINITE", "0")); - // } - - char * numCores = getenv("NUMCORES"); - if (numCores != NULL){ - argmap.insert(pair("NUMCORES", string(numCores))); - } else { - unsigned int cores = getNumCores(); - stringstream s; - s << cores; - argmap.insert(pair("NUMCORES", s.str())); - } - char * numNodes = getenv("NUMNODES"); - if (numNodes != NULL){ - argmap.insert(pair("NUMNODES", string(numNodes))); - } // else { - // argmap.insert(pair("NUMNODES", "1")); - // } - char * numProcessThreads = getenv("NUMPTHREADS"); - if (numProcessThreads != NULL){ - argmap.insert(pair("NUMPTHREADS", string(numProcessThreads))); - } - char * doQuit = getenv("QUIT"); - if (doQuit != NULL){ - argmap.insert(pair("QUIT", string(doQuit))); - } // else { - // argmap.insert(pair("QUIT", "0")); - // } - char * doUnitTests = getenv("DOUNITTESTS"); - if (doUnitTests != NULL){ - argmap.insert(pair("DOUNITTESTS", string(doUnitTests))); - } // else { - // argmap.insert(pair("DOUNITTESTS", "0")); - // } - char * doRegressionTests = getenv("DOREGRESSIONTESTS"); - if (doRegressionTests != NULL){ - argmap.insert(pair("DOREGRESSIONTESTS", string(doRegressionTests))); - } // else { - // argmap.insert(pair("DOREGRESSIONTESTS", "0")); - // } - + char * verbosity = getenv("VERBOSITY"); + if (verbosity != NULL) + { + argmap.insert(pair("VERBOSITY", string(verbosity))); + } + else + { + argmap.insert(pair("VERBOSITY", "0")); } - return argmap; + char * isInfinite = getenv("INFINITE"); + if (isInfinite != NULL) + { + argmap.insert(pair("INFINITE", string(isInfinite))); + } + + char * numNodes = getenv("NUMNODES"); + if (numNodes != NULL) + { + argmap.insert(pair("NUMNODES", string(numNodes))); + } + char * doQuit = getenv("QUIT"); + if (doQuit != NULL) + { + argmap.insert(pair("QUIT", string(doQuit))); + } + char * doUnitTests = getenv("DOUNITTESTS"); + if (doUnitTests != NULL) + { + argmap.insert(pair("DOUNITTESTS", string(doUnitTests))); + } } + return argmap; +} - /* --------------------------------------------------------------------------*/ - /** - * @Synopsis Get environment valus. - * - * @Param env Name of the environment variable. - * - * @Returns value of environment if set, empty string otherwise. - */ - /* ----------------------------------------------------------------------------*/ - string getEnv( const string& env ) +/* --------------------------------------------------------------------------*/ +/** + * @Synopsis Get environment valus. + * + * @Param env Name of the environment variable. + * + * @Returns value of environment if set, empty string otherwise. + */ +/* ----------------------------------------------------------------------------*/ +string getEnv( const string& env ) +{ + const char* pEnv = std::getenv( env.c_str() ); + if( pEnv ) + return string(pEnv); + return ""; +} + +int getEnvInt(const string& env, const int defaultVal=1) +{ + string e = getEnv(env); + if(e.empty()) + return defaultVal; + try { - const char* pEnv = std::getenv( env.c_str() ); - if( pEnv ) - return string(pEnv); - return ""; + return std::stoi(e); } + catch(std::exception& exc) + { + return defaultVal; + } +} } diff --git a/utility/strutil.cpp b/utility/strutil.cpp index 95b09450..c5c02b8c 100644 --- a/utility/strutil.cpp +++ b/utility/strutil.cpp @@ -177,4 +177,31 @@ string random_string( const unsigned len ) return s; } +void str_replace_all( string& str, const string& a, const string& b) +{ + if( a.size() == 0 ) + return; + + size_t index = 0; + while (true) + { + /* Locate the substring to replace. */ + index = str.find(a, index); + + if (index == std::string::npos) + break; + + /* Make the replacement. */ + str.erase( index, a.size() ); + str.insert( index, b ); + } +} + +bool isPrefix(const string& a, const string& b) +{ + if(a.size() < b.size()) + return false; + return (b.find(a, 0) == 0); +} + } diff --git a/utility/strutil.h b/utility/strutil.h index e2480d2b..9ed47e9a 100644 --- a/utility/strutil.h +++ b/utility/strutil.h @@ -55,6 +55,12 @@ namespace moose std::string random_string( const unsigned size ); + // Replace occurance of a substring in a given string. + void str_replace_all( std::string& str, const std::string& a, const std::string& b); + + // Is string a prefix of string b. + bool isPrefix(const std::string& a, const std::string& b); + /* --------------------------------------------------------------------------*/ /** * @Synopsis Converts a vector to string. diff --git a/utility/testing_macros.hpp b/utility/testing_macros.hpp index 30359ef9..c3c51a79 100644 --- a/utility/testing_macros.hpp +++ b/utility/testing_macros.hpp @@ -114,14 +114,14 @@ static ostringstream assertStream; moose::__dump__(assertStream.str(), moose::failed); \ } -#define ASSERT_TRUE( condition, msg) \ +#define ASSERT_TRUE(condition, msg) \ if( !(condition) ) {\ assertStream.str(""); \ assertStream << msg << endl; \ throw std::runtime_error( assertStream.str() );\ } -#define ASSERT_FALSE( condition, msg) \ +#define ASSERT_FALSE(condition, msg) \ if( (condition) ) {\ assertStream.str(""); \ assertStream.precision( 9 ); \ @@ -132,7 +132,7 @@ static ostringstream assertStream; #define ASSERT_EQ(a, b, token) \ if( ! doubleEq((a), (b)) ) { \ assertStream.str(""); \ - assertStream.precision( 9 ); \ + assertStream.precision( 12 ); \ LOCATION(assertStream) \ assertStream << "Expected " << a << ", received " << b << endl; \ assertStream << token << endl; \ @@ -143,7 +143,8 @@ static ostringstream assertStream; if(! doubleEq(a, b) ) { \ assertStream.str(""); \ LOCATION(assertStream); \ - assertStream << "Expected " << std::fixed << b << ", received " << a << endl; \ + assertStream.precision( 12 ); \ + assertStream << "Expected " << a << ", received " << b << endl; \ assertStream << token; \ moose::__dump__(assertStream.str(), moose::failed); \ throw std::runtime_error( "float equality test failed" ); \ diff --git a/utility/utility.cpp b/utility/utility.cpp new file mode 100644 index 00000000..9ad25807 --- /dev/null +++ b/utility/utility.cpp @@ -0,0 +1,31 @@ +/*** + * Description: Utility functions. + * + * Created: 2020-02-23 + + * Author: Dilawar Singh + * Organization: NCBS Bangalore + * License: MIT License + */ + +#include "utility.h" + +namespace moose { + + void splitIntervalInNParts(size_t max, size_t n, std::vector>& result) + { + size_t start = 0; + size_t stop = 0; + while(n > 0) + { + size_t f = (size_t) (max / n); + stop += f; + result.push_back({start, stop}); + start = stop; + n -= 1; + max -= f; + } + assert(max == 0); + } + +} // namespace moose diff --git a/utility/utility.h b/utility/utility.h index 33fae676..86a0aad4 100644 --- a/utility/utility.h +++ b/utility/utility.h @@ -11,7 +11,14 @@ #ifndef _UTILITY_H -#include "strutil.h" +#include +#include +#include +#include +#include +#include + +using namespace std; // See types.cpp file for definitions. namespace moose @@ -23,7 +30,9 @@ namespace moose // In setuptevn.cpp const map& getArgMap(); - string getEnv( const string& env); + + string getEnv(const string& env); + int getEnvInt(const string& env, const int defaultVal=1); // In fileutils.cpp bool filepath_exists( const string& path ); @@ -34,11 +43,22 @@ namespace moose * * @return */ - inline string basename( const string& path ) + inline std::string basename( const std::string& path ) { return path.substr( path.find_last_of('/') + 1 ); } + /* --------------------------------------------------------------------------*/ + /** + * @Synopsis Split a interval (0, max) in n parts which are almost equal + * to each other. + * + * @Param max + * @Param n + * @Param result. A vector of interval [start, end) (as std::pair). + */ + /* ----------------------------------------------------------------------------*/ + void splitIntervalInNParts(size_t max, size_t n, std::vector>& result); } From 2c33a0aa9fd7e12db6fc49cd8a9f74b20c8c5877 Mon Sep 17 00:00:00 2001 From: Dilawar Singh Date: Fri, 13 Mar 2020 11:48:56 +0530 Subject: [PATCH 2/7] builds locally. --- CMakeLists.txt | 25 +++++++++++-------------- cmake/build_moose-core.sh.in | 1 - 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cf83ee35..b424c787 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,20 +4,16 @@ set(CMAKE_BUILD_TYPE Release) # If from command line, version info is not passed, use the git to generate a # version file. If GIT fails, use the previous known version. -find_program(GIT_EXEC "git") -message( STATUS "Looking for git ${GIT_EXEC}" ) -if(VERSION_MOOSE) - message( STATUS "MOOSE version is set to ${VERSION_MOOSE} at build time" ) -elseif(GIT_EXEC) - message( STATUS "Getting version by reading git tags" ) - execute_process( - COMMAND ${GIT_EXEC} describe --tags --long - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} +if(NOT VERSION_MOOSE) + execute_process(COMMAND ${PYTHON_EXECUTABLE} moose-core/setup.py --version + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE VERSION_MOOSE - OUTPUT_STRIP_TRAILING_WHITESPACE - ) -endif( ) -message( STATUS "Building version ${VERSION_MOOSE}" ) + OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() + +add_definitions(-DMOOSE_VERSION="${VERSION_MOOSE}") +message(STATUS "MOOSE Version ${VERSION_MOOSE}") + # Prefix message( STATUS "CMAKE_INSTALL_PREFIX= ${CMAKE_INSTALL_PREFIX}" ) @@ -77,9 +73,10 @@ add_custom_command( OUTPUT ${OUTPUT_MOOSEBIN} COMMENT "Building pymoose in ${PYMOOSE_BUILD_DIR}" VERBATIM ) + add_custom_command( TARGET moose-core POST_BUILD COMMAND ${CMAKE_COMMAND} -E chdir ${PYMOOSE_INSTALL_DIR} tar xvf - ${PYMOOSE_BUILD_DIR}/bdist/pymoose-${VERSION_MOOSE}.CMAKE.tar.gz + ${PYMOOSE_BUILD_DIR}/pymoose-${VERSION_MOOSE}.CMAKE.tar.gz COMMENT "Unarchiving pymoose bdist" VERBATIM ) diff --git a/cmake/build_moose-core.sh.in b/cmake/build_moose-core.sh.in index 70eba010..8b5d4b08 100755 --- a/cmake/build_moose-core.sh.in +++ b/cmake/build_moose-core.sh.in @@ -22,4 +22,3 @@ cmake -DCMAKE_INSTALL_PREFIX=@PYMOOSE_INSTALL_DIR@ \ @CMAKE_PYMOOSE_ARGS@ \ @PYMOOSE_SOURCE_DIR@ make $MAKEOPTS -make bdist From 24097475dbcbc2c68fe1681def4952b4dab0acc8 Mon Sep 17 00:00:00 2001 From: Dilawar Singh Date: Fri, 13 Mar 2020 13:25:24 +0530 Subject: [PATCH 3/7] Use python3 (default). --- debian/rules | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/debian/rules b/debian/rules index 455987b8..b2819dd6 100755 --- a/debian/rules +++ b/debian/rules @@ -5,11 +5,11 @@ export MAKEOPTS=-j5 export DH_VERBOSE=1 %: - dh "$@" --buildsystem=cmake --with-python2 + dh "$@" --buildsystem=cmake --with-python3 override_dh_auto_configure: - dh_auto_configure -- -DVERSION_MOOSE=3.2.0-dev -DCMAKE_SKIP_RPATH=ON + dh_auto_configure -- -DCMAKE_SKIP_RPATH=ON override_dh_python2: dh_numpy - dh_python2 + dh_python3 From 6818f847bacc78d578efc37a8325613ea8183318 Mon Sep 17 00:00:00 2001 From: Dilawar Singh Date: Fri, 13 Mar 2020 14:22:32 +0530 Subject: [PATCH 4/7] Using moose-core/setup.py to get VERSION string. --- CMakeLists.txt | 17 +++++++++++------ debian/rules | 2 +- moose-core/setup.py | 15 ++++++++++----- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b424c787..edfb0337 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,16 +2,22 @@ cmake_minimum_required(VERSION 2.8) project(moose) set(CMAKE_BUILD_TYPE Release) -# If from command line, version info is not passed, use the git to generate a -# version file. If GIT fails, use the previous known version. +set(Python_ADDITIONAL_VERSIONS 2.7) +find_package(PythonInterp 3.5) +if(NOT PYTHONINTERP_FOUND) + find_package(PythonInterp 2.7) +endif() + +# NOTE: version should be changed in setup.py file. +# If moose version is not given, use setup.py file to get the default version. if(NOT VERSION_MOOSE) - execute_process(COMMAND ${PYTHON_EXECUTABLE} moose-core/setup.py --version - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + execute_process(COMMAND ${PYTHON_EXECUTABLE} setup.py --version + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/moose-core OUTPUT_VARIABLE VERSION_MOOSE OUTPUT_STRIP_TRAILING_WHITESPACE) endif() -add_definitions(-DMOOSE_VERSION="${VERSION_MOOSE}") +add_definitions(-DVERSION_MOOSE="${VERSION_MOOSE}") message(STATUS "MOOSE Version ${VERSION_MOOSE}") @@ -73,7 +79,6 @@ add_custom_command( OUTPUT ${OUTPUT_MOOSEBIN} COMMENT "Building pymoose in ${PYMOOSE_BUILD_DIR}" VERBATIM ) - add_custom_command( TARGET moose-core POST_BUILD COMMAND ${CMAKE_COMMAND} -E chdir ${PYMOOSE_INSTALL_DIR} tar xvf ${PYMOOSE_BUILD_DIR}/pymoose-${VERSION_MOOSE}.CMAKE.tar.gz diff --git a/debian/rules b/debian/rules index b2819dd6..db2935ad 100755 --- a/debian/rules +++ b/debian/rules @@ -1,6 +1,6 @@ #!/usr/bin/make -f -export MAKEOPTS=-j5 +export MAKEOPTS=-j$(bash nproc) export DH_VERBOSE=1 diff --git a/moose-core/setup.py b/moose-core/setup.py index b973d53c..ef7ba3d4 100644 --- a/moose-core/setup.py +++ b/moose-core/setup.py @@ -49,11 +49,16 @@ numCores_ = multiprocessing.cpu_count() - -version_ = '3.2.1.dev%s' % stamp - -# importlib is available only for python3. Since we build wheels, prefer .so -# extension. This way a wheel built by any python3.x will work with any python3. +# If environment variable MOOSE_VERSION is set, use it else use the default +# version. +version_ = os.environ.get('MOOSE_VERSION', '3.2.1.dev%s' % stamp) + +# And, if VERSION file exists in the source directory, read its content to set +# version. +versionFile = os.path.join(sdir_, 'VERSION') +if os.path.exists(versionFile): + with open(versionFile, 'r') as f: + version_ = f.read().strip() class CMakeExtension(Extension): def __init__(self, name, **kwargs): From 43ea0525ce73c81f94c483ce3802fb1a6adfb6ae Mon Sep 17 00:00:00 2001 From: Dilawar Singh Date: Fri, 13 Mar 2020 14:35:33 +0530 Subject: [PATCH 5/7] build with python2. --- debian/changelog | 6 ++++++ debian/rules | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/debian/changelog b/debian/changelog index 705cba43..9fd4a186 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +moose (3.3.0.3ubuntu1) experimental; urgency=medium + + * version bumped + + -- Dilawar Singh Fri, 13 Mar 2020 11:21:25 +0530 + moose (3.2.0.3ubuntu1) experimental; urgency=medium * Version bumped. diff --git a/debian/rules b/debian/rules index db2935ad..ab59ec1b 100755 --- a/debian/rules +++ b/debian/rules @@ -1,15 +1,15 @@ #!/usr/bin/make -f -export MAKEOPTS=-j$(bash nproc) +export MAKEOPTS=-j$(shell nproc) export DH_VERBOSE=1 %: - dh "$@" --buildsystem=cmake --with-python3 + dh "$@" --buildsystem=cmake --with-python2 override_dh_auto_configure: dh_auto_configure -- -DCMAKE_SKIP_RPATH=ON override_dh_python2: dh_numpy - dh_python3 + dh_python2 From e498ea7f74198cf41693ecc86bbe042d0852949c Mon Sep 17 00:00:00 2001 From: Dilawar Singh Date: Fri, 13 Mar 2020 21:03:10 +0530 Subject: [PATCH 6/7] python3 dependencies are also included on travis. --- .travis_prepare_linux.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis_prepare_linux.sh b/.travis_prepare_linux.sh index f756dfd6..2636c976 100755 --- a/.travis_prepare_linux.sh +++ b/.travis_prepare_linux.sh @@ -3,6 +3,7 @@ sudo apt-get update -qq sudo apt-get -y install libxml2-dev libbz2-dev wget sudo apt-get -y install libhdf5-serial-dev sudo apt-get -y install python-numpy python-setuptools python-networkx python-pip +sudo apt-get -y install python3-numpy python3-setuptools python3-matplotlib sudo apt-get -y install cmake cdbs sudo apt-get -y install libgsl0-dev sudo apt-get -y install python-suds python-matplotlib From eec29639a3e2bd93eb7a53be951df27ecd09d312 Mon Sep 17 00:00:00 2001 From: Dilawar Singh Date: Fri, 13 Mar 2020 21:28:22 +0530 Subject: [PATCH 7/7] If python3 is default then run the test using python3. --- .travis_build_linux.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis_build_linux.sh b/.travis_build_linux.sh index 4906319c..d42fb3cb 100755 --- a/.travis_build_linux.sh +++ b/.travis_build_linux.sh @@ -10,5 +10,5 @@ if [ -n "$TRAVIS" ]; then echo "We are on travis" sudo dpkg -i ../*.deb sudo apt-get install -f - python -c 'import moose; print(moose.__file__); print(moose.__version__)' + python -c 'import moose; print(moose.about())' || python3 -c 'import moose; print(moose.about())' fi